diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fe1f7ed --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Батникам нужны CRLF: с LF cmd.exe способен повести себя странно — +# например, оборвать последнюю строку или неверно разобрать блок в скобках. +*.cmd text eol=crlf +*.bat text eol=crlf + +# Остальному текстовому — LF в репозитории, нормализация при выгрузке. +*.mjs text +*.md text +*.html text +*.json text +.gitignore text diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..50e8d7b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Alex + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index d5048c6..820d124 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,168 @@ # deepwork -Цикл с инструментами поверх сервиса [deepseek-api](https://git.08h.ru/alex/deepseek-api). +**DeepSeek, который сам читает вашу папку с кодом.** -DeepSeek через веб-чат видит только то, что положили ему в вопрос. Здесь у него -появляется обратное направление: он возвращает блок-запрос, программа его -исполняет и досылает результат следующим сообщением в тот же чат. Обычный -агентский цикл, только транспорт — текст. +Обычный веб-чат видит только то, что вы вставили в вопрос. Спросишь «почему +падает вот эта функция» — и в ответ получишь три догадки, потому что остального +кода он не видел. + +Здесь у него появляется обратное направление. DeepSeek отвечает не текстом, +а **запросом**: «пришлите мне файл `server.js`», «покажите, где встречается +`waitForAnswer`». Программа исполняет запрос, досылает данные, и так по кругу, +пока он не соберёт всё нужное и не ответит по существу. + +``` +вы: "почему падает загрузка?" + │ + ▼ + DeepSeek ──► "=== NEED: upload.js ===" + │ │ + │ программа читает файл и досылает + │ │ + ▼ ▼ + DeepSeek ──► "=== FIND: parseBody ===" + │ │ + ▼ ▼ + DeepSeek ──► ответ по существу + исправленный файл +``` + +Читает он только вашу папку и только на чтение. Правки возвращает файлами, +которые вы записываете нажатием кнопки — или не записываете. + +--- + +## Оглавление + +1. [Что понадобится](#что-понадобится) +2. [Установка по шагам](#установка-по-шагам) +3. [Как пользоваться](#как-пользоваться) +4. [Что он умеет запрашивать](#что-он-умеет-запрашивать) +5. [Правки файлов](#правки-файлов) +6. [Настройка](#настройка) +7. [Если не работает](#если-не-работает) +8. [Безопасность](#безопасность) +9. [Как это устроено внутри](#как-это-устроено-внутри) +10. [Что проверено вживую](#что-проверено-вживую) + +--- + +## Что понадобится + +| Что | Зачем | Как проверить | +|---|---|---| +| **Windows** | скрипт запуска написан под неё | — | +| **Node.js 22 или новее** | на нём написана программа | `node --version` → `v22.…` и выше | +| **Сервис `deepseek-api`** | через него идёт разговор с DeepSeek | см. шаг 1 | + +Node.js, если его нет, ставится с [nodejs.org](https://nodejs.org) — берите +версию LTS. После установки **закройте и откройте заново** командную строку, +иначе `node` в ней не найдётся. + +--- + +## Установка по шагам + +### Шаг 1. Поднять deepseek-api + +У веб-версии DeepSeek нет API — только вкладка в браузере. Разговором с ней +занимается отдельная программа +[deepseek-api](https://git.08h.ru/alex/deepseek-api): она держит вкладку +и отдаёт наружу обычный HTTP. + +Поставьте и запустите её по инструкции в её README — это отдельные пять шагов, +включая вход в аккаунт DeepSeek. Возвращайтесь сюда, когда заработает. + +> **Проверка:** +> ```cmd +> curl http://localhost:11500/api/tags +> ``` +> должен вернуть список из трёх «моделей». Окно `deepseek-api` при этом +> остаётся открытым — пока оно живо, работает и сервис. + +### Шаг 2. Скачать deepwork + +```cmd +cd C:\#Projects +git clone https://git.08h.ru/alex/deepwork.git +``` + +Без git — скачайте ZIP с той же страницы и распакуйте. Папка может лежать где +угодно; рядом с чем-то конкретным её класть не нужно. + +> **Проверка:** +> ```cmd +> cd C:\#Projects\deepwork +> node deepwork.mjs --selftest +> ``` +> Ответ `самопроверка пройдена`. Ничего никуда не отправляется. + +### Шаг 3. Проверить связку + +```cmd +node deepwork.mjs --check +``` + +Три возможных ответа: + +| Что видно | Что это значит | +|---|---| +| `готов: браузер поднят, вкладка DeepSeek открыта` | всё на месте, можно работать | +| `не готов (HTTP 503)` | сервис жив, но браузер ещё не поднят — встанет сам на первом вопросе | +| `не отвечает: …` | `deepseek-api` не запущен, вернитесь к шагу 1 | + +**Готово.** Настраивать больше нечего: адрес `http://localhost:11500` вшит +как значение по умолчанию. + +--- ## Как пользоваться -Обычный путь — **пульт**: бросить папку проекта на `start-deepwork.cmd`. -Откроется страница: файлы галочками, поле вопроса, ход работы построчно, -кнопка «Записать» у каждого пришедшего файла. +### Способ 1: пульт (обычный путь) -Пульт открывается в браузере ПО УМОЛЧАНИЮ, а не в отладочном: там он занял бы -вкладку, и мост перестал бы видеть DeepSeek. Порт 8787 — рядом с пультом -orchestro (8777), оба могут работать разом. +**Перетащите папку своего проекта мышкой на файл `start-deepwork.cmd`.** -Тот же цикл из консоли: +Откроется страница в браузере: -``` -cd c:\мой\проект -node c:\#Projects\deepwork\deepwork.mjs "вопрос" --files a.js,b.js --apply -node c:\#Projects\deepwork\deepwork.mjs ui тот же пульт вручную +- слева файлы папки — отметьте галочками те, что точно нужны (можно ни одного); +- поле вопроса; +- ход работы построчно: видно, что DeepSeek запросил и сколько это заняло; +- у каждого пришедшего файла кнопка «Записать». + +Пульт открывается в браузере **по умолчанию**, а не в том, которым управляет +`deepseek-api`: иначе он занял бы там вкладку, и вкладка с чатом потерялась бы. +Порт 8787. + +Остановить — `Ctrl+C` в чёрном окне. + +### Способ 2: командная строка + +Работает в **текущей** папке: её читает, в неё же пишет правки. + +```cmd +cd C:\мой\проект +node C:\#Projects\deepwork\deepwork.mjs "почему падает загрузка файла?" ``` -Работает в текущей папке: её файлы показывает, в неё же пишет правки. +Полезные флаги: -## Инструменты +| Флаг | Что делает | +|---|---| +| `--files a.js,b.js` | положить эти файлы в вопрос сразу | +| `--steps 6` | сколько кругов позволить (по умолчанию 4) | +| `--apply` | записать пришедшие файлы на диск (без него только покажет) | +| `--chat search` | режим с поиском в интернете вместо обычного | +| `--check` | проверить связку и выйти | +| `--selftest` | внутренние проверки, ничего не отправляя | + +### Чего ожидать по времени + +Один круг — 7–15 секунд. Обычная задача укладывается в два-три круга, то есть +полминуты. Если DeepSeek запросил много файлов, вопрос на следующем круге +вырастает до десятков килобайт — это нормально. + +--- + +## Что он умеет запрашивать Только чтение и только внутри текущей папки: @@ -37,147 +172,220 @@ node c:\#Projects\deepwork\deepwork.mjs ui тот же пульт вру | `=== LIST: **/*.mjs ===` | список файлов по маске | | `=== FIND: текст ===` | где встречается текст, с номерами строк | -Запуска команд (`RUN`) нет намеренно: исполнять строки из ответа, пришедшего -из интернета, без белого списка и подтверждения нельзя. +**Запуска команд (`RUN`) нет, и не будет.** Исполнять строки, пришедшие +из интернета, без белого списка и подтверждения нельзя — а белого списка, +который был бы и полезен, и безопасен, придумать не вышло. -Лимиты на результат шага: `NEED` — 200 000 символов суммарно, `FIND` — 100 -попаданий, `LIST` — 300 путей. Обрезанное помечается прямо в тексте. +Лимиты на один круг: `NEED` — 200 000 символов суммарно, `FIND` — 100 +попаданий, `LIST` — 300 путей. Обрезанное помечается прямо в тексте, чтобы +DeepSeek видел, что данные неполные. -## Как устроено +Цикл останавливается, когда запросов в ответе больше нет, когда кончились +круги или когда пришёл тот же самый запрос второй раз подряд — это петля, +данные ему уже присылали. -У веб-версии DeepSeek нет API — только вкладка в браузере. Разговором с ней -занимается отдельный сервис `deepseek-api`, а нам показывает протокол Ollama. -Здесь про браузер не знают вовсе: обычный `POST /api/chat`. +--- -**Разговор помним мы, а не DeepSeek.** Сервис без памяти: каждый запрос он -кладёт в чат целиком, затирая прошлый. Поэтому стенограмма растёт здесь — -`growTranscript` подклеивает к отправленному тексту прошлый ответ модели -(между метками `=== ТВОЙ ПРЕДЫДУЩИЙ ОТВЕТ ===` и `=== END ===`) и результаты -запросов, и следующим шагом уезжает всё сразу. +## Правки файлов -Раньше эту роль играл флаг `--new` у моста, и помнил всё сам чат. Своя -стенограмма надёжнее: видно в одном месте, что именно уедет модели, а чужой -потребитель, вклинившийся между нашими шагами, ничего не портит — мы всё -приносим заново. Плата — вопрос растёт на длину прошлого ответа; при `steps: 4` -это единицы килобайт против 22 КБ первого сообщения. +Исправленный код DeepSeek возвращает блоками: -Цикл останавливается, когда запросов в ответе нет, когда кончились шаги или -когда пришёл тот же самый запрос второй раз подряд (петля). +``` +=== FILE: src/upload.js === +``` +...содержимое целиком... +``` +=== END FILE === +``` + +Записываются они **только по вашей команде** — кнопкой «Записать» в пульте +или флагом `--apply` в консоли. Без этого программа просто перечислит, что +пришло. + +**Прежняя версия не пропадает:** перед записью она уезжает в папку `backup/` +внутри проекта. Файлы вне рабочей папки не пишутся вовсе — путь проверяется. + +--- ## Настройка -`config.json` (в репозиторий не попадает, образец — `config.example.json`): +Нужна редко. `config.json` рядом с программой (в репозиторий не попадает, +образец — `config.example.json`): ```json -{ "deepseekHost": "http://localhost:11500", "deepseekModel": "deepseek:think", "steps": 4 } +{ + "deepseekHost": "http://localhost:11500", + "deepseekModel": "deepseek:think", + "steps": 4, + "timeout": 240 +} ``` -Без файла берётся `http://localhost:11500`. +| Ключ | По умолчанию | Смысл | +|---|---|---| +| `deepseekHost` | `http://localhost:11500` | адрес сервиса `deepseek-api` | +| `deepseekModel` | `deepseek:think` | режим чата: `think`, `search` или `vision` | +| `steps` | `4` | сколько кругов позволить | +| `timeout` | `240` | секунд на один круг (сверх этого сервису дают ещё две минуты на очередь) | +| `uiPort` | `8787` | порт пульта | -## Проверка +Без файла всё работает на значениях по умолчанию. А вот **битый** `config.json` +не молчит: программа скажет об ошибке, а не откатится тихо к умолчаниям — +иначе правка в настройках не действует, и понять почему невозможно. -``` -node deepwork.mjs --selftest внутренние проверки, ничего не отправляют -node deepwork.mjs --check сервис на месте, вкладка жива -``` +--- -`--check` различает три состояния: сервис отвечает и браузер поднят; сервис -жив, но браузера ещё нет (встанет на первом же вопросе); сервис не запущен. +## Если не работает -Запускается сервис своим `start.cmd` в папке `deepseek-api` — браузер он -поднимает сам. +| Что видно | В чём дело | Что делать | +|---|---|---| +| `deepseek-api не отвечает по адресу …` | сервис не запущен | Запустите `start.cmd` в папке `deepseek-api` | +| `--check` говорит `не готов (HTTP 503)` | сервис жив, браузера ещё нет | Ничего: браузер встанет на первом же вопросе | +| `deepseek-api ответил 500` | что-то со вкладкой | `curl http://localhost:11500/api/probe` покажет, что там видно | +| **Ответ пришёл обрезанным**, код оборван на середине | окно браузера свёрнуто | Разверните его. Свёрнутое окно Windows не отрисовывает, а DeepSeek рисует блоки кода лениво — см. [ниже](#обрезанные-ответы-причина-найдена) | +| `шаг 1: запросов нет, готово`, а ответ — догадки | DeepSeek поленился спросить и придумал | Спросите конкретнее либо дайте файл сразу через `--files`. Так бывает; напоминание в конце вопроса помогает, но не всегда | +| `тот же запрос повторно — петля, выхожу` | он не принял присланные данные | Обычно значит, что запрошенного файла нет или он пуст. Посмотрите журнал шагов | +| `шаги кончились, а запросы ещё идут` | задача крупнее четырёх кругов | `--steps 6`, но сначала подумайте, не проще ли разбить вопрос | +| `DeepSeek занят: «Server is busy»` | лимиты на стороне DeepSeek | Подождите минуту | +| `node не является внутренней или внешней командой` | Node не установлен или консоль открыта до установки | Поставьте Node, **закройте и откройте заново** консоль | +| Чаты в DeepSeek пропадают сами | тот же профиль браузера использует другая программа | Дайте `deepseek-api` отдельный профиль | -## Переезд на deepseek-api (26.08.2026) +--- -Транспорт сменился: был дочерний процесс `ask.mjs` из `ollama_orchestro` -с обменом через временные файлы, стал `POST /api/chat` к сервису -`deepseek-api`. Заодно ушли временные файлы шагов (и флаг `--keep-temp`), -проверка существования моста и запуск браузера — всё это теперь не наша забота. +## Безопасность -Память шагов переехала из чата DeepSeek в `growTranscript` (см. «Как устроено»). -Проверено живым прогоном: шаг 1 — 2094 символа, ответ `NEED: deepwork.mjs`; -шаг 2 — 28 447 символов стенограммы, ответ дословно верный и по вопросу -из ПЕРВОГО сообщения. Два шага за 17 с. +- **Ваш код уходит на серверы DeepSeek.** Не только присланные файлы: он сам + запрашивает то, что считает нужным, из всей рабочей папки. Для закрытых + проектов это не годится. +- **Ключей и паролей в папке быть не должно.** `.env`, `config.json` с токенами, + приватные ключи — всё это он может запросить, и это уедет наружу. Убирайте + такое из рабочей папки заранее. +- **Правки не применяются сами.** Только кнопкой или флагом `--apply`, + и прежняя версия всегда сохраняется в `backup/`. +- **За пределы рабочей папки программа не пишет** и не читает: путь + проверяется, `..` не проходит. +- **Пульт слушает только этот компьютер** (`127.0.0.1`), из сети к нему + не подключиться. -## Что проверено +--- -- `--selftest`: разбор запросов, отказ пути за пределы папки, маски `*` и `**`, - снятие тройных кавычек и подписи языка. Строка вида `=== NEED: … ===` - **внутри** блока `=== FILE: ===` за запрос не принимается — иначе правка - файла с описанием формата запускала бы запрос сама. -- Цикл целиком на заглушке вместо моста: приставка едет в первом сообщении, - второй вызов уходит с `--new`, результаты `NEED` и `FIND` доезжают, - отступы в записанном файле сохраняются, прежняя версия уходит в `backup/`. -- Пропавший файл в `NEED` возвращает «файла нет» и цикл не роняет. -- `--steps 1` отдаёт ответ с пометкой «шаги кончились», а не зависает. -- Битый `config.json` — понятная ошибка, а не молчаливый откат к умолчаниям. +## Как это устроено внутри -### Живые прогоны на DeepSeek, 11.08.2026 +### Разговор помним мы, а не DeepSeek -Задача одна и та же: из папки `ollama_orchestro` спросить, где решается, что -ответ дописан до конца, дав в вопросе **только** `ui.html` — то есть заведомо -не тот файл. Правильный ответ (`waitForAnswer` в `ask.mjs`) достижим только -через инструменты. +Сервис `deepseek-api` **без памяти**: каждый запрос он кладёт в чат целиком, +затирая прошлый. Поэтому стенограмму ведёт `deepwork` — функция +`growTranscript` подклеивает к отправленному тексту прошлый ответ модели +(между метками `=== ТВОЙ ПРЕДЫДУЩИЙ ОТВЕТ ===` и `=== END ===`) и результаты +запросов, и следующим кругом уезжает всё сразу. -| Прогон | Шагов | Что вышло | +Раньше память держал сам чат DeepSeek. Своя стенограмма надёжнее: видно +в одном месте, что именно уедет модели, а чужая программа, вклинившаяся между +нашими кругами, ничего не портит — мы всё приносим заново. Плата — вопрос +растёт на длину прошлого ответа; при четырёх кругах это единицы килобайт +против 22 КБ первого сообщения. + +### Что уезжает в первом сообщении + +1. Приставка из `agent-prompt.md` — кто он и какие блоки может вернуть. +2. **Дерево рабочей папки.** Без него первый живой прогон ушёл на угадывание + имён файлов, см. замеры ниже. +3. Файлы, отмеченные галочками (или переданные через `--files`). +4. **Напоминание про инструменты — вплотную к вопросу.** Не в начале: между + приставкой и вопросом ложатся килобайты файлов, и инструкция теряется. +5. Сам вопрос. + +### Файлы + +| Файл | Что в нём | +|---|---| +| `deepwork.mjs` | всё: цикл, инструменты, разбор ответов, пульт | +| `agent-prompt.md` | приставка к первому сообщению | +| `ui.html` | страница пульта | +| `config.json` | настройки (не в репозитории) | +| `start-deepwork.cmd` | запуск пульта перетаскиванием папки | + +Зависимостей нет — только то, что есть в Node 22. + +--- + +## Что проверено вживую + +### Внутренние проверки (`--selftest`) + +Разбор запросов, отказ пути за пределы папки, маски `*` и `**`, снятие тройных +кавычек и подписи языка. Строка вида `=== NEED: … ===` **внутри** блока +`=== FILE: ===` за запрос не принимается — иначе правка файла с описанием +формата запускала бы запрос сама. Пропавший файл в `NEED` возвращает «файла +нет» и цикл не роняет. `--steps 1` отдаёт ответ с пометкой «шаги кончились», +а не зависает. + +### Из чего выросли два правила, 11.08.2026 + +Задача одна и та же: спросить, где решается, что ответ дописан до конца, дав +в вопросе **заведомо не тот файл**. Правильный ответ достижим только через +инструменты. + +| Прогон | Кругов | Что вышло | |---|---|---| | 1. приставка только в начале сообщения | 1 | **запросов нет.** «Точный код в серверном файле» и три догадки | -| 2. + напоминание вплотную к вопросу | 4 | нашёл, но 2 круга ушли на угадывание имён файлов | -| 3. + дерево папки в первом сообщении | **2** | запросил `ask.mjs` сразу, ответил по существу | - -Два вывода, оба стоили живого прогона: +| 2. + напоминание вплотную к вопросу | 4 | нашёл, но два круга ушли на угадывание имён файлов | +| 3. + дерево папки в первом сообщении | **2** | запросил нужный файл сразу, ответил по существу | - **Инструкция в начале сообщения не работает.** Между приставкой и вопросом - легли 22 КБ файла, и DeepSeek инструменты просто не заметил. Помогло - дословное повторение перед самим вопросом (`TAIL_REMINDER`). -- **Дерево папки надо давать сразу.** Без него DeepSeek угадывал имена - (`server.js`, `bridge.js` — таких в проекте нет), потом просил `LIST *.js` - (проект на `.mjs`, пусто), потом `LIST **/*`. Дерево — 600 символов против - двух кругов по минуте. + легли 22 КБ файла, и DeepSeek инструменты просто не заметил. +- **Дерево папки надо давать сразу.** Без него он угадывал имена (`server.js`, + `bridge.js` — таких в проекте нет), потом просил `LIST *.js` (проект + на `.mjs`, пусто), потом `LIST **/*`. Дерево — 600 символов против двух + кругов по минуте. ### Пульт, 11.08.2026 -Сквозной прогон через страницу: вопрос без единого приложенного файла — -«какая функция решает, что ответ дописан?». 36 секунд, три шага. DeepSeek -запросил пятью блоками `FIND` сразу (`waitForAnswer`, `streaming`, `done`, -`stop_reason`, `finish_reason`), затем `NEED: ask.mjs`, и ответил точно: -`waitForAnswer`, строка 675. Журнал шагов обновлялся на странице по ходу. +Вопрос без единого приложенного файла — «какая функция решает, что ответ +дописан?». 36 секунд, три круга: пять блоков `FIND` сразу, затем `NEED` +на найденный файл, и точный ответ с номером строки. Журнал кругов обновлялся +на странице по ходу. -## Обрезанные ответы: причина найдена и устранена в мосте (11.08.2026) +### Обрезанные ответы: причина найдена -В третьем прогоне ответ оборвался посреди блока кода на `// Бы`. Оказалось, -это не «конец определён раньше времени» и не кнопка `Continue`. +Один из прогонов оборвался посреди блока кода на `// Бы`. Это не «конец +определён раньше времени» и не кнопка `Continue`. -**Браузер работал в фоне.** У неактивного окна страница не отрисовывается, а -DeepSeek рисует блоки кода лениво: пока блок не нарисован, в DOM от него +**Браузер работал в фоне.** У неактивного окна страница не отрисовывается, +а DeepSeek рисует блоки кода лениво: пока блок не нарисован, в DOM от него лежат первые две строки, а остального нет вовсе — его не достать ни -`innerText`, ни `textContent`. Прокрутка не помогает (проверено проходом по -всему ответу шагами: ни одного лишнего символа). +`innerText`, ни `textContent`. Прокрутка не помогает. -Помогает единственное — заставить браузер отрисовать страницу, и через CDP -это делает `Page.captureScreenshot`. Замеры на живых ответах: +Помогает единственное — заставить браузер отрисовать страницу. Замеры на живых +ответах: | | до отрисовки | после | |---|---|---| | ответ про TaskQueue | 2068 | 24 362 | | ответ про EventBus | 3136 | 30 817 | -| ответ про Router (уже с правкой) | 258 | **32 045** | +| ответ про Router | 258 | **32 045** | -Правка в `ollama_orchestro/ask.mjs`: `revealAnswer()` перед съёмом текста -делает дешёвый скриншот (jpeg, качество 1) и перечитывает ответ, до трёх раз, -пока текст растёт. Картинка выбрасывается. +Вторая причина обрезания — кнопка **Continue**: DeepSeek режет длинный ответ +по своему лимиту и предлагает дописать, а генерация при этом честно +завершается. Сквозная проверка после починки — ответ на 47 414 символов +с целыми кодом и тестами. -Вдобавок `browser-launch.ps1` запускает браузер развёрнутым и с запретом -фонового режима (`--disable-backgrounding-occluded-windows`, -`--disable-renderer-backgrounding`, `--disable-background-timer-throttling`, -`--disable-features=CalculateNativeWinOcclusion`). Это не замена скриншоту: -свёрнутое окно Windows не рисует вообще. +Обе поломки лечатся в `deepseek-api`, а не здесь: отрисовка и кнопка `Continue` +живут в его `browser.mjs`. Отсюда остаётся одно требование — **не сворачивать +окно браузера**. -Вторая причина обрезания, найденная там же, — кнопка **Continue**: DeepSeek -режет длинный ответ по своему лимиту и предлагает дописать, а генерация при -этом честно завершается. Теперь `waitForAnswer` жмёт её и ждёт дальше; -продолжение уходит в тот же блок ответа. Сквозная проверка — ответ на 47 414 -символов с целыми кодом и тестами. +### Переезд на deepseek-api, 26.08.2026 -Обе правки в `ollama_orchestro`, deepwork получает их даром — мост вызывается -подпроцессом. +Раньше `deepwork` вызывал мост `ask.mjs` из проекта DeepShim дочерним процессом +и гонял текст через временные файлы. Теперь это `POST /api/chat`, а память +кругов переехала из чата в стенограмму (см. выше). + +Проверено живым прогоном: круг 1 — 2094 символа, ответ `NEED: deepwork.mjs`; +круг 2 — 28 447 символов стенограммы, ответ дословно верный и по вопросу +из **первого** сообщения. Два круга за 17 с. + +--- + +## Лицензия + +MIT. diff --git a/deepwork.mjs b/deepwork.mjs index 79a5b54..cc713f7 100644 --- a/deepwork.mjs +++ b/deepwork.mjs @@ -44,9 +44,9 @@ deepwork — задать DeepSeek вопрос и дать ему дочита --steps N сколько кругов позволить (по умолчанию 4) --apply применить пришедшие блоки === FILE: === на диск (прежняя версия уезжает в backup/) - --chat роль think (по умолчанию) | search - --timeout сек максимум бездействия страницы, передаётся мосту - --check проверить, что мост на месте и вкладка жива + --chat роль think (по умолчанию) | search | vision + --timeout сек сколько секунд ждать ответа на один шаг + --check проверить, что сервис на месте и вкладка жива --selftest прогнать внутренние проверки, ничего не отправляя Инструменты, которые может вернуть DeepSeek (только чтение, только внутри diff --git a/start-deepwork.cmd b/start-deepwork.cmd index f5553d2..fbf09a4 100644 --- a/start-deepwork.cmd +++ b/start-deepwork.cmd @@ -5,6 +5,7 @@ REM ============================================================ REM deepwork web console. Drag and drop a project folder onto REM this file: DeepSeek gets tools (NEED / LIST / FIND) and can REM read that folder himself, step by step. +REM Needs the deepseek-api service running (its own start.cmd). REM ASCII only on purpose - cmd.exe mangles UTF-8 Cyrillic. REM ============================================================ @@ -43,10 +44,11 @@ if errorlevel 1 ( ) echo [OK] Node.js found -powershell -NoProfile -Command "try { Invoke-RestMethod -Uri 'http://127.0.0.1:9333/json/version' -TimeoutSec 2 | Out-Null; exit 0 } catch { exit 1 }" >nul 2>&1 +powershell -NoProfile -Command "try { Invoke-RestMethod -Uri 'http://localhost:11500/api/tags' -TimeoutSec 3 | Out-Null; exit 0 } catch { exit 1 }" >nul 2>&1 if errorlevel 1 ( - echo [WARN] Bridge is NOT available on port 9333. - echo Run start-browser.cmd in ollama_orchestro, then log in. + echo [WARN] deepseek-api is NOT ready on port 11500. + echo Run start.cmd in the deepseek-api folder - it starts the + echo browser by itself. Log in to DeepSeek in the window it opens. echo The console will start anyway and show the same warning. echo. ) @@ -54,7 +56,8 @@ if errorlevel 1 ( cd /d "%~1" echo. -echo Open the printed address in your DEFAULT browser, not the debug one. +echo Open the printed address in your DEFAULT browser, not the one +echo that deepseek-api drives. echo Ctrl+C here stops it. echo. node "%DW_DIR%deepwork.mjs" ui