# deepwork **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` вшит как значение по умолчанию. --- ## Как пользоваться ### Способ 1: пульт (обычный путь) **Перетащите папку своего проекта мышкой на файл `start-deepwork.cmd`.** Откроется страница в браузере: - слева файлы папки — отметьте галочками те, что точно нужны (можно ни одного); - поле вопроса; - ход работы построчно: видно, что 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 запросил много файлов, вопрос на следующем круге вырастает до десятков килобайт — это нормально. --- ## Что он умеет запрашивать Только чтение и только внутри текущей папки: | Блок в ответе | Что делает | |---|---| | `=== NEED: путь, путь ===` | прислать файлы целиком | | `=== LIST: **/*.mjs ===` | список файлов по маске | | `=== FIND: текст ===` | где встречается текст, с номерами строк | **Запуска команд (`RUN`) нет, и не будет.** Исполнять строки, пришедшие из интернета, без белого списка и подтверждения нельзя — а белого списка, который был бы и полезен, и безопасен, придумать не вышло. Лимиты на один круг: `NEED` — 200 000 символов суммарно, `FIND` — 100 попаданий, `LIST` — 300 путей. Обрезанное помечается прямо в тексте, чтобы DeepSeek видел, что данные неполные. Цикл останавливается, когда запросов в ответе больше нет, когда кончились круги или когда пришёл тот же самый запрос второй раз подряд — это петля, данные ему уже присылали. --- ## Правки файлов Исправленный код DeepSeek возвращает блоками: ``` === FILE: src/upload.js === ``` ...содержимое целиком... ``` === END FILE === ``` Записываются они **только по вашей команде** — кнопкой «Записать» в пульте или флагом `--apply` в консоли. Без этого программа просто перечислит, что пришло. **Прежняя версия не пропадает:** перед записью она уезжает в папку `backup/` внутри проекта. Файлы вне рабочей папки не пишутся вовсе — путь проверяется. --- ## Настройка Нужна редко. `config.json` рядом с программой (в репозиторий не попадает, образец — `config.example.json`): ```json { "deepseekHost": "http://localhost:11500", "deepseekModel": "deepseek:think", "steps": 4, "timeout": 240 } ``` | Ключ | По умолчанию | Смысл | |---|---|---| | `deepseekHost` | `http://localhost:11500` | адрес сервиса `deepseek-api` | | `deepseekModel` | `deepseek:think` | режим чата: `think`, `search` или `vision` | | `steps` | `4` | сколько кругов позволить | | `timeout` | `240` | секунд на один круг (сверх этого сервису дают ещё две минуты на очередь) | | `uiPort` | `8787` | порт пульта | Без файла всё работает на значениях по умолчанию. А вот **битый** `config.json` не молчит: программа скажет об ошибке, а не откатится тихо к умолчаниям — иначе правка в настройках не действует, и понять почему невозможно. --- ## Если не работает | Что видно | В чём дело | Что делать | |---|---|---| | `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.** Не только присланные файлы: он сам запрашивает то, что считает нужным, из всей рабочей папки. Для закрытых проектов это не годится. - **Ключей и паролей в папке быть не должно.** `.env`, `config.json` с токенами, приватные ключи — всё это он может запросить, и это уедет наружу. Убирайте такое из рабочей папки заранее. - **Правки не применяются сами.** Только кнопкой или флагом `--apply`, и прежняя версия всегда сохраняется в `backup/`. - **За пределы рабочей папки программа не пишет** и не читает: путь проверяется, `..` не проходит. - **Пульт слушает только этот компьютер** (`127.0.0.1`), из сети к нему не подключиться. --- ## Как это устроено внутри ### Разговор помним мы, а не DeepSeek Сервис `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 | нашёл, но два круга ушли на угадывание имён файлов | | 3. + дерево папки в первом сообщении | **2** | запросил нужный файл сразу, ответил по существу | - **Инструкция в начале сообщения не работает.** Между приставкой и вопросом легли 22 КБ файла, и DeepSeek инструменты просто не заметил. - **Дерево папки надо давать сразу.** Без него он угадывал имена (`server.js`, `bridge.js` — таких в проекте нет), потом просил `LIST *.js` (проект на `.mjs`, пусто), потом `LIST **/*`. Дерево — 600 символов против двух кругов по минуте. ### Пульт, 11.08.2026 Вопрос без единого приложенного файла — «какая функция решает, что ответ дописан?». 36 секунд, три круга: пять блоков `FIND` сразу, затем `NEED` на найденный файл, и точный ответ с номером строки. Журнал кругов обновлялся на странице по ходу. ### Обрезанные ответы: причина найдена Один из прогонов оборвался посреди блока кода на `// Бы`. Это не «конец определён раньше времени» и не кнопка `Continue`. **Браузер работал в фоне.** У неактивного окна страница не отрисовывается, а DeepSeek рисует блоки кода лениво: пока блок не нарисован, в DOM от него лежат первые две строки, а остального нет вовсе — его не достать ни `innerText`, ни `textContent`. Прокрутка не помогает. Помогает единственное — заставить браузер отрисовать страницу. Замеры на живых ответах: | | до отрисовки | после | |---|---|---| | ответ про TaskQueue | 2068 | 24 362 | | ответ про EventBus | 3136 | 30 817 | | ответ про Router | 258 | **32 045** | Вторая причина обрезания — кнопка **Continue**: DeepSeek режет длинный ответ по своему лимиту и предлагает дописать, а генерация при этом честно завершается. Сквозная проверка после починки — ответ на 47 414 символов с целыми кодом и тестами. Обе поломки лечатся в `deepseek-api`, а не здесь: отрисовка и кнопка `Continue` живут в его `browser.mjs`. Отсюда остаётся одно требование — **не сворачивать окно браузера**. ### Переезд на deepseek-api, 26.08.2026 Раньше `deepwork` вызывал мост `ask.mjs` из проекта DeepShim дочерним процессом и гонял текст через временные файлы. Теперь это `POST /api/chat`, а память кругов переехала из чата в стенограмму (см. выше). Проверено живым прогоном: круг 1 — 2094 символа, ответ `NEED: deepwork.mjs`; круг 2 — 28 447 символов стенограммы, ответ дословно верный и по вопросу из **первого** сообщения. Два круга за 17 с. --- ## Лицензия MIT.