diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 354e17b..e99b2ff 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -85,6 +85,13 @@ jobs:
dist/*.zip
dist/*.blockmap
dist/latest-mac.yml
+ - os: ubuntu-latest
+ command: build:linux:local
+ artifact: Linux-build
+ paths: |
+ dist/*.AppImage
+ dist/*.tar.gz
+ dist/latest-linux.yml
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -139,6 +146,12 @@ jobs:
name: macOS-build
path: artifacts/mac
+ - name: Download Linux artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: Linux-build
+ path: artifacts/linux
+
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
@@ -149,3 +162,4 @@ jobs:
files: |
artifacts/win/*
artifacts/mac/*
+ artifacts/linux/*
diff --git a/.gitignore b/.gitignore
index f180931..c61d0bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,7 +30,10 @@ userData/
# Temp
*.tmp
+.tmp/
temp/
+plan.md
+release.bat
# Project specific
.cuckooCode/
@@ -53,3 +56,5 @@ test/coverage.lcov
# cookie/agents — НЕ игнорируем: агенты проекта должны попадать в git.
# Пользовательские агенты лежат в ~/cookie/agents (вне репозитория).
# Ранее здесь был /cookie/agents — убрано, иначе новые агенты untracked.
+/.cookie/memory
+/.cookie/prompts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76d5c16..b6d74de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,85 +1,57 @@
# Changelog
-## [5.0.9] - 2026-10-26
+## [5.0.10] - 2026-11-01
-### Added
-
-- ⛔ **Уведомление в Telegram при rate-limit DeepSeek (429 / 40029)** — при превышении лимита запросов в Telegram приходит ==КАПС-предупреждение== с просьбой подождать:
- - в main-world перехватчике `token-interceptor-inject.js` в патчах `fetch`/`XHR` ловятся HTTP `429` и бизнес-код `40029` (`IP_ACCESS_RESTRICTED`) в теле ответа;
- - событие уходит через `postMessage({ __cuckoo: "rate-limit" })`, preload слушает с антиспамом 60с;
- - IPC `telegram-rate-limit` → `botsrc.notifyRateLimit()` шлёт сообщение с ожиданием 5–20 минут (учёт `retry-after` при наличии);
- - строки локализации `rateLimit.*` (ru/en) в `botsrc/i18n.js`; в окнах-субагентах уведомление подавляется.
-- 🔄 **Pull-модель получения initial-prompt в окне субагента** — если push потерялся из-за гонки IPC, окно само запрашивает промпт у main:
- - `subagent.js` кэширует combined-промпт по `windowId` и отдаёт через `getInitPrompt()`;
- - новый IPC-хендлер `subagent-get-init-prompt` в `src/main/ipc.js`;
- - в `chat-input.js` окно-субагент через 20с запрашивает промпт, если не получило пушем.
-
-### Changed
-
-- 🪟 **Отправка initial-prompt в субагент стала устойчивее** — повторные отправки в `3с / 8с / 15с`, абсолютный таймаут до 3 минут (было: 1.2с и 60с) в `subagent.js`.
-- ⏳ **Ожидание поля ввода в окне субагента** — увеличено с ~15с до 90с (180 попыток × 500мс), `pendingInitialPrompt` больше не сбрасывается по таймауту (`chat-input.js`).
-- 🛡 **Защита от дубля initial-prompt** — `applyInitialPrompt()` с флагом `_initialPromptApplied` не даёт отправить промпт дважды (push + pull).
-
-### Fixed
-
-- 🐛 **Окно субагента больше не остаётся пустым без промпта** — повторные отправки + pull-запрос закрывают гонку долгой загрузки окна.
-- 🧹 **DSML/XML-мусор в ответе субагента не считается финальным ответом** — проверка вынесена ==выше анализа cuckoo-блоков== (`subagent-watch.js`):
- - детект по `textContent` **и** `innerHTML` (ловит мусор внутри `
` и когда теги съедены markdown-рендером);
- - паттерны: маркеры `DSML`, `invoke/parameter/tool_calls name=` с тегом и без;
- - при обнаружении в чат уходит предупреждение (на английском) использовать `cuckoo`-блок, ответ не завершается; лимит 3 подсказки + антидубль по снапшоту.
-
-## [5.0.8] - 2026-10-22
+Всем привет! 👋 Этот релиз — большой: у нас наконец-то появился **полноценный интерфейс в стиле VS Code**. Ниже — всё, что изменилось, простым языком. 🚀
### Added
-- 💬 **Inline-комментарии к строкам плана с обратной связью ИИ** — в диалоге утверждения плана (`exit_plan_mode`) можно ==комментировать отдельные строки==, не отклоняя план целиком:
- - выделите фрагмент плана → появляется кнопка «💬» → откроется поле ввода под нужным блоком;
- - комментарии помечают строку подсветкой и сохраняются с привязкой к тексту строки;
- - при одобрении комментарии прикладываются к запросу и ==автоматически отправляются== в чат;
- - при отклонении комментарии возвращаются модели как замечания.
-- 📝 **Панель промптов проекта** — сохранённые промпты в `.cookie/prompts/*.md`:
- - кнопка «Промпты» в оверлее: создать / изменить / удалить и вставить текст в поле ввода;
- - хранилище `prompts-store.js` + IPC `prompts-list` / `prompts-save` / `prompts-delete`.
-- 🤖 **Команда `/prompts` в Telegram-боте** — список с кнопками «Вставить» / «Удалить» и «Создать» с пошаговым вводом; локализация ru/en, команда в `/help` и меню.
-- 📜 **Система правил проекта `.cookie/rules.md`** — инструмент `readrules()` и гейт `rules-gate.js`: до принятия правил разрешены только `read` / `read_lines` / `file_read` / `memory_read` / `readrules`; нет файла — нет блокировки; субагенты без гейта.
-- 🌍 **Глобальные Skill** — скиллы ищутся в `/skills/` и `/.cuckoo/skills/`; глобальный перекрывает проектный.
+- 🖥 **Новый Shell-интерфейс в стиле VS Code** — встречайте ==полностью новый UI==, собранный из partials и бандла React/TS:
+ - аккуратная модульная структура в `src/ui/shell/` (`index.html` с ``, partials для toolbar, activity bar, status bar, модалок и страниц, а также стили `base/components/pages/dsh-tokens`);
+ - activity bar для переключения страниц, сворачиваемая боковая панель и status bar;
+ - страницы на любой вкус: **Files, Git, Settings, Agents, MCP, Skills, Snippets, Workspaces, Conversations, Token, About**;
+ - встроенный **Monaco Editor** — тот самый редактор из VS Code 🎉 (вендоринг в `src/ui/vendor/monaco`);
+ - темы (`theme-presenter`), фоны, шрифты и даже «питомцы» — всё настраивается в настройках.
+- 🧩 **Много-много IPC-хендлеров для Shell** в `src/main/shell-ipc.js` (`shell-*`) — теперь приложение умеет:
+ - навигацию и историю окна (`shell-navigate/back/forward/reload/home`), а также minimize/maximize/close/is-maximized;
+ - работать с проектом: выбор каталога, `shell-init-project`, дерево файлов, чтение файла, dir-info;
+ - управлять сессиями: список всех сессий, архивирование, переименование;
+ - настройки: `get/save/reset-settings`, auto-compact и триггер compact;
+ - сниппеты, skills, агентов, MCP-серверы;
+ - профили и провайдеры, web-сессии;
+ - темы, фоны, шрифты, «питомцев», логи, апдейты и внешние ссылки.
+- 🐙 **Git прямо из приложения** — новый модуль `src/main/git-gitops.js` (вдохновлён git-расширением VS Code) и страница **Git** (`git-react.tsx`):
+ - `getRemotes`, `getBranchStatus` (upstream, ahead/behind), `commitAll`, `push`, `pull`, `fetchRemote`, `publish`, `sync`;
+ - все команды запускаются через `execFile("git", args)` в каталоге проекта с буфером 8 МБ.
+- ✏️ **Редактирование кода прямо в Monaco-превью** — страница Files (`files-react.tsx`) и `preview-monaco.ts`:
+ - открывай файл в Monaco, редактируй и сохраняй через IPC;
+ - `getMonacoValue()` помогает забрать содержимое из редактора;
+ - подсветка расширений, иконки папок/файлов и поиск по дереву.
+- 🔔 **Telegram-алерты синхронизируются с процессами** (`0544956`):
+ - долгие процессы трекаются по **PID**: если убить процесс с ПК (в том числе `kill-all`), кнопка «убить» из сообщения в Telegram исчезает;
+ - добавили ru/en-сообщения «остановлено с ПК» в `botsrc/i18n.js`, логика — в `process-manager.js` и `botsrc/index.js`.
### Changed
-- 🗂 **Проектная память переехала в `.cookie/memory/`** — `/.cookie/memory/ProjectMemory.md` (`memory-store.js`, `MemoryTool.js`, README ru/en).
-- 🪟 **Выбор git-ветки** — изолированные CSS-классы `.cc-branch-btn`: глобальные стили DeepSeek больше не режут текст кнопок.
-- 📖 **Документация** — README (ru/en/осн.) дополнены разделами про правила, скиллы, промпты и режим плана.
+- 🎛 **Настройки переехали и стали удобнее** (`60c98d6`) — `settings-react.tsx` переписан:
+ - новая вёрстка на компонентах `setting-row`, `select`, `ui-button`;
+ - изменения применяются ==сразу==, без перезапуска (`shell-save-settings` → live-apply);
+ - дополнен `shell-ipc.js`, обновлены `components.css` и `main.ts`.
+- 🧱 **Окно перешло на Shell** — затронуты `src/main/index.js`, `window.js`, `preload/index.js`; появился `shell-preload.js` (мост API shell) и `shell-api.ts` на стороне UI.
+- 🗂 **`settings-store.js`** немного причесали (`d1a7aad`): уточнили хранение и комментарии.
+- 🏗 **Сборка и CI** (`51d506f`): `scripts/build-shell.mjs` и `scripts/copy-monaco.mjs` собирают Shell и копируют Monaco **до** `electron-builder`, скрипты прописаны в `package.json`.
+- 📄 **README** (ru/en) обновлён под новый интерфейс и возможности.
### Fixed
-- 🐛 **Ответ `ask_user_question` всегда виден в выводе** — попадает в лог даже без `log()`, без дублирования.
-
-## [5.0.7] - 2026-10-15
-
-### Added
-
-- 🎯 **Режим цели `/goal` — автономные многораундовые задачи** — одна команда превращает задачу в самодвижущийся цикл: AI шаг за шагом продвигается к цели ==без вашего участия между шагами==:
- - раунд завершился (нет tool-вызовов) — Cookie Code **сам** отправляет AI «продолжай» через задержку `NUDGE_DELAY`;
- - движок живёт в preload (`goal-engine.js`), состояние per-session, персистится в `localStorage` (`cuckoo-goal-v1`);
- - завершение — когда AI вызывает инструмент `goalDone()`;
- - предохранители: лимит итераций (по умолчанию 50, настройка `cuckoo-goal-max-iterations`) и остановка при 3 раундах без прогресса (`NO_PROGRESS_LIMIT`).
-- ⌨️ **Перехват команды `/goal` в веб-чате** (`goal-command.js`) — команда ловится на capture-фазе (Enter и клик по кнопке отправки) и обрабатывается локально, в AI не уходит:
- - `/goal <описание>` — задать цель;
- - `/goal` — показать статус;
- - `/goal stop | pause | resume` — управление.
-- 🪟 **Плавающая панель «Цель»** (`goal-panel.js`) — слева появляется перетаскиваемая карточка с текстом цели, номером итерации, таймером и кнопками **Пауза** / **Выход**:
- - стили встроены в overlay (`template.js`), цвет статуса меняется по состоянию (`running` / `paused` / `done`);
- - позиция панели сохраняется в `localStorage` (`cuckoo-goal-pos`).
-- 🤖 **Цель в Telegram** — команда `/goal` в боте умеет задавать цель, показывать статус и управлять ею (`stop` / `pause` / `resume`):
- - в чат приходит человеческое уведомление о старте и о завершении цели (`notifyGoalDone`);
- - статус читается из `goal-store` в main по активному окну.
-- 🧰 **Инструмент `goal_done`** (`GoalDoneTool.js`) — AI вызывает `goalDone()`, чтобы объявить цель выполненной; тул шлёт IPC `goal-done` в окно, и движок останавливает цикл (заменяет текстовый маркер `[[GOAL_DONE]]`, который модель забывала писать).
-
-### Changed
+- 🐛 **Починили устаревшие тесты** — `test/main/session-store.test.js`, `test/main/window.test.js` и `test/preload/commands.test.js` приведены в соответствие с новым Shell-окном и API.
+- 🩹 **Стабильность макета Shell** — серия правок (`MAJOR UPDATE`, `major2`, `major3`) поправила layout: sidebar, модалки, страницы и токены темы (см. `base.css` / `shell.html`).
+- 📊 **Stats dashboard, recorder и tool-render** — подкрутили отображение статистики и инлайн-рендер результатов инструментов под новую тему.
+- 🧹 Мелкие фиксы `exit-plan-mode`, `whats-new`, `observer`, `continue-button` и `tps`.
-- 🍪 **Логотип и README** — в README (ru/en/осн.) добавлен блок про режим цели; в таблицу инструментов добавлен `goalDone`.
-- 📖 **Команда `/goal` в help бота** — в списке команд появились `/goal <цель>` и `/goal stop|pause|resume` (ru/en).
+### Removed
-### Fixed
+- ~~Старый монолитный `src/ui/shell.html`~~ — теперь всё собирается из partials (`src/ui/shell/index.html` + `scripts/build-shell.mjs`).
+- Удалили устаревший ассет `assets/петы.jpg` — на его месте новое изображение.
-- 🐛 **Snake_case алиас `goal_done`** — наряду с `goalDone()` в `JsRunner` зарегистрирован `goal_done`.
+Спасибо, что пользуетесь Cookie Code! 💚
diff --git a/README.en.md b/README.en.md
index da11e21..9b9ea47 100644
--- a/README.en.md
+++ b/README.en.md
@@ -16,82 +16,99 @@
-
+
-**Turn DeepSeek into a real coding assistant.** Cookie Code bridges the gap between AI chat and your actual codebase — no API tokens, no copy-paste, just pure automation.
+**Cookie Code** turns the DeepSeek web chat into a developer workstation. The AI opens files in your project, runs commands, edits code, and commits, and you stay in the same chat.
+
+The app works through your regular DeepSeek web account. No API key, and you do not pay per token.
---
-## 🎯 Why Cookie Code?
+## Why this exists
+
+The DeepSeek web chat thinks well, but it cannot see your project. It cannot open a file, run a test, or make a commit, so you end up copying code back and forth.
-**The Problem:** DeepSeek is smart, but blind to your project. It can't read files, run commands, or commit changes. You're stuck copy-pasting code back and forth.
+Cookie Code adds a local executor to the chat. The AI writes a block that calls a tool, the app intercepts the block, runs it in a Node sandbox, and streams the result back into the chat. The loop then repeats: think, act, read the result.
-**The Solution:** Cookie Code injects a local execution layer into the DeepSeek web chat:
+What you get:
-✅ **Zero token cost** — uses your free DeepSeek web account, no API keys
-✅ **Real agent loop** — AI reads files → writes code → runs tests → commits changes
-✅ **Subagents** — AI delegates tasks to isolated agents (own context, own tool whitelist)
-✅ **Git integration** — see diffs, browse history, review changes in a visual panel
-✅ **Telegram control** — code from your phone, get notifications, approve commands remotely
-✅ **Beautiful UI** — glass effects, custom themes, animated pets, dark mode
+- A workflow on your regular DeepSeek web account, with no API keys and no per-token billing.
+- A full agent loop: file reads, edits, shell commands, SQL queries, MCP tools.
+- Subagents in separate windows with their own context and their own tool allowlist.
+- Git inside the app: diff, history, commit, push.
+- Control from your phone through Telegram.
+- A UI you can rebuild: wallpapers, glass effects, fonts, themes.
---
-## ✨ Key Features
+## Features
+
+### An AI agent that works on your code
+
+The AI can:
+
+- Read files: project structure, file contents, pattern search.
+- Write and edit code: create files, apply patches, delete stale code.
+- Run commands: bash, PowerShell, SQL queries, any shell script.
+- Search the project: files by glob, contents by regular expression.
+- Keep a task list: create, update, delete.
+- Fetch data over HTTP and call APIs.
+- Connect MCP servers and call their tools.
+- Remember you and the project in two memory levels.
+- Follow project rules from `.cookie/rules.md`.
-### 🤖 **AI Agent That Actually Does Things**
+What the loop looks like:
-The AI can now:
+1. You type: "Show recent changes in auth.js".
+2. The AI replies with a ```cuckoo block that calls grep.
+3. Cookie Code runs the call and streams the result into the chat.
+4. The AI reads the output and continues.
-- 📖 **Read your files** — entire project structure, grep patterns, file contents
-- ✏️ **Write & edit code** — create files, apply patches, delete old code
-- 💻 **Run commands** — bash, PowerShell, database queries, any shell script
-- 🔍 **Search & navigate** — find files by glob, search content with regex
-- 📊 **Manage tasks** — create, track, and complete todo lists
-- 🌐 **Fetch data** — HTTP requests, API calls, web scraping
-- 🔧 **MCP tools** — connect any MCP server for extended capabilities
-- 🧠 **Two-level memory** — AI remembers both you and the project: **global** memory (`/memory.md`) holds user/system facts, **project** memory (`/.cookie/memory/ProjectMemory.md`) holds conventions, architecture and key paths
-- 📜 **Project rules** — a `.cookie/rules.md` file sets rules the AI must accept via `readrules()`. Until accepted, mutating tools are locked. No file — no lock. Subagents bypass the gate.
+### Two-level memory
-**How it works:**
+The AI remembers both you and the project:
-1. You ask: "Show me recent changes in auth.js"
-2. AI emits: `` `cuckoo const r = await grep('auth.js', 'login');` ``
-3. Cookie Code intercepts, executes, streams result back to AI
-4. AI sees the output and continues working
+- Global memory (`/memory.md`) holds facts about you and your system.
+- Project memory (`/.cookie/memory/ProjectMemory.md`) holds conventions, architectural decisions, and key paths for that project.
-### 🚀 **Subagents — AI Builds Its Own Helpers**
+The `memorySave`, `memoryRead`, and `memoryClear` tools take a `scope` argument with the values `project`, `global`, or `all`. Both files can be opened and cleared from Settings.
+
+### Project rules
+
+A `.cookie/rules.md` file sets rules the AI must accept through `readrules()`. Until the rules are accepted, tools that change files stay locked. No file means no lock. Subagents bypass this gate.
+
+### Subagents
-
-
+
+
-Cookie Code can **delegate tasks to isolated AI agents**, each in its own window with its own context. The subagent's drafts, searches, and tool calls **never pollute the main conversation** — only the final summary comes back to the parent.
+The AI delegates tasks to isolated agents. Each one runs in its own window with its own context, and only the final summary returns to the main conversation. Drafts and intermediate tool calls never pollute the parent chat.
-**How it works:**
+How it works:
-1. You: _"Delegate to explore: find all calls to apiFetch"_
-2. AI calls `run_agent("explore", "find all calls to apiFetch")`
-3. A **separate window** opens using the same DeepSeek login
-4. The subagent works in isolation: `glob → read → grep → ...`
-5. When done, the window closes and **only the summary** appears in the chat
+1. You ask: "Delegate to explore: find every call to apiFetch".
+2. The AI calls `run_agent("explore", "...", "...")`.
+3. A separate window opens with the same DeepSeek login.
+4. The subagent works in isolation: `glob → read → grep`.
+5. When it finishes, the window closes and the summary appears in the chat.
-**Three ways to create an agent:**
+Three ways to create an agent:
-- **Manually** — drop `cookie/agents/.md` with frontmatter into your project
-- **Via AI** — say _"Create an agent for SQL migration review"_ → AI calls `create_agent` and uses it immediately
-- **Built-in** — `explore`, `code-reviewer`, `git-committer`, `changelog-writer` ship with the project
+- Manually: drop `cookie/agents/.md` with frontmatter into the project.
+- Through the AI: say "Create an agent for SQL migration review", and the AI calls `create_agent` and uses it right away.
+- Use a built-in one: `explore`, `code-reviewer`, `git-committer`, `changelog-writer`, and `page-scripter` already ship in the project.
-**Safety rails:**
+What constrains a subagent:
-- 🔒 **Tool whitelist** — put `tools: read, grep` in the agent's frontmatter → it **physically cannot** call `bash` or `mysql`
-- 🚫 **Anti-recursion** — a subagent cannot spawn another subagent
-- ⏱ **maxTurns** — breaks infinite loops (e.g., 40 steps for the committer)
-- ⏲ **10-min timeout** — force-closes a hung window
+- Tool allowlist. Set `tools: read, grep`, and the agent physically cannot call `bash` or `mysql`.
+- No recursion. A subagent cannot spawn another subagent.
+- A step limit (`maxTurns`) that breaks infinite loops.
+- A 10-minute timeout that closes a hung window.
-**Agent example:**
+Agent example:
```markdown
---
@@ -104,388 +121,223 @@ maxTurns: 20
You are an experienced code review expert...
```
----
-
-### 🎯 **Goals — Autonomous Multi-Round Tasks**
+### Goals
-The `/goal` command turns a single task into a **self-driving multi-round loop**: the AI keeps advancing step by step until the goal is done — no input from you between steps.
+The `/goal` command turns a task into a self-driving loop: the AI advances step by step without input from you between steps.
-**How it works:**
+- `/goal ` sets a goal, `/goal` shows status, and `/goal stop|pause|resume` controls it.
+- When a response round ends, Cookie Code sends "continue" to the AI automatically.
+- The goal completes when the AI calls the `goalDone()` tool.
+- Loop protection: a 50-iteration limit and a stop after three rounds without progress.
+- The Goal panel on the left shows the goal text, the iteration number, a timer, and Pause and Exit buttons.
+- Every chat has its own goal.
+- You can set and manage goals from Telegram with `/goal`, and start and completion notifications arrive there.
-1. Type `/goal ` in chat (or set a goal from Telegram: `/goal `)
-2. The AI receives the goal instruction and starts working
-3. When a response round ends (no tool calls), Cookie Code **automatically** sends the AI "continue"
-4. When done, the AI calls the `goalDone()` tool and the loop stops
+### Interface
-**Controls:**
+- Glass panels with configurable blur and opacity.
+- 27 wallpapers included.
+- Animated pets that react to your work.
+- Dark and light themes, switched automatically or by hand.
+- Your own typeface: drop a file in the folder and pick it in Settings.
+- An RGB glow for the username.
-| Command | Action |
-| ------------------------------ | ------------------- |
-| `/goal ` | Set a goal |
-| `/goal` | Show current status |
-| `/goal stop` | Stop the goal |
-| `/goal pause` / `/goal resume` | Pause / resume |
+### Safety
-**Goal panel:** a floating panel on the left shows the goal text, iteration number, elapsed time and **Pause** / **Exit** buttons. It can be dragged.
+- Tool approval: risky commands run only after you confirm them.
+- Dangerous patterns: regular expressions for commands that must never run.
+- Hidden service messages: the chat stays clean while the AI still sees the full context.
+- Session allowlist: approve a tool once and it runs freely until reload.
+- Project rules: the AI accepts them through `readrules()` before starting work.
+- Plan mode: the AI writes a plan to `plan.md` instead of changing code. You approve or reject the plan, and you can leave comments on its lines.
-**Loop protection:**
-
-- ⏱ **Iteration limit** — 50 rounds by default (setting `cuckoo-goal-max-iterations`)
-- 🔁 **No progress** — 3 identical rounds in a row stop the goal
-- ⏸ **Manual stop** — `/goal stop` or the "Exit" button instantly break the loop
-
-**Per-session:** each chat has its own goal — switching sessions keeps them separate.
-
-**Telegram notifications:** you get notified on goal start and completion, and can set/manage goals right from the bot.
-
----
-
-### 🎨 **Beautiful & Customizable**
-
-
-
-
+### Project prompts
-- **Glass UI** — frosted glass panels with custom blur and opacity
-- **27 wallpapers** — hand-picked backgrounds built-in
-- **Animated pets** — cute mascots that react to your work
-- **Dark/Light themes** — automatic or manual switching
-- **Custom fonts** — bring your own typeface
-- **RGB effects** — animated username glow
+Prompts live in `.cookie/prompts/*.md`, and the Prompts button opens them in the overlay. You can create, edit, delete, and insert a prompt into the input with one click. The `/prompts` command does the same from Telegram.
-### 🔒 **Smart Safety Gates**
+### Telegram bot
-- **Tool approval** — confirm risky commands (bash, file writes) before execution
-- **Dangerous patterns** — regex blacklist for commands you never want to run
-- **Hidden service messages** — clean chat UI, but AI still sees full context
-- **Session-based whitelist** — approve a tool once, it runs freely until reload
+Control the app from your phone:
-### 📱 **Telegram Bot Integration**
+- `/status` shows the current project, active processes, and task count.
+- `/diff` sends uncommitted changes with syntax highlighting.
+- `/log` browses commit history and shows the diff of a selected commit.
+- `/todos` manages the task list.
+- `/prompts` opens project prompts.
+- `/screen` takes a screenshot of the active window.
+- `/stop` kills runaway processes.
-Control everything from your phone:
+Incoming messages are typed into the chat. Voice messages are transcribed by local Whisper and sent to the AI. Photos and files are attached to the input field.
-- `/status` — current project, active processes, todo count
-- `/diff` — see uncommitted changes with syntax highlighting
-- `/log` — browse git history, show commit diffs
-- `/todos` — manage task list remotely
-- `/prompts` — project prompts from the bot: list with Insert/Delete and a step-by-step Create (name → text)
-- `/screen` — take a screenshot of the active window
-- `/stop` — kill runaway processes
+### Git
-**Incoming messages** → typed into chat automatically
-**Voice messages** → transcribed via local Whisper and sent to AI
-**Photos/files** → attached to the chat input field
+A built-in diff viewer:
-### 🧠 **Two-Level Memory**
+- The Changes tab shows uncommitted edits line by line.
+- The History tab browses commits, and a click opens the full diff.
+- Navigation jumps between hunks and filters added and removed lines.
+- A minimap gives an overview of the whole change.
+- Inline diff highlights character-level differences.
+- The Commit button assembles the unified diff of every changed file and posts a message to the chat asking for a commit. You can then summon the `git-committer` agent or commit yourself.
-The AI remembers **both you and the project** — memory is split into two independent levels:
+### Hotkeys
-| Level | Location | What it remembers |
-| --------- | ---------------------------------------------- | ---------------------------------------------------------------------- |
-| 🌍 Global | `/memory.md` | User and system facts: name, OS, GPU, code style preferences |
-| 🗂 Project | `/.cookie/memory/ProjectMemory.md` | Conventions, architectural decisions, key paths, stack of this project |
+| Key | Action |
+| ------- | ------------------------------------------- |
+| **F1** | Show the current CHANGELOG (What's New box) |
+| **F11** | Fullscreen mode |
+| **F12** | Developer tools (DevTools) |
-- Tools `memorySave(text, scope?)`, `memoryRead(scope?)`, `memoryClear(scope?)` accept `scope`: `'project'` | `'global'` (`memoryRead` also `'all'`).
-- By default `memorySave` writes to **project** memory if the project is initialized, otherwise to global.
-- Absolute paths to both files are injected into the system prompt and exposed in JS scripts as `globalThis.memoryPath` and `globalThis.projectMemoryPath`.
-- Files can be opened, cleared, and their stats viewed separately per level in **Settings → Cookie Code**.
-- Project memory lives in `.gitignore` — the AI's personal notes are never committed.
-
-### ⌨️ **Hotkeys**
-
-| Key | Action |
-| ------ | ------------------------------------------- |
-| **F1** | Show the current CHANGELOG (What's New box) |
-
-The What's New window (F1) is **draggable by its header** and adapts its width to the screen.
-
-### 📊 **Git Integration**
-
-
-
-
+---
-Built-in diff viewer:
+## What's new
-- **Changes tab** — see uncommitted changes, file-by-file diffs
-- **History tab** — browse commits, click to see full diff
-- **Navigation** — jump between hunks, filter added/deleted lines
-- **Mini-map** — visual overview of changes
-- **Inline diff** — character-level highlighting for precise edits
-- **Commit button** — stitches the unified diff of **all** changed files and posts a ready message to the chat asking to commit (you can summon the `git-committer` agent or commit yourself)
+Recent major changes:
-### 📈 **Statistics Dashboard**
+- **A new VS Code style shell.** The UI was rewritten: an activity bar on the left, a page panel (Home, Workspaces, Files, Prompts, Skills, Subagents, MCP, Token, About), and a status bar. The window has no system frame and uses its own buttons, and F11 goes fullscreen.
+- **Project file tree.** Folders and subfolders expand, up to 6 levels deep and 500 entries per folder. The **@** button inserts `User mentioned file: ` into the chat, or `User mentioned folder: ` for a folder. Name and path search, a Monaco preview, and open-in-system are included.
+- **Subagents in separate lightweight windows.** The window opens straight into a DeepSeek chat with the prompt and its own context, with no extra panels.
+- **Speed and tokens.** Output speed is computed from the difference in the server-side `accumulated_token_usage` and shown in real time. Context and speed appear in the status bar.
+- **A "Task detected" block and History.** Home shows the current command or task, a progress indicator, a **Kill** button, and a collapsible history of executed commands instead of an empty placeholder.
+- **Project prompts.** Stored in `.cookie/prompts/*.md`, created, edited, and deleted in the UI, and inserted into the input with one click.
+- **Updates.** The "Check for updates" button reports an honest result: up to date, a new version available, the update downloaded, an error, or unavailable in dev mode. The version on the About page comes from the latest `CHANGELOG.md` entry.
-Track your productivity:
+### Statistics
-- **Activity heatmap** — GitHub-style contribution graph
-- **Token usage** — daily/weekly trends
-- **Favorite models** — which AI you use most
-- **Streak tracking** — longest consecutive days of coding
+- A GitHub style activity heatmap.
+- Token usage by day and by week.
+- Your most used models.
+- Your longest coding streak.
---
-## 🚀 Quick Start
-
-### Option 1: Download Binary (Recommended)
+## Quick start
-**Windows:**
+### Download a build
-1. Download [CookieCode-Setup.exe](https://github.com/merfiDEV/Cookie-code/releases/latest)
-2. Run installer
-3. Launch Cookie Code
+**Windows:** download [CookieCode-Setup.exe](https://github.com/merfiDEV/Cookie-code/releases/latest), run the installer, open the app.
-**macOS:**
+**macOS:** download [CookieCode.dmg](https://github.com/merfiDEV/Cookie-code/releases/latest), drag it to Applications, open it.
-1. Download [CookieCode.dmg](https://github.com/merfiDEV/Cookie-code/releases/latest)
-2. Drag to Applications
-3. Open (right-click → Open if Gatekeeper blocks)
-
-### Option 2: Build from Source
+### Build from source
```bash
-# Clone the repo
git clone https://github.com/merfiDEV/Cookie-code.git
cd Cookie-code
-
-# Install dependencies
npm install
-
-# Run in development mode
npm start
-
-# Or build for your platform
-npm run build:win # Windows installer
-npm run build:mac # macOS .dmg
```
-**Requirements:** Node.js 16+ (18+ recommended)
+You need Node.js 16 or newer.
---
-## 📖 How to Use
-
-### 1️⃣ **First Launch**
+## Usage
-On first run, Cookie Code opens the DeepSeek chat and shows a setup wizard:
+### First launch
-1. **Pick a project directory** — this is your working folder
-2. **Choose a theme** — wallpaper, glass effects, pet
-3. **(Optional)** Set up Telegram bot for remote control
+1. Pick a project directory.
+2. Pick a theme: wallpaper, glass effects, pet.
+3. Optionally set up the Telegram bot.
-### 2️⃣ **Start Coding**
+### Working
-Just chat naturally with the AI:
+Just talk to the AI:
```
-You: "Review the changes I made today"
-AI: Let me check... [runs git diff]
- You modified 3 files: auth.js, api.js, README.md
- [shows inline diff blocks]
+You: "Show the changes I made today"
+AI: runs git diff and lists three changed files
You: "Write tests for the login function"
-AI: [reads auth.js, creates auth.test.js, runs npm test]
- ✅ All 5 tests passing
-
-You: "Commit this with a good message"
-AI: [runs git add + git commit]
- Committed: "feat(auth): add comprehensive login tests"
-```
-
-### 3️⃣ **Explore Tools**
-
-Open the side panel (Cookie Code logo) to:
+AI: reads auth.js, creates the tests, runs them, and reports the result
-- 🗂️ **Browse sessions** — switch between project contexts
-- 📝 **Manage todos** — see AI-created task lists
-- 🔄 **View git diff** — visual file changes
-- ⚙️ **Adjust settings** — themes, tools, Telegram
-
----
-
-## 🎓 Advanced Features
-
-### Project-Wide Context (Coming Soon)
-
-**Current limitation:** AI only knows files it explicitly reads.
-
-**Planned feature:** Full project indexing
-
-- Embed all source files into a vector database
-- AI can semantic search: "Where's the auth logic?"
-- Instant jump-to-definition for any symbol
-- RAG (Retrieval-Augmented Generation) for better answers
-
-### MCP Server Support
-
-Connect any [Model Context Protocol](https://modelcontextprotocol.io) server:
-
-```json
-{
- "mcpServers": {
- "github": {
- "command": "npx",
- "args": ["-y", "@modelcontextprotocol/server-github"],
- "env": { "GITHUB_TOKEN": "..." }
- }
- }
-}
+You: "Commit this"
+AI: runs git commit with the message "feat(auth): add login tests"
```
-Now AI can create PRs, review code, manage issues — all through natural language.
-
-### Custom Tool Scripts
-
-Drop `.js` files into `tools/custom/` to extend Cookie Code:
-
-```javascript
-// tools/custom/deploy.js
-module.exports = {
- name: "deploy",
- description: "Deploy to production",
- params: { target: "string" },
- async execute({ target }) {
- // Your deployment logic
- return { success: true, url: "..." };
- },
-};
-```
-
-AI can now call `deploy` like any built-in tool.
+The side panel opens sessions, the task list, the git diff, and settings.
---
-## 🛠️ Built-in Tools
-
-Cookie Code ships with 20+ tools out of the box:
-
-| Tool | Description | Example |
-| ----------- | ------------------------- | --------------------------------------- |
-| `read` | Read file contents | `read('src/auth.js')` |
-| `write` | Create or overwrite file | `write('test.js', code)` |
-| `edit` | Apply targeted patch | `edit('app.js', oldCode, newCode)` |
-| `glob` | Find files by pattern | `glob('**/*.test.js')` |
-| `grep` | Search file contents | `grep('TODO', { include: '*.js' })` |
-| `bash` | Run shell command | `bash('npm test')` |
-| `pwsh` | Run PowerShell script | `pwsh('Get-Process')` |
-| `git` | Git operations | `git('status')` |
-| `mysql` | SQL queries | `mysql('SELECT * FROM users')` |
-| `webFetch` | HTTP requests | `webFetch('https://api.example.com')` |
-| `todoWrite` | Manage task lists | `todoWrite([{content: 'Fix bug'}])` |
-| `mcpCall` | Call MCP server tool | `mcpCall('github', 'create_pr', {...})` |
-| `goalDone` | Complete a goal (`/goal`) | `goalDone()` |
-| `readrules` | Accept project rules | `readrules()` |
-
-[Full tool reference →](docs/TOOLS.md)
+## Built-in tools
+
+The app registers 44 tools. The main ones:
+
+| Tool | Description |
+| ------------------- | ------------------------------ |
+| `read` | Read file contents |
+| `write` | Create or overwrite a file |
+| `edit` | Apply a targeted patch |
+| `glob` | Find files by pattern |
+| `grep` | Search file contents |
+| `bash` / `pwsh` | Run shell commands |
+| `mysql` | SQL queries |
+| `webFetch` | HTTP requests |
+| `todoWrite` | Task lists |
+| `mcpCall` | Call an MCP server tool |
+| `skillLoad` | Load a custom skill |
+| `run_agent` | Delegate a task to a subagent |
+| `memorySave` | Write a fact to memory |
+| `goalDone` | Complete a `/goal` |
+| `readrules` | Accept project rules |
+| `ask_user_question` | Ask a clarifying question |
+| `exitPlanMode` | Submit the plan from `plan.md` |
+| `attachFile` | Attach a file to the chat |
+| `cityTime` | Current time and city |
+
+Full TypeScript declarations live in [`tools/cuckoo-tools.d.ts`](tools/cuckoo-tools.d.ts).
---
-## 🎨 Customization
-
-### Themes
-
-**Settings → Cookie Code → Theme & Glass**
-
-- **Background blur** — 0-30px frosted glass effect
-- **Panel opacity** — 0-100% transparency
-- **Glass colors** — custom hex colors for panels
-- **Button styles** — border radius, hover effects
-
-### Pets
+## Customization
-**Settings → Cookie Code → Pets**
+**Themes:** background blur, panel opacity, glass color.
-Drop PNG/GIF files into `userData/pets/`, pick from grid. Animated pets react to tool execution success/failure.
+**Pets:** drop PNG or GIF files into `userData/pets/` and pick one from the grid.
-### Fonts
+**Fonts:** drop `.ttf` or `.woff` files into `userData/fonts/` and pick one from the list.
-**Settings → Cookie Code → Font**
-
-Drop `.ttf`/`.otf`/`.woff` files into `userData/fonts/`, select from dropdown. Applies to entire UI.
-
-### Skills
-
-Add a folder in `.cuckoo/skills//` with `SKILL.md` (and optional `tool.js`) — callable via `skillList`, `skillLoad`, `skillExecute`. Skills are two-level: **global** (`/skills//`) and **project** (`/.cuckoo/skills//`); a global skill overrides a project one with the same name.
-
-### Project Prompts
-
-Store reusable prompts in `.cookie/prompts/*.md` (one file per prompt). The **Prompts** button in the overlay opens a panel to create / edit / delete a prompt and insert its text into the input (text only, no send). From Telegram — the `/prompts` command.
-
-### Project Rules
-
-A `.cookie/rules.md` file sets rules the AI must accept via `readrules()` before working. Until accepted, tools (except `read`, `read_lines`, `file_read`, `memoryRead`, `readrules`) are locked. No file — no lock; subagents bypass the gate.
-
-### Plan Mode & Comments
-
-The **Plan** toggle (next to DeepSeek toggles) makes the AI explore only and write a plan to `plan.md` instead of changing code; it submits the plan via `exit_plan_mode()`.
-
-- **Line comments** — select a fragment of the plan → a 💬 button appears → leave a note right under that line (multiple lines supported).
-- On **reject**, comments return to the model (text + source line + selection).
-- On **approve**, comments are appended to the "work according to the plan" request and sent to chat; the plan can also be approved from Telegram.
+**Skills:** a folder with `SKILL.md` and an optional `tool.js` in `.cuckoo/skills//` for one project, or in `/skills//` for every project. A global skill overrides a project skill with the same name.
---
-## 🤝 Contributing
-
-We welcome contributions! Here's how:
+## Contributing
-1. **Fork** the repo
-2. **Create a branch** — `git checkout -b feature/amazing-feature`
-3. **Make changes** — add features, fix bugs, improve docs
-4. **Test** — `npm test` (402 tests, 100% critical path coverage)
-5. **Commit** — `git commit -m 'feat: add amazing feature'`
-6. **Push** — `git push origin feature/amazing-feature`
-7. **Open PR** — describe what changed and why
+1. Fork the repo.
+2. Create a branch: `git checkout -b feature/amazing`.
+3. Make your changes.
+4. Run the tests: `npm test`.
+5. Commit: `git commit -m 'feat: add feature'`.
+6. Push the branch and open a pull request.
-### Areas We Need Help
+Where help is welcome:
-- 🌍 **Translations** — add more languages to `src/preload/i18n/`
-- 📚 **Documentation** — improve guides, add video tutorials
-- 🐛 **Bug reports** — test on different systems, report edge cases
-- ✨ **New tools** — implement tool ideas from the [wishlist](https://github.com/merfiDEV/Cookie-code/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
+- Translations.
+- Documentation.
+- Bug reports.
+- New tools.
---
-## 📜 License
-
-MIT License — see [LICENSE](LICENSE) for details.
+## License
-Free to use, modify, and distribute. Commercial use allowed.
+MIT. Use, modify, and redistribute freely, including in commercial projects.
---
-## 🙏 Credits
-
-Built with:
-
-- [Electron](https://www.electronjs.org/) — desktop app framework
-- [DeepSeek](https://www.deepseek.com/) — AI chat interface
-- [Telegraf](https://github.com/telegraf/telegraf) — Telegram bot framework
-- [gifenc](https://github.com/mattdesl/gifenc) — GIF processing
+## Credits
-Inspired by:
+Built with [Electron](https://electronjs.org/), [DeepSeek](https://deepseek.com/), and [Telegraf](https://github.com/telegraf/telegraf).
-- [Aider](https://github.com/paul-gauthier/aider) — AI pair programming in terminal
-- [Claude Desktop](https://claude.ai/download) — MCP protocol pioneer
-- [Cursor](https://cursor.sh/) — AI-first code editor
+Inspired by [Aider](https://github.com/paul-gauthier/aider), [Claude Desktop](https://claude.ai/download), and [Cursor](https://cursor.sh/).
---
-## ⭐ Star History
+## Star history
[](https://star-history.com/#merfiDEV/Cookie-code&Date)
-If Cookie Code saves you time, consider giving it a star! It helps others discover the project.
-
----
-
-## 🔗 Links
-
-- **Documentation:** [docs/](docs/)
-- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
-- **Roadmap:** [GitHub Projects](https://github.com/merfiDEV/Cookie-code/projects)
-- **Discord:** [Join the community](https://discord.gg/...) _(coming soon)_
-- **Twitter:** [@CookieCodeAI](https://twitter.com/...) _(coming soon)_
+If Cookie Code saves you time, give it a star.
---
diff --git a/README.md b/README.md
index 4c910b2..8aa13a2 100644
--- a/README.md
+++ b/README.md
@@ -12,86 +12,103 @@
- English (full) · Русский · Русский (full)
+ English · Русский · Русский (полная версия)
-
+
-**Превратите DeepSeek в настоящего помощника по коду.** Cookie Code соединяет AI-чат с вашей реальной кодовой базой — без API-токенов, без копипасты, только чистая автоматизация.
+**Cookie Code** превращает веб-чат DeepSeek в рабочее место разработчика. AI открывает файлы вашего проекта, запускает команды, правит код и делает коммиты, а вы остаётесь в том же чате.
+
+Приложение работает через ваш обычный веб-аккаунт DeepSeek. API-ключ не нужен, по токенам вы не платите.
---
-## 🎯 Зачем Cookie Code?
+## Зачем это нужно
+
+Веб-чат DeepSeek хорошо думает, но не видит проект. Он не может открыть файл, запустить тест или сделать коммит, поэтому код приходится копировать туда и обратно.
-**Проблема:** DeepSeek умён, но слеп к вашему проекту. Он не может читать файлы, запускать команды или коммитить изменения. Вы застряли в копипасте кода туда-сюда.
+Cookie Code добавляет к чату локальный исполнитель. AI пишет блок с вызовом инструмента, приложение перехватывает его, выполняет в песочнице Node и возвращает результат обратно в чат. Дальше цикл повторяется: думай, действуй, смотри результат.
-**Решение:** Cookie Code внедряет слой локального выполнения в веб-чат DeepSeek:
+Что вы получаете:
-✅ **Нулевая стоимость токенов** — использует ваш бесплатный веб-аккаунт DeepSeek, без API-ключей
-✅ **Настоящий агентный цикл** — AI читает файлы → пишет код → запускает тесты → коммитит изменения
-✅ **Субагенты** — AI делегирует задачи изолированным агентам (свой контекст, свой whitelist инструментов)
-✅ **Интеграция Git** — смотрите diff, листайте историю, проверяйте изменения визуально
-✅ **Управление через Telegram** — пишите код с телефона, получайте уведомления, подтверждайте команды удалённо
-✅ **Красивый UI** — стеклянные эффекты, кастомные темы, анимированные петы, тёмная тема
+- Работу через веб-аккаунт DeepSeek без API-ключей и оплаты по токенам.
+- Полный агентный цикл: чтение файлов, правки, shell-команды, SQL-запросы, MCP-инструменты.
+- Субагентов в отдельных окнах со своим контекстом и списком разрешённых инструментов.
+- Git внутри приложения: diff, история, коммит и push.
+- Управление с телефона через Telegram.
+- Интерфейс, который можно перестроить под себя: обои, стекло, шрифты, темы.
---
-## ✨ Основные возможности
+## Возможности
+
+### AI-агент, который работает с вашим кодом
+
+AI умеет:
+
+- Читать файлы: структуру проекта, содержимое, поиск по шаблону.
+- Писать и править код: создавать файлы, применять патчи, удалять устаревшее.
+- Запускать команды: bash, PowerShell, SQL-запросы, любые shell-скрипты.
+- Искать по проекту: файлы по glob, содержимое по регулярному выражению.
+- Вести список задач: создавать, отмечать, удалять.
+- Загружать данные: HTTP-запросы и вызовы API.
+- Подключать MCP-серверы и вызывать их инструменты.
+- Помнить вас и проект в двух уровнях памяти.
+- Работать по правилам проекта из `.cookie/rules.md`.
-### 🤖 **AI-агент, который реально работает**
+Как это выглядит:
-Теперь AI умеет:
+1. Вы пишете: «Покажи последние изменения в auth.js».
+2. AI отвечает блоком ```cuckoo с вызовом grep.
+3. Cookie Code выполняет вызов и стримит результат в чат.
+4. AI читает вывод и продолжает работу.
-- 📖 **Читать файлы** — структура проекта, grep-паттерны, содержимое
-- ✏️ **Писать и редактировать код** — создавать файлы, применять патчи, удалять старый код
-- 💻 **Запускать команды** — bash, PowerShell, SQL-запросы, любые shell-скрипты
-- 🔍 **Искать и навигировать** — находить файлы по glob, искать по regex
-- 📊 **Управлять задачами** — создавать, отслеживать и завершать todo-списки
-- 🌐 **Получать данные** — HTTP-запросы, API-вызовы, веб-скрапинг
-- 🔧 **MCP-инструменты** — подключать любой MCP-сервер для расширенных возможностей
-- 🧠 **Двухуровневая память** — AI помнит и вас, и проект: **глобальная** память (`/memory.md`) хранит факты о пользователе и системе, **проектная** (`/.cookie/memory/ProjectMemory.md`) — соглашения, архитектуру и важные пути конкретного проекта. Инструменты `memorySave`/`memoryRead`/`memoryClear` принимают `scope` ('project' | 'global' | 'all'). Файлы открываются и очищаются в настройках.
-- 📜 **Правила проекта** — файл `.cookie/rules.md` задаёт правила для AI. Пока правила не приняты (инструмент `readrules`), изменяющие инструменты заблокированы. Нет файла — нет и блокировки. Субагенты работают без гейта.
+### Двухуровневая память
-**Как это работает:**
+AI помнит и вас, и проект:
-1. Вы спрашиваете: "Покажи последние изменения в auth.js"
-2. AI генерирует: `` `cuckoo const r = await grep('auth.js', 'login');` ``
-3. Cookie Code перехватывает, выполняет, стримит результат обратно в AI
-4. AI видит вывод и продолжает работать
+- Глобальная память (`/memory.md`) хранит факты о вас и системе.
+- Проектная память (`/.cookie/memory/ProjectMemory.md`) хранит соглашения, архитектурные решения и важные пути конкретного проекта.
-### 🚀 **Субагенты — AI создаёт своих помощников**
+Инструменты `memorySave`, `memoryRead` и `memoryClear` принимают параметр `scope` со значениями `project`, `global` или `all`. Файлы открываются и очищаются в настройках.
+
+### Правила проекта
+
+Файл `.cookie/rules.md` задаёт правила, которые AI обязан принять через `readrules()`. Пока правила не приняты, инструменты, меняющие файлы, заблокированы. Если файла нет, блокировки тоже нет. Субагенты работают без этого гейта.
+
+### Субагенты
-
-
+
+
-Cookie Code умеет **делегировать задачи изолированным AI-агентам**, каждый в своём окне и со своим контекстом. Черновики, поиски и tool-вызовы субагента **не засоряют основной диалог** — родителю возвращается только финальное резюме.
+AI делегирует задачи изолированным агентам. Каждый работает в своём окне и своём контексте, а в основной диалог возвращается только итоговое резюме. Черновики и промежуточные вызовы родительский чат не засоряют.
-**Как это работает:**
+Как это работает:
-1. Вы: _«Делегируй explore: найди все вызовы apiFetch»_
-2. AI вызывает `run_agent("explore", "...", "...")`
-3. Открывается **отдельное окно** с тем же логином DeepSeek
-4. Субагент работает в изоляции: `glob → read → grep → ...`
-5. Когда закончит — окно закрывается, в чат приходит **только резюме**
+1. Вы просите: «Делегируй explore: найди все вызовы apiFetch».
+2. AI вызывает `run_agent("explore", "...", "...")`.
+3. Открывается отдельное окно с тем же логином DeepSeek.
+4. Субагент работает в изоляции: `glob → read → grep`.
+5. Когда он заканчивает, окно закрывается, в чат приходит резюме.
-**Три способа завести агента:**
+Три способа завести агента:
-- **Вручную** — положите `cookie/agents/<имя>.md` с frontmatter в проект
-- **Через AI** — скажите _«Создай агента для ревью SQL-миграций»_ → AI вызовет `create_agent` и сразу его использует
-- **Готовые** — `explore`, `code-reviewer`, `git-committer`, `changelog-writer` уже в проекте
+- Вручную: положите `cookie/agents/<имя>.md` с frontmatter в проект.
+- Через AI: скажите «Создай агента для ревью SQL-миграций», AI вызовет `create_agent` и сразу его использует.
+- Взять готовый: `explore`, `code-reviewer`, `git-committer`, `changelog-writer` и `page-scripter` уже лежат в проекте.
-**Что защищает:**
+Что ограничивает субагента:
-- 🔒 **Whitelist инструментов** — в frontmatter агента указываете `tools: read, grep` → агент **физически не сможет** вызвать `bash` или `mysql`
-- 🚫 **Anti-recursion** — субагент не может запустить ещё одного субагента
-- ⏱ **maxTurns** — обрубает зацикливание (например, 40 шагов для коммиттера)
-- ⏲ **Timeout 10 мин** — принудительно закрывает зависшее окно
+- Белый список инструментов. Укажите `tools: read, grep`, и агент физически не сможет вызвать `bash` или `mysql`.
+- Запрет рекурсии. Субагент не может запустить ещё одного субагента.
+- Лимит шагов `maxTurns`, который обрубает зацикливание.
+- Таймаут 10 минут, после которого зависшее окно закрывается.
-**Пример агента:**
+Пример агента:
```markdown
---
@@ -101,100 +118,106 @@ tools: read, grep, glob
maxTurns: 20
---
-Ты — опытный эксперт по ревью кода...
+Ты опытный эксперт по ревью кода...
```
----
+### Цели
-### 🎯 **Цели — автономные многораундовые задачи**
+Команда `/goal` превращает задачу в самодвижущийся цикл: AI шаг за шагом идёт к цели без вашего участия между шагами.
-Команда `/goal` превращает задачу в **самодвижущийся цикл**: AI шаг за шагом продвигается к цели, пока не выполнит её — без вашего участия между шагами.
+- `/goal <описание>` задаёт цель, `/goal` показывает статус, `/goal stop|pause|resume` управляет ей.
+- Когда раунд ответа завершается, Cookie Code сам отправляет AI «продолжай».
+- Цель считается выполненной, когда AI вызывает инструмент `goalDone()`.
+- От зацикливания защищают лимит итераций (50) и остановка после трёх раундов без прогресса.
+- Панель «Цель» слева показывает текст цели, номер итерации, таймер и кнопки «Пауза» и «Выход».
+- У каждого чата своя цель.
+- Задавать цель и управлять ей можно из Telegram командой `/goal`, уведомления о старте и завершении приходят туда же.
-- **`/goal <описание>`** — задать цель; **`/goal`** — статус; **`/goal stop|pause|resume`** — управление
-- Когда раунд ответа завершается, Cookie Code **сам** отправляет AI «продолжай»
-- Завершение — когда AI вызывает инструмент `goalDone()`
-- **Защита от зацикливания:** лимит итераций (50) и остановка при 3 раундах без прогресса
-- **Панель «Цель»** слева: текст, итерация, таймер, кнопки Пауза/Выход
-- **Per-session:** у каждого чата своя цель
-- Задавать и управлять целью можно из **Telegram** (`/goal`), с уведомлениями о старте и завершении
+### Интерфейс
-### 🎨 **Красиво и настраиваемо**
+- Стеклянные панели с настраиваемым размытием и прозрачностью.
+- 27 обоев в комплекте.
+- Анимированные петы, которые реагируют на вашу работу.
+- Тёмная и светлая темы, переключение автоматическое или ручное.
+- Свой шрифт: положите файл в папку и выберите его в настройках.
+- RGB-эффект для никнейма.
-- **Стеклянный UI** — матовое стекло с настраиваемым размытием и прозрачностью
-- **27 обоев** — вручную отобранные фоны встроены
-- **Анимированные петы** — милые маскоты, реагирующие на вашу работу
-- **Тёмная/светлая тема** — автоматическое или ручное переключение
-- **Кастомные шрифты** — используйте свой шрифт
-- **RGB-эффекты** — анимированное свечение никнейма
+### Защита
-### 🔒 **Умная защита**
+- Подтверждение инструментов: рискованные команды выполняются только после вашего согласия.
+- Опасные паттерны: регулярные выражения для команд, которые нельзя запускать никогда.
+- Скрытые служебные сообщения: чат остаётся чистым, но AI видит полный контекст.
+- Белый список на сессию: подтвердите инструмент один раз, и до перезагрузки он работает свободно.
+- Правила проекта: AI принимает их через `readrules()` до начала работы.
+- Режим плана: AI сначала пишет план в `plan.md`, а не меняет код. План можно утвердить или отклонить, к строкам плана можно оставлять комментарии.
-- **Подтверждение инструментов** — подтверждайте рискованные команды (bash, запись файлов) перед выполнением
-- **Опасные паттерны** — regex-чёрный список команд, которые никогда не должны запускаться
-- **Скрытые служебные сообщения** — чистый UI чата, но AI всё равно видит полный контекст
-- **Белый список на сессию** — подтвердите инструмент один раз, он работает свободно до перезагрузки
-- **Правила проекта** — `.cookie/rules.md`: AI принимает их через `readrules()` до начала работы
-- **Режим плана** — AI сначала планирует (`plan.md`), а не меняет код; план утверждается, к строкам можно оставлять комментарии для ИИ
+### Промпты проекта
-### 💬 **Промпты проекта**
+Промпты лежат в `.cookie/prompts/*.md`, кнопка «Промпты» открывает их в оверлее. Промпт можно создать, изменить, удалить и вставить в поле ввода одной кнопкой. Из Telegram работает команда `/prompts`.
-- Хранятся в `.cookie/prompts/*.md`, кнопка **«Промпты»** в оверлее
-- Создать / изменить / удалить и вставить в поле ввода одной кнопкой
-- Из Telegram — команда `/prompts`
+### Telegram-бот
-### 📱 **Интеграция с Telegram-ботом**
+Управление с телефона:
-Управляйте всем с телефона:
+- `/status` показывает текущий проект, активные процессы и число задач.
+- `/diff` присылает незакоммиченные изменения с подсветкой синтаксиса.
+- `/log` листает историю коммитов и показывает diff выбранного коммита.
+- `/todos` управляет списком задач.
+- `/prompts` открывает промпты проекта.
+- `/screen` делает скриншот активного окна.
+- `/stop` убивает сбежавшие процессы.
-- `/status` — текущий проект, активные процессы, количество задач
-- `/diff` — смотрите незакоммиченные изменения с подсветкой синтаксиса
-- `/log` — листайте git-историю, показывайте diff коммитов
-- `/todos` — управляйте списком задач удалённо
-- `/prompts` — промпты проекта: вставить / удалить / создать
-- `/screen` — сделайте скриншот активного окна
-- `/stop` — убейте сбежавшие процессы
+Входящие сообщения печатаются в чат. Голосовые распознаются локальным Whisper и уходят в AI. Фото и файлы прикрепляются к полю ввода.
-**Входящие сообщения** → автоматически печатаются в чат
-**Голосовые сообщения** → распознаются через локальный Whisper и отправляются в AI
-**Фото/файлы** → прикрепляются к полю ввода чата
-
-### 📊 **Интеграция Git**
+### Git
Встроенный просмотрщик diff:
-- **Вкладка "Изменения"** — незакоммиченные изменения, построчные diff
-- **Вкладка "История"** — листайте коммиты, кликайте для просмотра полного diff
-- **Навигация** — прыгайте между hunks, фильтруйте добавленные/удалённые строки
-- **Мини-карта** — визуальный обзор изменений
-- **Внутристроковый diff** — посимвольная подсветка для точных правок
-- **Кнопка «Коммит»** — склеивает unified diff **всех** изменённых файлов и отправляет в чат готовое сообщение с просьбой закоммитить (можно позвать агента `git-committer` или закоммитить самому)
+- Вкладка «Изменения» показывает незакоммиченные правки построчно.
+- Вкладка «История» листает коммиты, клик открывает полный diff.
+- Навигация прыгает между hunks и фильтрует добавленные и удалённые строки.
+- Мини-карта даёт обзор изменений целиком.
+- Внутристрочный diff подсвечивает различия посимвольно.
+- Кнопка «Коммит» собирает unified diff всех изменённых файлов и отправляет в чат готовое сообщение с просьбой закоммитить. Дальше можно позвать агента `git-committer` или закоммитить самому.
-### ⌨️ **Горячие клавиши**
+### Горячие клавиши
| Клавиша | Действие |
| ------- | -------------------------------------------- |
| **F1** | Показать текущий CHANGELOG (окно What's New) |
+| **F11** | Полноэкранный режим |
+| **F12** | Инструменты разработчика (DevTools) |
+
+---
+
+## Что нового
-### 📈 **Дашборд статистики**
+Свежие крупные изменения:
-Отслеживайте продуктивность:
+- **Новый shell в стиле VS Code.** Переписан интерфейс: activity bar слева, панель страниц (Главная, Рабочие области, Файлы, Промпты, Скиллы, Субагенты, MCP, Token, О программе) и статус-бар. Окно без системной рамки со своими кнопками, F11 разворачивает на весь экран.
+- **Дерево файлов проекта.** Папки и подпапки раскрываются, глубина 6 уровней, до 500 элементов на папку. Кнопка **@** вставляет в чат `User mentioned file: <абсолютный путь>`, для папки `User mentioned folder: <абсолютный путь>`. Есть поиск по имени и пути, превью файла в Monaco и открытие в системе.
+- **Субагенты в отдельных лёгких окнах.** Открывается сразу чат DeepSeek с промптом и своим контекстом, без лишних панелей.
+- **Скорость и токены.** Скорость вывода считается по разнице серверного `accumulated_token_usage` и показывается в реальном времени. Контекст и скорость видны в статус-баре.
+- **Блок «Обнаружена задача» и История.** На Главной вместо пустой заглушки текущая команда или задача, индикатор выполнения, кнопка **Kill** и сворачиваемая история выполненных команд.
+- **Промпты проекта.** Хранятся в `.cookie/prompts/*.md`, создаются, редактируются и удаляются в интерфейсе, вставляются в поле ввода одной кнопкой.
+- **Обновления.** Кнопка «Проверить обновления» честно сообщает результат: обновлений нет, доступна новая версия, обновление скачано, ошибка или недоступно в dev-режиме. Версия на странице «О программе» берётся из последней записи `CHANGELOG.md`.
-- **Тепловая карта активности** — график вкладов в стиле GitHub
-- **Использование токенов** — тренды по дням/неделям
-- **Любимые модели** — какой AI вы используете чаще
-- **Отслеживание серий** — самая длинная последовательность дней кодинга
+### Статистика
+
+- Тепловая карта активности в стиле GitHub.
+- Использование токенов по дням и неделям.
+- Любимые модели.
+- Самая длинная серия дней с кодом.
---
-## 🚀 Быстрый старт
+## Быстрый старт
-### Скачать бинарник (рекомендуется)
+### Скачать готовую сборку
-**Windows:**
-Скачать [CookieCode-Setup.exe](https://github.com/merfiDEV/Cookie-code/releases/latest) → Запустить установщик → Открыть
+**Windows:** скачайте [CookieCode-Setup.exe](https://github.com/merfiDEV/Cookie-code/releases/latest), запустите установщик, откройте приложение.
-**macOS:**
-Скачать [CookieCode.dmg](https://github.com/merfiDEV/Cookie-code/releases/latest) → Перетащить в Applications → Открыть
+**macOS:** скачайте [CookieCode.dmg](https://github.com/merfiDEV/Cookie-code/releases/latest), перетащите в Applications, откройте.
### Собрать из исходников
@@ -205,114 +228,119 @@ npm install
npm start
```
-**Требования:** Node.js 16+
+Нужен Node.js 16 или новее.
---
-## 📖 Использование
+## Использование
### Первый запуск
-1. Выберите директорию проекта
-2. Выберите тему (обои, стеклянные эффекты, пет)
-3. (Опционально) Настройте Telegram-бота
+1. Выберите каталог проекта.
+2. Выберите тему: обои, стеклянные эффекты, пет.
+3. При желании настройте Telegram-бота.
-### Начните кодить
+### Работа
-Просто общайтесь естественно:
+Просто общайтесь с AI:
```
Вы: "Покажи изменения, которые я сделал сегодня"
-AI: [запускает git diff] Вы изменили 3 файла...
+AI: запускает git diff и показывает три изменённых файла
Вы: "Напиши тесты для функции логина"
-AI: [читает auth.js, создаёт тесты, запускает их] ✅ Все 5 тестов прошли
+AI: читает auth.js, создаёт тесты, запускает их и сообщает результат
Вы: "Закоммить это"
-AI: [git commit] Закоммичено: "feat(auth): добавлены тесты логина"
+AI: делает git commit с сообщением "feat(auth): добавлены тесты логина"
```
-### Исследуйте
+Боковая панель открывает сессии, список задач, git diff и настройки.
-Откройте боковую панель для:
+---
-- 🗂️ Просмотра сессий
-- 📝 Управления задачами
-- 🔄 Просмотра git diff
-- ⚙️ Настройки
+## Встроенные инструменты
+
+В приложении зарегистрировано 44 инструмента. Основные:
+
+| Инструмент | Описание |
+| ------------------- | --------------------------------- |
+| `read` | Прочитать содержимое файла |
+| `write` | Создать или перезаписать файл |
+| `edit` | Применить точечную правку |
+| `glob` | Найти файлы по шаблону |
+| `grep` | Поиск по содержимому файлов |
+| `bash` / `pwsh` | Запуск shell-команд |
+| `mysql` | SQL-запросы |
+| `webFetch` | HTTP-запросы |
+| `todoWrite` | Списки задач |
+| `mcpCall` | Инструменты MCP-сервера |
+| `skillLoad` | Загрузка пользовательского скилла |
+| `run_agent` | Делегировать задачу субагенту |
+| `memorySave` | Записать факт в память |
+| `goalDone` | Завершить цель `/goal` |
+| `readrules` | Принять правила проекта |
+| `ask_user_question` | Задать уточняющий вопрос |
+| `exitPlanMode` | Отдать план из `plan.md` |
+| `attachFile` | Прикрепить файл к чату |
+| `cityTime` | Текущее время и город |
+
+Полные TypeScript-декларации лежат в [`tools/cuckoo-tools.d.ts`](tools/cuckoo-tools.d.ts).
---
-## 🛠️ Встроенные инструменты
-
-20+ инструментов из коробки:
-
-| Инструмент | Описание |
-| --------------- | -------------------------- |
-| `read` | Прочитать содержимое файла |
-| `write` | Создать/перезаписать файл |
-| `edit` | Применить патч |
-| `glob` | Найти файлы по паттерну |
-| `grep` | Поиск по содержимому |
-| `bash` / `pwsh` | Запуск shell-команд |
-| `git` | Git-операции |
-| `mysql` | SQL-запросы |
-| `webFetch` | HTTP-запросы |
-| `todoWrite` | Списки задач |
-| `mcpCall` | Инструменты MCP-сервера |
-| `goalDone` | Завершить цель (`/goal`) |
-| `readrules` | Принять правила проекта |
+## Настройка
----
+**Темы:** размытие фона, прозрачность панелей, цвет стекла.
+
+**Петы:** бросьте PNG или GIF в `userData/pets/` и выберите из сетки.
-## 🎨 Настройка
+**Шрифты:** бросьте `.ttf` или `.woff` в `userData/fonts/` и выберите из списка.
-**Темы:** Размытие фона, прозрачность панелей, стеклянные цвета
-**Петы:** Бросьте PNG/GIF в `userData/pets/`, выберите из сетки
-**Шрифты:** Бросьте `.ttf`/`.woff` в `userData/fonts/`, выберите из выпадающего списка
+**Скиллы:** папка с `SKILL.md` и необязательным `tool.js` в `.cuckoo/skills/<имя>/` для проекта или в `/skills/<имя>/` для всех проектов. Глобальный скилл перекрывает проектный с тем же именем.
---
-## 🤝 Контрибуции
+## Участие в разработке
-1. Форкните репозиторий
-2. Создайте ветку: `git checkout -b feature/amazing`
-3. Внесите изменения
-4. Тестируйте: `npm test`
-5. Коммитьте: `git commit -m 'feat: add feature'`
-6. Пушьте и открывайте PR
+1. Форкните репозиторий.
+2. Создайте ветку: `git checkout -b feature/amazing`.
+3. Внесите изменения.
+4. Прогоните тесты: `npm test`.
+5. Закоммитьте: `git commit -m 'feat: add feature'`.
+6. Отправьте ветку и откройте pull request.
-**Области, где нужна помощь:**
+Где нужна помощь:
-- 🌍 Переводы
-- 📚 Документация
-- 🐛 Отчёты об ошибках
-- ✨ Новые инструменты
+- Переводы.
+- Документация.
+- Отчёты об ошибках.
+- Новые инструменты.
---
-## 📜 Лицензия
+## Лицензия
-MIT — свободно использовать, изменять, распространять. Коммерческое использование разрешено.
+MIT. Используйте, изменяйте и распространяйте свободно, включая коммерческие проекты.
---
-## 🙏 Благодарности
+## Благодарности
-Собрано с [Electron](https://electronjs.org/), [DeepSeek](https://deepseek.com/), [Telegraf](https://github.com/telegraf/telegraf)
+Собрано на [Electron](https://electronjs.org/), [DeepSeek](https://deepseek.com/) и [Telegraf](https://github.com/telegraf/telegraf).
-Вдохновлено [Aider](https://github.com/paul-gauthier/aider), [Claude Desktop](https://claude.ai/download), [Cursor](https://cursor.sh/)
+Вдохновлено [Aider](https://github.com/paul-gauthier/aider), [Claude Desktop](https://claude.ai/download) и [Cursor](https://cursor.sh/).
---
-## ⭐ История звёзд
+## История звёзд
[](https://star-history.com/#merfiDEV/Cookie-code&Date)
-Если Cookie Code экономит ваше время, поставьте звезду!
+Если Cookie Code экономит ваше время, поставьте звезду.
---
- Сделано с 🍪 разработчиками, для разработчиков
+ Сделано с 🍪 разработчиками для разработчиков
diff --git a/README.ru.md b/README.ru.md
index ae37635..7847f54 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -5,7 +5,7 @@
-
+
@@ -16,19 +16,23 @@
English · Русский
-**Cookie Code** — AI-агент для рабочего стола с **нулевой стоимостью токенов**.
+**Cookie Code** превращает веб-чат DeepSeek в рабочее место разработчика. AI открывает файлы проекта, запускает команды, правит код и делает коммиты, а вы остаётесь в том же чате.
-Приложение встраивает веб-чат DeepSeek в нативное окно Electron, добавляет боковой оверлей и превращает чат в локальный исполнитель: AI генерирует вызовы инструментов (блоки JavaScript-кода), которые перехватываются, подтверждаются, выполняются в локальной песочнице и стримятся обратно в чат. Никакого API-ключа, никакой оплаты за токены — вы используете обычный веб-аккаунт.
+Приложение работает через ваш обычный веб-аккаунт DeepSeek. API-ключ не нужен, по токенам вы не платите.
---
## Зачем это нужно
-Веб-чаты прекрасно **думают**, но не могут **действовать** на вашей машине. Cookie Code замыкает этот цикл:
+Веб-чаты хорошо думают, но не действуют на вашей машине. DeepSeek не откроет файл, не запустит тест и не сделает коммит, поэтому код приходится копировать туда и обратно.
-- **Нулевая стоимость токенов** — всё идёт через веб-интерфейс DeepSeek, без API.
-- **Настоящий агентный цикл** — Думай → Действуй → Наблюдай → Повторяй. Работа с файлами, поиск по коду, shell-команды, запросы к БД, MCP-инструменты.
-- **Нативная оболочка** — Electron-обёртка с собственным оверлеем, темами и настройками.
+Cookie Code замыкает этот цикл. AI пишет блок с вызовом инструмента, приложение перехватывает его, выполняет в песочнице Node и возвращает результат в чат. Дальше цикл повторяется: думай, действуй, смотри результат.
+
+Что вы получаете:
+
+- Работу через веб-аккаунт DeepSeek без API-ключей и оплаты по токенам.
+- Полный агентный цикл: файлы, поиск по коду, shell-команды, запросы к БД, MCP-инструменты.
+- Нативную оболочку Electron с собственным оверлеем, темами и настройками.
---
@@ -36,171 +40,182 @@
### Выполнение инструментов
-- AI отправляет вызовы инструментов в виде блоков JavaScript (```cuckoo).
+- AI отправляет вызовы инструментов блоками JavaScript с меткой `cuckoo`.
- Каждый вызов перехватывается, показывается в оверлее и выполняется в песочнице Node.
-- Результаты автоматически стримятся в чат как системное сообщение.
+- Результаты автоматически стримятся в чат системным сообщением.
- Ненулевой код выхода shell (`[exit code: N]`) подсвечивается красным под соответствующим блоком.
### Инлайн tool-блоки
Каждый `cuckoo`-блок в чате превращается в раскрывающуюся карточку:
-- Иконка ▼ + название инструмента (Read / Write / Edit / Bash / Glob / Grep / PowerShell / Todo / WebFetch / MCP / MySQL / …)
-- Подсказка файла из первого аргумента
-- Клик — развернуть/свернуть
-- **Красный стиль + иконка ⚠** при ошибке выполнения
+- Иконка ▼ и название инструмента: Read, Write, Edit, Bash, Glob, Grep, PowerShell, Todo, WebFetch, MCP, MySQL и другие.
+- Подсказка с файлом из первого аргумента.
+- Клик разворачивает и сворачивает карточку.
+- При ошибке карточка получает красный стиль и иконку ⚠.
-Стили сохраняются после перезагрузки страницы — восстанавливаются из `localStorage`.
+Стили переживают перезагрузку страницы: они восстанавливаются из `localStorage`.
### Мета ответа
-Под каждым ответом AI появляется автоматический бейдж:
+Под каждым ответом AI появляется бейдж:
```
⏱ 5.2s · ~380 tok
```
-- **Реальное время** ответа (от начала стрима до завершения)
-- **Оценка токенов** (`символы / 4`) — приблизительная
-- Сохраняется в `localStorage`, восстанавливается после перезагрузки
+- Реальное время ответа от начала стрима до завершения.
+- Оценка токенов по формуле «символы / 4».
+- Значение сохраняется в `localStorage` и восстанавливается после перезагрузки.
### Фоны
-- **27 вручную отобранных обоев** в комплекте
-- Выбор через сетку превью в **Настройки → Cookie Code**
-- Смена мгновенная, без перезагрузки
+- 27 вручную отобранных обоев в комплекте.
+- Выбор через сетку превью в **Настройки → Cookie Code**.
+- Смена мгновенная, перезагрузка не нужна.
### Шрифт
-Полный контроль над шрифтом интерфейса Cookie Code **и** страницы DeepSeek:
-
-- **Системный шрифт** по умолчанию — ничего не навязывается
-- **Встроенный Anthropic Mono** — на выбор одним кликом
-- **Свои шрифты** — положите файлы (`.ttf` / `.otf` / `.woff` / `.woff2`) в папку `/fonts` (кнопка **«Открыть папку шрифтов»**) и нажмите **«Обновить»** — шрифт появится в сетке превью
-- **Слайдер жирности** (100–900) — работает и для системного, и для любого кастомного шрифта
-- Выбор через сетку превью в **Настройки → Cookie Code**, применяется мгновенно и ко всему интерфейсу, и к странице DeepSeek
+Полный контроль над шрифтом интерфейса Cookie Code и страницы DeepSeek:
-Все настройки сохраняются в `cuckoo-settings.json` (`font`, `fontWeight`).
+- Системный шрифт по умолчанию, ничего не навязывается.
+- Встроенный Anthropic Mono выбирается одним кликом.
+- Свои шрифты: положите файлы `.ttf`, `.otf`, `.woff` или `.woff2` в папку `/fonts`, нажмите кнопку «Открыть папку шрифтов», затем «Обновить». Шрифт появится в сетке превью.
+- Слайдер жирности от 100 до 900 работает и для системного, и для своего шрифта.
+- Настройки сохраняются в `cuckoo-settings.json` в полях `font` и `fontWeight`.
-
+
### Блюр и прозрачность
-Полный контроль над стеклянным эффектом интерфейса:
+Стеклянный эффект настраивается целиком:
-- Блюр фонового изображения (0–30 px)
-- Блюр шапки и сайдбара
-- Прозрачность шапки / сайдбара / tool-блоков
-- Стекло tool-блоков
+- Блюр фонового изображения от 0 до 30 px.
+- Блюр шапки и сайдбара.
+- Прозрачность шапки, сайдбара и tool-блоков.
+- Стекло tool-блоков.
-Все настройки сохраняются в `cuckoo-settings.json`.
+Все значения лежат в `cuckoo-settings.json`.
### RGB-ник
-Ник пользователя в сайдбаре имеет **анимированный радужный градиент** (включено по умолчанию). Отключается в **Настройки → Cookie Code → Эффекты**.
+Ник пользователя в сайдбаре получает анимированный радужный градиент и включён по умолчанию. Отключается в **Настройки → Cookie Code → Эффекты**.
### Telegram-бот
-Управляйте Cookie Code и следите за ним с телефона:
-
-
+
-
-
+
+
-- **Уведомления об инструментах** — каждый вызов (успех/ошибка, имя, аргументы, результат) приходит в ваш Telegram-чат. Для `edit` показывается новый код (до 2000 символов).
-- **Ответы AI** — каждый текстовый ответ AI дублируется в Telegram (человекочитаемый текст без code-блоков).
-- **Входящие сообщения** — напишите боту, и сообщение попадёт в чат DeepSeek, как если бы вы набрали его сами.
-- **Команда `/todos`** — список задач активного окна прямо из Telegram.
-- **Команда `/prompts`** — промпты проекта прямо из бота: список с кнопками «Вставить» / «Удалить» и «Создать» с пошаговым вводом имени и текста.
-- **`/help`** — полная справка по командам бота.
-- **`/settings`** — интерактивное меню настроек с inline-кнопками. Все опции Cookie Code редактируются с телефона: внешний вид (кастомизация, RGB-ник, язык UI), стекло и панель (размытие, прозрачность, ширина, цвета), агент и приватность (режим подтверждения, скрытие служебных сообщений, авто-форматтеры, файловые чипы, затронутые файлы, список опасных паттернов), а также сам Telegram-бот (токен, chat ID, тумблеры уведомлений). Обои сознательно исключены.
-- **`/cancel`** — отменить ожидающий ввод значения.
-- Лёгкий клиент **без зависимостей** (long-polling, без VPS и webhook).
-- Настройка в **Настройки → Cookie Code → Telegram-бот** (токен от @BotFather + chat ID) или прямо из Telegram через `/settings`.
+- Уведомления об инструментах: каждый вызов с успехом или ошибкой, именем, аргументами и результатом приходит в ваш чат. Для `edit` показывается новый код до 2000 символов.
+- Ответы AI дублируются в Telegram как обычный текст без code-блоков.
+- Входящие сообщения: напишите боту, и текст попадёт в чат DeepSeek, как если бы вы набрали его сами.
+- `/todos` показывает список задач активного окна.
+- `/prompts` открывает промпты проекта: список с кнопками «Вставить» и «Удалить», плюс создание с пошаговым вводом имени и текста.
+- `/help` выводит полную справку по командам.
+- `/settings` открывает интерактивное меню с inline-кнопками. С телефона правятся внешний вид (кастомизация, RGB-ник, язык), стекло и панель (размытие, прозрачность, ширина, цвета), агент и приватность (режим подтверждения, скрытие служебных сообщений, авто-форматтеры, файловые чипы, затронутые файлы, список опасных паттернов), а также сам бот (токен, chat ID, тумблеры уведомлений). Обои в меню намеренно не вынесены.
+- `/cancel` отменяет ожидающий ввод.
+- Клиент лёгкий и без зависимостей: long-polling, без VPS и webhook.
+- Настройка идёт в **Настройки → Cookie Code → Telegram-бот** (токен от @BotFather и chat ID) или из самого Telegram через `/settings`.
### Чистое окно
-Без системного меню Electron — приложение сразу открывается в DeepSeek. Все стандартные горячие клавиши (Ctrl+C/V, Ctrl+R, F12) работают.
+Системного меню Electron нет, приложение сразу открывается в DeepSeek. Стандартные сочетания клавиш (Ctrl+C, Ctrl+V, Ctrl+R, F12) работают.
### Двухуровневая память
-AI помнит **и вас, и проект** — память разделена на два независимых уровня:
+AI помнит и вас, и проект, причём память разделена на два независимых уровня:
| Уровень | Где хранится | Что помнит |
| ------------- | ---------------------------------------------- | ------------------------------------------------------------------------ |
| 🌍 Глобальная | `/memory.md` | Факты о пользователе и системе: имя, ОС, GPU, предпочтения по стилю кода |
| 🗂 Проектная | `/.cookie/memory/ProjectMemory.md` | Соглашения, архитектурные решения, важные пути, стек конкретного проекта |
-- Инструменты `memorySave(text, scope?)`, `memoryRead(scope?)`, `memoryClear(scope?)` принимают `scope`: `'project'` | `'global'` (а `memoryRead` ещё `'all'`).
-- По умолчанию `memorySave` пишет в **проектную** память, если проект инициализирован, иначе в глобальную.
+- Инструменты `memorySave(text, scope?)`, `memoryRead(scope?)` и `memoryClear(scope?)` принимают `scope` со значениями `project`, `global`, а `memoryRead` ещё и `all`.
+- По умолчанию `memorySave` пишет в проектную память, если проект инициализирован, иначе в глобальную.
- Абсолютные пути к обоим файлам подставляются в системный промпт и доступны в JS-скриптах как `globalThis.memoryPath` и `globalThis.projectMemoryPath`.
-- Файлы открываются, очищаются и показывают статистику отдельно для каждого уровня — в **Настройки → Cookie Code**.
-- Проектная память лежит в `.gitignore` — личные заметки AI не коммитятся.
+- Файлы открываются, очищаются и показывают статистику отдельно для каждого уровня в **Настройки → Cookie Code**.
+- Проектная память лежит в `.gitignore`, поэтому личные заметки AI не коммитятся.
### Горячие клавиши
| Клавиша | Действие |
| ------- | -------------------------------------------- |
| **F1** | Показать текущий CHANGELOG (окно What's New) |
+| **F11** | Полноэкранный режим |
+| **F12** | Инструменты разработчика (DevTools) |
+
+Окно What's New (F1) перетаскивается за шапку и подстраивает ширину под экран.
-Окно What's New (F1) можно **перетаскивать за шапку** и оно адаптируется по ширине под экран.
+## Что нового
+
+Свежие крупные изменения:
+
+- **Shell в стиле VS Code.** Интерфейс переписан: activity bar, боковые страницы (Главная, Рабочие области, Файлы, Промпты, Скиллы, Субагенты, MCP, Token, О программе) и статус-бар. Окно без системной рамки со своими кнопками, F11 разворачивает на весь экран.
+- **Дерево файлов проекта.** Папки и подпапки раскрываются, кнопка **@** вставляет в чат `User mentioned file: <абсолютный путь>` или `folder` для папки. Есть превью в Monaco и открытие в системе.
+- **Субагенты в лёгких окнах.** Открывается только чат DeepSeek с промптом и изолированным контекстом, без shell-обвязки.
+- **TPS и токены.** Скорость вывода считается по разнице серверного `accumulated_token_usage`, с запасной оценкой по длине текста. Контекст и скорость видны в статус-баре.
+- **Блок «Обнаружена задача» и История.** На Главной текущая команда или задача, индикатор выполнения, кнопка **Kill** и сворачиваемая история выполненных команд.
+- **Промпты проекта.** Лежат в `.cookie/prompts/*.md`, создаются, редактируются и удаляются, вставляются в поле ввода одним кликом, при желании с авто-отправкой.
+- **Обновления.** «Проверить обновления» честно сообщает результат: актуально, доступна новая версия, скачано, ошибка или недоступно в dev-режиме. Версия на странице «О программе» берётся из последней записи `CHANGELOG.md`.
+- **Прочее.** Клик по агенту или скиллу вставляет `Use the agent` или `Use the skill`; иконка приложения на странице «О программе» берётся из билда; heatmap статистики стал компактнее; агенты и скиллы ищутся в `cookie/agents`, `.cuckoo/agents` и `~/.cookie/agents`.
### Перенос контекста
Длинный чат можно продолжить в новом, не теряя наработок:
-- Кнопка **«Перенести контекст»** в панели Cookie Code
-- История текущего чата читается из DOM, **AI сжимает её в структурный конспект** (цель, решения, изменённые файлы, открытые вопросы)
-- Новый чат открывается автоматически, конспект вставляется как контекст — работа продолжается с того же места
-- Длинные истории автоматически подрезаются по оценке токенов
+- Кнопка **«Перенести контекст»** в панели Cookie Code.
+- История текущего чата читается из DOM, AI сжимает её в структурный конспект: цель, решения, изменённые файлы, открытые вопросы.
+- Новый чат открывается автоматически, конспект вставляется как контекст, работа продолжается с того же места.
+- Длинные истории автоматически подрезаются по оценке токенов.
### Инициализация проекта
-Выберите каталог проекта один раз — AI получит дерево каталога и системный промпт, адаптированный к реальному проекту. Все дальнейшие вызовы инструментов разрешают пути относительно этого каталога.
+Выберите каталог проекта один раз. AI получит дерево каталога и системный промпт, собранный под реальный проект. Дальше все вызовы инструментов разрешают пути относительно этого каталога.
### Поддержка MCP
-Формат конфигурации, совместимый с Claude Desktop. Поддерживаются MCP-серверы `stdio` и `http` типов. Управление серверами и инструментами — из оверлея.
+Формат конфигурации совместим с Claude Desktop. Поддерживаются MCP-серверы типов `stdio` и `http`. Серверы и инструменты управляются из оверлея.
### Скиллы
-Поместите папку в `.cuckoo/skills//` с файлом `SKILL.md` (и опциональным `tool.js`) — она станет вызываемой через `skillList`, `skillLoad`, `skillExecute`.
+Положите папку в `.cuckoo/skills//` с файлом `SKILL.md` и необязательным `tool.js`, и она станет вызываемой через `skillList`, `skillLoad` и `skillExecute`.
-Skill бывают двух уровней: **глобальные** (`/skills//`) и **проектные** (`/.cuckoo/skills//`). При совпадении имён глобальный перекрывает проектный.
+Скиллы бывают двух уровней: глобальные в `/skills//` и проектные в `/.cuckoo/skills//`. При совпадении имён глобальный перекрывает проектный.
### Промпты проекта
-Сохраняйте часто используемые промпты и вставляйте их в чат одной кнопкой. Промпты лежат в `.cookie/prompts/*.md` (один файл — один промпт). Кнопка **«Промпты»** в оверлее открывает панель: создать / изменить / удалить промпт и вставить его текст в поле ввода (только текст, без отправки). Из Telegram — команда `/prompts`.
+Часто используемые промпты вставляются в чат одной кнопкой. Они лежат в `.cookie/prompts/*.md`, один файл на промпт. Кнопка **«Промпты»** в оверлее открывает панель: создать, изменить, удалить промпт и вставить его текст в поле ввода. Из Telegram работает команда `/prompts`.
### Субагенты
-
-
+
+
-Cookie Code умеет **делегировать задачи изолированным AI-агентам**. Каждый субагент работает в **отдельном окне** с тем же partition (общий логин DeepSeek), в **своём контексте**, и возвращает родителю **только финальное резюме** — черновики, поиски и tool-вызовы не засоряют основной диалог.
+Cookie Code делегирует задачи изолированным AI-агентам. Каждый субагент работает в отдельном окне с тем же partition и общим логином DeepSeek, в своём контексте, и возвращает родителю только финальное резюме. Черновики, поиски и tool-вызовы основной диалог не засоряют.
-**Пример:**
+Пример:
-1. Вы: _«Делегируй explore: найди все вызовы apiFetch»_
-2. AI вызывает `run_agent("explore", "найди все вызовы apiFetch")`
-3. Открывается второе окно, туда автоматически уходит системный промпт + задача
-4. Субагент работает: `glob → read → grep → ...`
-5. Когда напишет финал **без** `cuckoo`-блоков — окно закрывается, в родительский чат приходит только резюме
+1. Вы просите: «Делегируй explore: найди все вызовы apiFetch».
+2. AI вызывает `run_agent("explore", "найди все вызовы apiFetch")`.
+3. Открывается второе окно, туда автоматически уходит системный промпт и задача.
+4. Субагент работает: `glob → read → grep`.
+5. Когда он пишет финал без `cuckoo`-блоков, окно закрывается, а в родительский чат приходит только резюме.
-**Три способа завести агента:**
+Три способа завести агента:
-- **Вручную** — положите `cookie/agents/.md` с frontmatter в проект
-- **Через AI** — попросите: _«Создай агента для ревью SQL-миграций»_ — AI вызовет `create_agent` и сможет его сразу использовать
-- **Готовые** — в проекте уже есть `explore`, `code-reviewer`, `git-committer`, `changelog-writer`
+- Вручную: положите `cookie/agents/.md` с frontmatter в проект.
+- Через AI: попросите «Создай агента для ревью SQL-миграций», AI вызовет `create_agent` и сможет сразу его использовать.
+- Взять готовый: в проекте уже есть `explore`, `code-reviewer`, `git-committer`, `changelog-writer` и `page-scripter`.
-**Формат файла агента** (`<проект>/cookie/agents/<имя>.md`):
+Формат файла агента (`<проект>/cookie/agents/<имя>.md`):
```markdown
---
@@ -210,91 +225,85 @@ tools: read, grep, glob
maxTurns: 20
---
-Ты — опытный эксперт по ревью кода. Проверь указанный код, найди
+Ты опытный эксперт по ревью кода. Проверь указанный код, найди
реальные проблемы и дай рекомендации.
```
-**Поля frontmatter:**
-
-| Поле | Обязательно | Описание |
-| ------------- | ----------- | ---------------------------------------------------------- |
-| `name` | нет | Имя агента (по умолчанию — имя файла без `.md`) |
-| `description` | **да** | Когда делегировать. Без него агент игнорируется |
-| `tools` | нет | Список разрешённых инструментов через запятую. Пусто = все |
-| `maxTurns` | нет | Лимит шагов 1..1000 (защита от зацикливания) |
+Поля frontmatter:
-**Изоляция и защита:**
+| Поле | Обязательно | Описание |
+| ------------- | ----------- | --------------------------------------------------------- |
+| `name` | нет | Имя агента, по умолчанию имя файла без `.md` |
+| `description` | **да** | Когда делегировать. Без него агент игнорируется |
+| `tools` | нет | Разрешённые инструменты через запятую. Пусто означает все |
+| `maxTurns` | нет | Лимит шагов от 1 до 1000, защита от зацикливания |
-- 🔒 **Whitelist инструментов** — `tools: read, grep` → агент **физически не сможет** вызвать `bash`, `mysql`, `deleteFile` — блокировка на двух уровнях (JsRunner + main IPC)
-- 🚫 **Anti-recursion** — субагент не может вызвать `run_agent`
-- ⏱ **maxTurns** — обрубает бесконечные циклы
-- ⏲ **Timeout 10 мин** — принудительно закрывает зависшее окно
-- 📁 **Общий projectDir** — субагент видит ту же рабочую папку, что родитель
-- 🎯 **Прогрессивное раскрытие** — в системный промпт родителя идут только `name` + `description` каждого агента, полный `systemPrompt` читается только при запуске
+Изоляция и защита:
-**Уведомления в Telegram:**
+- 🔒 **Белый список инструментов.** С `tools: read, grep` агент физически не сможет вызвать `bash`, `mysql` или `deleteFile`: блокировка стоит на двух уровнях, в JsRunner и в main IPC.
+- 🚫 **Запрет рекурсии.** Субагент не может вызвать `run_agent`.
+- ⏱ **maxTurns** обрубает бесконечные циклы.
+- ⏲ **Таймаут 10 минут** принудительно закрывает зависшее окно.
+- 📁 **Общий projectDir.** Субагент видит ту же рабочую папку, что и родитель.
+- 🎯 **Прогрессивное раскрытие.** В системный промпт родителя идут только `name` и `description`, полный `systemPrompt` читается при запуске.
-При делегировании в TG приходят:
+Уведомления в Telegram:
-1. Карточка запуска: `🚀 ИИ делегирует задачу субагенту` + имя + задача
-2. Каждый tool-вызов агента: `🤖 Агент: explore` + `📖 Reading file.js`
-3. Финальный результат: `🎯 Субагент вернул результат` + резюме
+1. Карточка запуска: `🚀 ИИ делегирует задачу субагенту`, имя и задача.
+2. Каждый tool-вызов агента: `🤖 Агент: explore` и `📖 Reading file.js`.
+3. Финальный результат: `🎯 Субагент вернул результат` и резюме.
### Цели (goal-режим)
-Команда `/goal` превращает одну задачу в **автономный многораундовый цикл**: AI сам продвигается шаг за шагом, пока не выполнит цель — без вашего участия между шагами.
+Команда `/goal` превращает одну задачу в автономный многораундовый цикл: AI продвигается шаг за шагом, пока не выполнит цель, без вашего участия между шагами.
-**Как работает:**
+Как это работает:
-1. Введите в чате `/goal <описание цели>` (или задайте цель из Telegram: `/goal <описание>`)
-2. AI получает инструкцию цели и начинает работу
-3. Когда раунд ответа завершается (без tool-вызовов), Cookie Code **автоматически** отправляет AI «продолжай»
-4. Когда цель выполнена — AI вызывает инструмент `goalDone()` и цикл останавливается
+1. Введите в чате `/goal <описание цели>` или задайте цель из Telegram.
+2. AI получает инструкцию цели и начинает работу.
+3. Когда раунд ответа завершается без tool-вызовов, Cookie Code автоматически отправляет AI «продолжай».
+4. Когда цель выполнена, AI вызывает `goalDone()` и цикл останавливается.
-**Управление:**
+Управление:
| Команда | Действие |
| ------------------------------ | ---------------------------- |
| `/goal <текст>` | Задать цель |
| `/goal` | Показать статус текущей цели |
| `/goal stop` | Остановить цель |
-| `/goal pause` / `/goal resume` | Пауза / возобновить |
+| `/goal pause` / `/goal resume` | Пауза и возобновление |
-**Панель «Цель»:** плавающая панель слева показывает текст цели, номер итерации, время работы и кнопки **Пауза** / **Выход**. Её можно перетаскивать.
+Панель «Цель» слева показывает текст цели, номер итерации, время работы и кнопки **Пауза** и **Выход**. Панель можно перетаскивать.
-**Защита от зацикливания:**
+Защита от зацикливания:
-- ⏱ **Лимит итераций** — по умолчанию 50 раундов (настройка `cuckoo-goal-max-iterations`)
-- 🔁 **Нет прогресса** — если 3 раунда подряд одинаковый вывод, цель останавливается
-- ⏸ **Ручная остановка** — `/goal stop` или кнопка «Выход» мгновенно прерывают цикл
+- ⏱ Лимит итераций: по умолчанию 50 раундов, настройка `cuckoo-goal-max-iterations`.
+- 🔁 Нет прогресса: если три раунда подряд дают одинаковый вывод, цель останавливается.
+- ⏸ Ручная остановка: `/goal stop` или кнопка «Выход» прерывают цикл мгновенно.
-**Per-session:** у каждого чата своя цель — при переключении сессии состояние сохраняется отдельно.
-
-**Уведомления в Telegram:** при старте и завершении цели в TG приходят уведомления; задавать цель и управлять ею можно прямо из бота.
+У каждого чата своя цель, при переключении сессии состояние сохраняется отдельно. При старте и завершении цели в Telegram приходят уведомления, задавать цель и управлять ею можно из бота.
### Авто-форматтеры
-Каждый `write` и `edit` прогоняет файл через форматтер для конкретного языка — код AI автоматически приводится к стилю вашего проекта. Не нужно вручную запускать `prettier --write`, стиль не мешает в diff.
-
-Встроенные форматтеры:
+Каждый `write` и `edit` прогоняет файл через форматтер для его языка, поэтому код AI сразу приводится к стилю проекта. Запускать `prettier --write` вручную не нужно, и стиль не мешает в diff.
-| Форматтер | Для чего | Что нужно |
-| -------------- | ------------------------------------------ | ------------------------------------------------------------------------------- |
-| `prettier` | `.js .jsx .ts .tsx .json .css .md .yaml` … | `prettier` в ближайшем `package.json` + бинарь в `node_modules/.bin` или `PATH` |
-| `biome` | то же, что prettier | `biome.json` / `biome.jsonc` в проекте |
-| `gofmt` | `.go` | `gofmt` в `PATH` |
-| `ruff` | `.py .pyi` | `ruff` в `PATH` + `[tool.ruff]` в `pyproject.toml` (или `ruff.toml`) |
-| `rustfmt` | `.rs` | `rustfmt` в `PATH` |
-| `shfmt` | `.sh .bash` | `shfmt` в `PATH` |
-| `clang-format` | `.c .cpp .h` … | конфиг `.clang-format` + `clang-format` в `PATH` |
+| Форматтер | Для чего | Что нужно |
+| -------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------- |
+| `prettier` | `.js`, `.jsx`, `.ts`, `.tsx`, `.json`, `.css`, `.md`, `.yaml` | `prettier` в ближайшем `package.json` и бинарь в `node_modules/.bin` или `PATH` |
+| `biome` | то же, что prettier | `biome.json` или `biome.jsonc` в проекте |
+| `gofmt` | `.go` | `gofmt` в `PATH` |
+| `ruff` | `.py`, `.pyi` | `ruff` в `PATH` и `[tool.ruff]` в `pyproject.toml` или `ruff.toml` |
+| `rustfmt` | `.rs` | `rustfmt` в `PATH` |
+| `shfmt` | `.sh`, `.bash` | `shfmt` в `PATH` |
+| `clang-format` | `.c`, `.cpp`, `.h` | конфиг `.clang-format` и `clang-format` в `PATH` |
-- Определение **учитывает конфиг проекта**: ruff не запустится без `[tool.ruff]`, prettier — без зависимости в `package.json`. Никакого неожиданного форматирования чужого кода.
-- Ошибки форматтера глушатся — падение форматтера никогда не блокирует `write`/`edit`.
+- Определение учитывает конфиг проекта: ruff не запустится без `[tool.ruff]`, prettier без зависимости в `package.json`. Чужой код сам по себе не форматируется.
+- Ошибки форматтера глушатся, падение форматтера никогда не блокирует `write` и `edit`.
- Отключается через `"formattersEnabled": false` в `cuckoo-settings.json`.
### Персистентность сессии
-Логин, проекты и настройки хранятся в `%APPDATA%/cuckoo-ai-pro-session` (Windows) или аналогичном пути userData на macOS/Linux.
+Логин, проекты и настройки хранятся в `%APPDATA%/cuckoo-ai-pro-session` на Windows и в аналогичном пути userData на macOS и Linux.
---
@@ -302,25 +311,22 @@ maxTurns: 20
### Требования
-- Node.js >= 16.0.0
+- Node.js 16.0.0 или новее
- npm
### Из исходников
```bash
-# Клонировать
git clone https://github.com/merfiDEV/Cookie-code.git
cd Cookie-code
-# Установить зависимости
npm install
-# Если npm блокирует postinstall electron (allowScripts), одобрить:
+# Если npm блокирует postinstall electron (allowScripts), одобрите его:
# npm install-scripts ls
# npm install-scripts approve electron
# npm install
-# Запустить
npm start
```
@@ -341,23 +347,21 @@ npm run build:mac:dmg
## Использование
-1. Запустите приложение — оно сразу откроется в DeepSeek.
+1. Запустите приложение, оно сразу откроется в DeepSeek.
2. Войдите в свой аккаунт DeepSeek.
-3. Нажмите **«Инициализировать проект»** и выберите каталог. Теперь AI имеет доступ к дереву и системному промпту.
-4. Общайтесь с AI. Попросите отредактировать файлы, выполнить команды, найти что-то в коде.
+3. Нажмите **«Инициализировать проект»** и выберите каталог. Теперь AI видит дерево проекта и системный промпт.
+4. Общайтесь с AI: просите отредактировать файлы, выполнить команды, найти что-то в коде.
5. Вызовы инструментов в ответе AI перехватываются, показываются в оверлее и выполняются.
-6. Результаты автоматически отправляются обратно AI, цикл продолжается.
+6. Результаты автоматически уходят обратно AI, и цикл продолжается.
### Пример вызова инструмента
AI генерирует блок вида:
-````markdown
```cuckoo
const content = await read("src/index.js");
log(content);
```
-````
Cookie Code перехватывает его, выполняет в песочнице и возвращает результат AI.
@@ -365,42 +369,51 @@ Cookie Code перехватывает его, выполняет в песоч
## Доступные инструменты
-| Инструмент | Описание |
-| ------------------------------------------ | --------------------------------------------------------------------------- |
-| `read`, `readLines` | Чтение файлов (с номерами строк, offset/limit) |
-| `write`, `edit` | Создание / изменение файлов (авто-форматирование при сохранении — см. ниже) |
-| `deleteFile` | Удаление файла |
-| `glob`, `grep` | Поиск по файлам (на базе ripgrep) |
-| `bash`, `pwsh` | Выполнение команд |
-| `todoWrite` | Структурированный список задач |
-| `goalDone` | Завершить цель (`/goal`) — остановить авто-продвижение |
-| `webFetch` | Загрузка HTTP(S) как Markdown |
-| `mysql` | SQL-запросы |
-| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP-инструменты |
-| `skillList`, `skillLoad`, `skillExecute` | Пользовательские скиллы |
-| `readrules` | Прочитать и принять правила проекта (разблокирует инструменты в сессии) |
-| `run_agent` | Делегировать задачу субагенту (отдельное окно, изолированный контекст) |
-| `create_agent` | Создать нового субагента (файл `cookie/agents/<имя>.md`) |
-| `list_agents` | Список доступных субагентов (проект + пользователь) |
-| `read_agent` | Полный systemPrompt субагента по имени |
-| `openBrowserWindow`, `injectJS` | Окно браузера Electron + инъекция JS |
-
-Полные TypeScript-декларации — в `tools/cuckoo-tools.d.ts`.
+В приложении зарегистрировано 44 инструмента.
+
+| Инструмент | Описание |
+| ------------------------------------------ | -------------------------------------------------------------------------- |
+| `read`, `readLines` | Чтение файлов с номерами строк, offset и limit |
+| `write`, `edit` | Создание и изменение файлов, с авто-форматированием при сохранении |
+| `deleteFile` | Удаление файла |
+| `glob`, `grep` | Поиск по файлам на базе ripgrep |
+| `bash`, `pwsh` | Выполнение команд |
+| `todoWrite` | Структурированный список задач |
+| `goalDone` | Завершить цель `/goal` и остановить авто-продвижение |
+| `webFetch` | Загрузка HTTP(S) как Markdown |
+| `mysql` | SQL-запросы |
+| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP-инструменты |
+| `skillList`, `skillLoad`, `skillExecute` | Пользовательские скиллы |
+| `readrules` | Прочитать и принять правила проекта, что разблокирует инструменты в сессии |
+| `run_agent` | Делегировать задачу субагенту в отдельное окно с изолированным контекстом |
+| `create_agent` | Создать субагента в файле `cookie/agents/<имя>.md` |
+| `list_agents` | Список доступных субагентов из проекта и пользовательских |
+| `read_agent` | Полный systemPrompt субагента по имени |
+| `openBrowserWindow`, `injectJS` | Окно браузера Electron и инъекция JS |
+| `injectPageJS` | Выполнить JS на странице |
+| `ask_user_question` | Задать уточняющий вопрос с вариантами ответа |
+| `exitPlanMode` | Отдать план из `plan.md` на утверждение |
+| `generateCommitMessage` | Собрать статус и diff для сообщения коммита |
+| `attachFile`, `attachTelegram` | Прикрепить файл в чат или отправить его в Telegram |
+| `readPhoto` | Показать локальное изображение модели |
+| `cityTime` | Текущее время и город пользователя |
+
+Полные TypeScript-декларации лежат в `tools/cuckoo-tools.d.ts`.
---
## Кастомизация
-Cookie Code создан для того, чтобы его перестраивать: меняйте обои, настраивайте стеклянный эффект, задавайте акцентный цвет, пишите собственные скиллы или расширяйте набор инструментов.
+Cookie Code рассчитан на перестройку: меняйте обои, настраивайте стекло, задавайте акцентный цвет, пишите свои скиллы и расширяйте набор инструментов.
-
+
-
+
-
+
-
+
### Внешний вид
@@ -423,56 +436,56 @@ Cookie Code создан для того, чтобы его перестраив
### Пользовательские скиллы
-Добавьте собственный вызываемый скилл, не трогая код приложения:
+Свой вызываемый скилл добавляется без правки кода приложения:
```
.cuckoo/skills//
├── SKILL.md # инструкции для AI
-└── tool.js # опциональные экспортируемые функции
+└── tool.js # необязательные экспортируемые функции
```
AI получает к нему доступ через `skillList`, `skillLoad` и `skillExecute`.
### Правила проекта
-Проект может задать собственные правила, которые AI обязан принять перед началом работы:
+Проект задаёт правила, которые AI обязан принять до начала работы:
```
.cookie/rules.md
```
-Пока правила не приняты, инструменты (кроме `read`, `read_lines`, `file_read`, `memoryRead`, `readrules`) **заблокированы** — AI видит в начале системного промпта напоминание прочитать память и правила и вызвать `readrules()`. После вызова блокировка для этой сессии снимается.
+Пока правила не приняты, инструменты кроме `read`, `read_lines`, `file_read`, `memoryRead` и `readrules` заблокированы. В начале системного промпта AI видит напоминание прочитать память и правила и вызвать `readrules()`. После вызова блокировка для сессии снимается.
-- Если файла `.cookie/rules.md` нет — упоминания правил нет в промпте, а инструменты работают свободно.
-- Субагенты не блокируются — они работают без гейта правил.
+- Если файла `.cookie/rules.md` нет, упоминания правил в промпте нет, и инструменты работают свободно.
+- Субагенты не блокируются, они работают без гейта правил.
### Режим плана и комментарии
-Кнопка **«План»** рядом с тумблерами DeepSeek включает режим планирования: AI только исследует проект и пишет план в `plan.md`, не меняя код. Готовый план он отдаёт на утверждение через `exit_plan_mode()` — вы соглашаетесь (инструменты разблокируются) или отклоняете.
+Кнопка **«План»** рядом с тумблерами DeepSeek включает режим планирования. AI только исследует проект и пишет план в `plan.md`, не меняя код. Готовый план он отдаёт на утверждение через `exit_plan_mode()`, а вы соглашаетесь или отклоняете.
-- **Комментарии к строкам** — выделите фрагмент плана → появится кнопка «💬» → оставьте замечание прямо под нужной строкой. Можно комментировать несколько строк.
-- **При отклонении** замечания возвращаются модели как результат `exit_plan_mode` (текст + строка + выделение).
+- **Комментарии к строкам.** Выделите фрагмент плана, появится кнопка «💬», оставьте замечание прямо под нужной строкой. Комментировать можно несколько строк.
+- **При отклонении** замечания возвращаются модели как результат `exit_plan_mode`: текст, строка и выделение.
- **При согласии** комментарии прикладываются к запросу «Работай в соответствии с планом» и уходят в чат.
-- При согласии план можно утвердить и из Telegram.
+- План можно утвердить и из Telegram.
### Пользовательские инструменты
-Реализации инструментов лежат в `tools/` и работают в главном процессе. Добавьте функцию, объявите её в `tools/cuckoo-tools.d.ts` — и AI сможет вызывать её как любой встроенный инструмент.
+Реализации инструментов лежат в `tools/` и работают в главном процессе. Добавьте функцию, объявите её в `tools/cuckoo-tools.d.ts`, и AI сможет вызывать её как любой встроенный инструмент.
### Провайдер
-Адаптер DeepSeek находится в `src/providers/deepseek.js` — форкните его, чтобы подключить Cookie Code к другой платформе веб-чата.
+Адаптер DeepSeek находится в `src/providers/deepseek.js`. Форкните его, чтобы подключить Cookie Code к другой платформе веб-чата.
---
## Безопасность
-- Опциональный гейт подтверждения tool-вызовов (off / risky / all) — настраивается в приложении или через Telegram `/settings`
-- Таймаут команды 30 с, таймаут песочницы 60 с
-- Буфер вывода 1 МБ
-- Редактируемый блэклист опасных команд (rm -rf /, format, diskpart, …) — regex-паттерны, меняются прямо в настройках или через Telegram
-- Авто-форматтеры запускаются только когда этого требует конфиг проекта (конфиг-осознанное определение) и никогда не блокируют `write`/`edit`
-- Пути файлов ограничены каталогом проекта
+- Гейт подтверждения tool-вызовов с режимами off, risky и all. Настраивается в приложении или через Telegram `/settings`.
+- Таймаут команды 30 секунд, таймаут песочницы 60 секунд.
+- Буфер вывода 1 МБ.
+- Редактируемый чёрный список опасных команд (`rm -rf /`, `format`, `diskpart` и другие) из регулярных выражений. Меняется в настройках или через Telegram.
+- Авто-форматтеры запускаются только когда этого требует конфиг проекта и никогда не блокируют `write` и `edit`.
+- Пути файлов ограничены каталогом проекта.
---
@@ -505,7 +518,7 @@ AI получает к нему доступ через `skillList`, `skillLoad`
}
```
-Все настройки редактируются через **Настройки → Cookie Code**.
+Все настройки редактируются в **Настройки → Cookie Code**.
---
@@ -516,42 +529,32 @@ src/
├── main/ Главный процесс Electron
│ ├── index.js Точка входа, создание окон
│ ├── ipc.js IPC-обработчики
+│ ├── shell-ipc.js IPC для shell-интерфейса
+│ ├── git-gitops.js Git-операции
│ ├── settings-store Пользовательские настройки
│ ├── profile-manager Профили окон
-│ ├── session-store Сессия ↔ каталог проекта
+│ ├── session-store Сессия и каталог проекта
│ ├── mcp-client Интеграция MCP SDK
│ ├── skill-manager Загрузка скиллов
-│ ├── format-registry Встроенные форматтеры (prettier/biome/gofmt/ruff/...)
-│ ├── formatter Авто-формат после write/edit
-│ ├── window.js Реестр окон
-│ └── ...
+│ ├── format-registry Встроенные форматтеры
+│ ├── formatter Авто-формат после write и edit
+│ └── window.js Реестр окон
├── preload/
│ ├── api.js contextBridge → electronAPI
│ ├── index.js Инициализация
-│ ├── i18n/
-│ │ └── i18n.js RU/EN-переводы, хелпер `t(key, params)`
+│ ├── i18n/i18n.js Переводы RU и EN, хелпер t(key, params)
│ ├── dom/ Парсеры DOM и observers
-│ │ ├── observer.js Основной observer реплик
-│ │ ├── tool-render.js Инлайн tool-блоки
-│ │ ├── response-meta.js Бейдж ⏱ под ответом
-│ │ ├── settings-tab.js Вкладка Cookie Code в настройках
-│ │ ├── background.js Обои и блюр
-│ │ ├── context-port.js Перенос контекста чата
-│ │ ├── fonts.js Шрифт интерфейса и страницы
-│ │ └── ...
│ └── overlay/ Оверлей-панель
-│ ├── template.js buildOverlayHTML() + OVERLAY_CSS
-│ ├── diff-panel.js Панель «Изменения» (git) / «История»
-│ └── todo-panel.js Плавающий список задач
├── providers/
│ └── deepseek.js Адаптер платформы
├── ui/
-│ ├── backgrounds/ 27 обоев + registry.json
-│ ├── fonts/ Встроенные шрифты (Anthropic Mono)
-│ └── logos/
-tools/ Реализация инструментов (в главном процессе)
-└── cuckoo-tools.d.ts TypeScript-декларации для AI
-botsrc/ Интеграция Telegram-бота (без зависимостей)
+│ ├── shell/ Интерфейс в стиле VS Code (HTML, CSS, React)
+│ ├── backgrounds/ 27 обоев и registry.json
+│ ├── fonts/ Встроенные шрифты
+│ └── vendor/monaco Вендоренный Monaco Editor
+tools/ Реализация инструментов в главном процессе
+├── cuckoo-tools.d.ts TypeScript-декларации для AI
+botsrc/ Telegram-бот без зависимостей
├── telegram.js Клиент Telegram (long-polling)
└── index.js Настройки, уведомления, приём сообщений
```
diff --git a/assets/photo_2026-10-31_15-05-24.jpg b/assets/photo_2026-10-31_15-05-24.jpg
new file mode 100644
index 0000000..26c5a9e
Binary files /dev/null and b/assets/photo_2026-10-31_15-05-24.jpg differ
diff --git a/botsrc/i18n.js b/botsrc/i18n.js
index e11635d..41e81cf 100644
--- a/botsrc/i18n.js
+++ b/botsrc/i18n.js
@@ -455,6 +455,7 @@ const STRINGS = {
"longproc.body": "Команда выполняется более {sec} с:",
"longproc.kill": "🛑 Убить процесс",
"longproc.killed": "🛑 Процесс остановлен пользователем",
+ "longproc.killedPc": "🛑 Процесс остановлен с ПК",
"longproc.killFailed": "⚠️ Не удалось остановить процесс",
"longproc.gone": "Процесс уже завершён",
@@ -937,6 +938,7 @@ const STRINGS = {
"longproc.body": "Command has been running for over {sec}s:",
"longproc.kill": "🛑 Kill process",
"longproc.killed": "🛑 Process stopped by user",
+ "longproc.killedPc": "🛑 Process stopped from PC",
"longproc.killFailed": "⚠️ Failed to stop process",
"longproc.gone": "Process already finished",
diff --git a/botsrc/index.js b/botsrc/index.js
index 4350b04..ee37e07 100644
--- a/botsrc/index.js
+++ b/botsrc/index.js
@@ -11,6 +11,7 @@
const { telegramBot, TelegramBot } = require("./telegram");
const settingsStore = require("../src/main/settings-store");
const windowState = require("../src/main/window");
+const { getAIWebContents } = windowState;
const i18n = require("./i18n");
let started = false;
@@ -133,35 +134,10 @@ async function _sendToChat(text) {
if (!win || win.isDestroyed())
return { success: false, error: "нет активного окна" };
- const safe = JSON.stringify(String(text));
- const script = `(function(){
- const ta = document.querySelector('textarea[placeholder], textarea[name="search"], textarea.ds-scroll-area');
- if (!ta) return { ok: false, error: 'textarea not found' };
- const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
- setter.call(ta, ${safe});
- ta.dispatchEvent(new Event('input', { bubbles: true }));
- ta.focus();
- return { ok: true };
- })()`;
-
- await win.webContents.executeJavaScript(script, true);
- // Небольшая пауза, чтобы React обработал ввод.
- await new Promise((r) => setTimeout(r, 150));
- // Отправляем нативный Enter (тот же приём, что chat-send-enter).
- win.webContents.sendInputEvent({
- type: "keyDown",
- keyCode: "Return",
- key: "Enter",
- });
- win.webContents.sendInputEvent({
- type: "char",
- keyCode: "Return",
- key: "\r",
- });
- win.webContents.sendInputEvent({
- type: "keyUp",
- keyCode: "Return",
- key: "Enter",
+ // Send via IPC to view's preload (uses proper ProseMirror handling)
+ getAIWebContents(win).send("fill-input", {
+ text: String(text),
+ autoSend: true,
});
return { success: true };
} catch (err) {
@@ -178,7 +154,7 @@ async function _evalInWindow(script) {
if (!win || win.isDestroyed())
return { success: false, error: "нет активного окна" };
try {
- const result = await win.webContents.executeJavaScript(script, true);
+ const result = await getAIWebContents(win).executeJavaScript(script, true);
return { success: true, result };
} catch (err) {
return { success: false, error: err.message };
@@ -285,13 +261,13 @@ async function _captureActiveWindow(targetWin) {
win.focus();
if (typeof win.moveTop === "function") win.moveTop();
try {
- win.webContents.focus();
+ getAIWebContents(win).focus();
} catch (_) {}
// Даём окну отрисоваться/подняться.
await new Promise((r) => setTimeout(r, 350));
- const image = await win.webContents.capturePage();
+ const image = await getAIWebContents(win).capturePage();
const png = image.toPNG();
const outPath = path.join(
app.getPath("temp"),
@@ -347,6 +323,12 @@ const _planCallbackTokens = new Map();
* key = token ('k') → { pid, messageId }
*/
const _longProcessTokens = new Map();
+/**
+ * Обратный индекс: pid → Set для уведомлений о долгих процессах.
+ * Нужен, чтобы убрать кнопку «Убить процесс» из Telegram, когда процесс
+ * останавливают с ПК (overlay Kill / killAll), а не кнопкой в TG.
+ */
+const _longProcessByPid = new Map();
/**
* Реестр callback-кнопок выбора окна для /screen.
* key = token ('sc_' без префикса — храним 's'), value = windowId.
@@ -934,6 +916,12 @@ async function notifyLongProcess(pid, command, sec) {
pid: numPid,
messageId: res.messageId || null,
});
+ let set = _longProcessByPid.get(numPid);
+ if (!set) {
+ set = new Set();
+ _longProcessByPid.set(numPid, set);
+ }
+ set.add(token);
return { success: true, token };
}
@@ -969,6 +957,41 @@ async function _handleLongProcessCallback(token, ref, cbq) {
{ parseMode: "HTML", replyMarkup: { inline_keyboard: [] } },
);
}
+ const pidSet = _longProcessByPid.get(ref.pid);
+ if (pidSet) {
+ pidSet.delete(token);
+ if (pidSet.size === 0) _longProcessByPid.delete(ref.pid);
+ }
+}
+
+/**
+ * Убрать кнопку «Убить процесс» из Telegram, если процесс остановлен с ПК
+ * (overlay Kill / killAll), а не кнопкой в TG. Редактирует все связанные
+ * сообщения: убирает клавиатуру и помечает «процесс остановлен».
+ * @param {number|number[]} pid pid или массив pid
+ */
+async function notifyProcessKilled(pid) {
+ const pids = Array.isArray(pid) ? pid : [pid];
+ for (const p of pids) {
+ const numPid = Number(p);
+ if (!numPid) continue;
+ const set = _longProcessByPid.get(numPid);
+ if (!set) continue;
+ const tokens = Array.from(set);
+ _longProcessByPid.delete(numPid);
+ for (const token of tokens) {
+ const ref = _longProcessTokens.get(token);
+ _longProcessTokens.delete(token);
+ if (!ref || !ref.messageId) continue;
+ try {
+ await telegramBot.editMessageText(
+ ref.messageId,
+ _t("longproc.title") + "\n" + _t("longproc.killedPc"),
+ { parseMode: "HTML", replyMarkup: { inline_keyboard: [] } },
+ );
+ } catch (_) {}
+ }
+ }
}
/** Перерисовать сообщение с вопросами: отметить выбранное, убрать лишние кнопки. */
@@ -1798,14 +1821,9 @@ async function _cmdStop() {
const win = windowState.getParentWindow
? windowState.getParentWindow()
: windowState.getMainWindow();
- if (
- win &&
- !win.isDestroyed() &&
- win.webContents &&
- !win.webContents.isDestroyed()
- ) {
+ if (win && !win.isDestroyed() && !getAIWebContents(win).isDestroyed()) {
try {
- win.webContents.stop();
+ getAIWebContents(win).stop();
} catch (_) {}
}
const { processManager } = require("../src/main/process-manager");
@@ -2059,7 +2077,7 @@ async function _cmdNew() {
// Fire-and-forget: не await-им executeJavaScript, т.к. loadURL внутри
// newChat() выгружает контекст и промис не вернётся.
try {
- win.webContents
+ getAIWebContents(win)
.executeJavaScript(
"try { window.electronAPI.newChat(); } catch (e) {} true",
true,
@@ -2156,7 +2174,7 @@ async function _renderDiffImage(diffText, filePath, status) {
);
// Ждём отрисовку.
await new Promise((r) => setTimeout(r, 300));
- const wc = win.webContents;
+ const wc = getAIWebContents(win);
const size = await wc.executeJavaScript(
"({ w: document.body.scrollWidth, h: document.body.scrollHeight })",
true,
@@ -2416,9 +2434,9 @@ async function _sendGoalCommand(action, text) {
return { success: false, error: "нет активного окна" };
try {
if (action === "start") {
- win.webContents.send("goal-start", { text: String(text || "") });
+ getAIWebContents(win).send("goal-start", { text: String(text || "") });
} else {
- win.webContents.send("goal-control", { action });
+ getAIWebContents(win).send("goal-control", { action });
}
return { success: true };
} catch (err) {
@@ -2554,7 +2572,7 @@ async function _readTogglesState() {
})()`;
try {
- const res = await win.webContents.executeJavaScript(script, true);
+ const res = await getAIWebContents(win).executeJavaScript(script, true);
return res || { think: null, search: null };
} catch (err) {
_log("error", "_readTogglesState error:", err.message);
@@ -2583,7 +2601,7 @@ async function _toggleDeepSeek(name) {
})()`;
try {
- const res = await win.webContents.executeJavaScript(script, true);
+ const res = await getAIWebContents(win).executeJavaScript(script, true);
if (!res || !res.ok)
return { ok: false, error: (res && res.error) || "unknown" };
// Даём React время отрисовать новое состояние
@@ -3145,13 +3163,13 @@ async function _doInitProject(chatId, dir) {
let homeUrl = null;
try {
const { getProviderByUrl } = require("../src/providers");
- const provider = getProviderByUrl(win.webContents.getURL());
+ const provider = getProviderByUrl(getAIWebContents(win).getURL());
if (provider && provider.homeUrl) homeUrl = provider.homeUrl;
} catch (_) {}
if (!homeUrl) homeUrl = "https://chat.deepseek.com/";
try {
- await win.webContents.loadURL(homeUrl);
+ await getAIWebContents(win).loadURL(homeUrl);
} catch (err) {
return { success: false, error: err.message };
}
@@ -3168,13 +3186,15 @@ async function _doInitProject(chatId, dir) {
const { buildInitPrompt } = require("../src/main/project-context");
const combined = await buildInitPrompt(dir, providerId);
if (combined && !win.isDestroyed()) {
- win.webContents.send("initial-prompt", combined);
+ getAIWebContents(win).send("initial-prompt", combined);
sent = true;
}
} catch (_) {}
};
try {
- win.webContents.once("did-finish-load", () => setTimeout(doSend, 1200));
+ getAIWebContents(win).once("did-finish-load", () =>
+ setTimeout(doSend, 1200),
+ );
} catch (_) {}
setTimeout(doSend, 4000);
@@ -3552,7 +3572,7 @@ async function _navigateToSession(id) {
let url = null;
try {
const { getProviderByUrl } = require("../src/providers");
- const provider = getProviderByUrl(win.webContents.getURL());
+ const provider = getProviderByUrl(getAIWebContents(win).getURL());
if (provider && typeof provider.getSessionUrl === "function") {
url = provider.getSessionUrl(id);
} else if (provider && provider.sessionUrlBase) {
@@ -3561,7 +3581,7 @@ async function _navigateToSession(id) {
} catch (_) {}
if (!url) url = "https://chat.deepseek.com/a/chat/s/" + id;
try {
- await win.webContents.loadURL(url);
+ await getAIWebContents(win).loadURL(url);
return { success: true };
} catch (err) {
return { success: false, error: err.message };
@@ -3866,7 +3886,7 @@ function _tgTempDir() {
*/
async function _sendInWindow(win) {
try {
- const wc = win.webContents;
+ const wc = getAIWebContents(win);
const clickScript = `(function(){
const sels = ['button[type="submit"]','button[aria-label*="send"]','button[aria-label*="发送"]','button[data-testid="send-button"]','button[data-testid="send"]','.send-btn','.submit-btn'];
for (const s of sels) {
@@ -3918,14 +3938,14 @@ async function _insertImageToWindow(absPath, caption, send) {
ta.focus();
return { ok: true };
})()`;
- await win.webContents.executeJavaScript(script, true);
+ await getAIWebContents(win).executeJavaScript(script, true);
await new Promise((r) => setTimeout(r, 150));
- win.webContents.sendInputEvent({
+ getAIWebContents(win).sendInputEvent({
type: "keyDown",
keyCode: "V",
modifiers: ["control"],
});
- win.webContents.sendInputEvent({
+ getAIWebContents(win).sendInputEvent({
type: "keyUp",
keyCode: "V",
modifiers: ["control"],
@@ -3970,7 +3990,7 @@ async function _attachFileToWindow(absPath, caption, send) {
mimeType,
UPLOAD_TIMEOUT_MS,
);
- const result = await win.webContents.executeJavaScript(code, true);
+ const result = await getAIWebContents(win).executeJavaScript(code, true);
if (!result || result.success !== true)
return {
success: false,
@@ -3987,7 +4007,7 @@ async function _attachFileToWindow(absPath, caption, send) {
ta.focus();
return { ok: true };
})()`;
- await win.webContents.executeJavaScript(script, true);
+ await getAIWebContents(win).executeJavaScript(script, true);
await new Promise((r) => setTimeout(r, 300));
if (send) await _sendInWindow(win);
}
@@ -5323,8 +5343,8 @@ function _notifySettingsChanged(patch) {
for (const win of wins) {
try {
if (!win || win.isDestroyed()) continue;
- if (!win.webContents || win.webContents.isDestroyed()) continue;
- win.webContents.send("cuckoo-settings-changed", patch || null);
+ if (getAIWebContents(win).isDestroyed()) continue;
+ getAIWebContents(win).send("cuckoo-settings-changed", patch || null);
} catch (_) {}
}
} catch (_) {}
@@ -5530,6 +5550,7 @@ module.exports = {
requestPlanApproval,
cancelPlanApproval,
notifyLongProcess,
+ notifyProcessKilled,
askQuestion,
setOnQuestionAnswered,
setOnQuestionCancelled,
diff --git a/package-lock.json b/package-lock.json
index 6df79ed..6d6a406 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,11 +20,18 @@
"docx": "^9.7.1",
"electron-log": "^5.4.4",
"electron-updater": "^6.8.9",
+ "esbuild": "^0.24.0",
+ "katex": "^0.16.11",
"material-icon-theme": "^5.38.1",
+ "monaco-editor": "^0.52.0",
"mysql2": "^3.24.2",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
"turndown": "^7.2.4"
},
"devDependencies": {
+ "@types/react": "^18.3.31",
+ "@types/react-dom": "^18.3.7",
"electron": "^33.0.0",
"electron-builder": "^24.13.3",
"prettier": "^3.3.3"
@@ -304,6 +311,390 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
+ "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz",
+ "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz",
+ "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz",
+ "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz",
+ "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz",
+ "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz",
+ "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz",
+ "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz",
+ "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz",
+ "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz",
+ "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz",
+ "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz",
+ "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz",
+ "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz",
+ "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz",
+ "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz",
+ "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz",
+ "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz",
+ "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz",
+ "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz",
+ "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz",
+ "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz",
+ "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz",
+ "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@hono/node-server": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/@hono/node-server/-/node-server-2.1.1.tgz",
@@ -672,6 +1063,34 @@
"xmlbuilder": ">=11.0.1"
}
},
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.31",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz",
+ "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
"node_modules/@types/responselike": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/@types/responselike/-/responselike-1.0.3.tgz",
@@ -1885,6 +2304,13 @@
"node": ">= 8"
}
},
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
@@ -2560,6 +2986,45 @@
"dev": true,
"optional": true
},
+ "node_modules/esbuild": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz",
+ "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.24.0",
+ "@esbuild/android-arm": "0.24.0",
+ "@esbuild/android-arm64": "0.24.0",
+ "@esbuild/android-x64": "0.24.0",
+ "@esbuild/darwin-arm64": "0.24.0",
+ "@esbuild/darwin-x64": "0.24.0",
+ "@esbuild/freebsd-arm64": "0.24.0",
+ "@esbuild/freebsd-x64": "0.24.0",
+ "@esbuild/linux-arm": "0.24.0",
+ "@esbuild/linux-arm64": "0.24.0",
+ "@esbuild/linux-ia32": "0.24.0",
+ "@esbuild/linux-loong64": "0.24.0",
+ "@esbuild/linux-mips64el": "0.24.0",
+ "@esbuild/linux-ppc64": "0.24.0",
+ "@esbuild/linux-riscv64": "0.24.0",
+ "@esbuild/linux-s390x": "0.24.0",
+ "@esbuild/linux-x64": "0.24.0",
+ "@esbuild/netbsd-x64": "0.24.0",
+ "@esbuild/openbsd-arm64": "0.24.0",
+ "@esbuild/openbsd-x64": "0.24.0",
+ "@esbuild/sunos-x64": "0.24.0",
+ "@esbuild/win32-arm64": "0.24.0",
+ "@esbuild/win32-ia32": "0.24.0",
+ "@esbuild/win32-x64": "0.24.0"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
@@ -3455,6 +3920,12 @@
"url": "https://github.com/sponsors/panva"
}
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
"node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.3.1.tgz",
@@ -3564,6 +4035,31 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/katex": {
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz",
+ "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==",
+ "funding": [
+ "https://opencollective.com/katex",
+ "https://github.com/sponsors/katex"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^8.3.0"
+ },
+ "bin": {
+ "katex": "cli.js"
+ }
+ },
+ "node_modules/katex/node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -3693,6 +4189,18 @@
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0"
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
@@ -3905,6 +4413,12 @@
"node": ">=10"
}
},
+ "node_modules/monaco-editor": {
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz",
+ "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
+ "license": "MIT"
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
@@ -4315,6 +4829,31 @@
"node": ">= 0.10"
}
},
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
"node_modules/read-config-file": {
"version": "6.3.2",
"resolved": "https://registry.npmmirror.com/read-config-file/-/read-config-file-6.3.2.tgz",
@@ -4479,6 +5018,15 @@
"node": ">=11.0.0"
}
},
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
diff --git a/package.json b/package.json
index 49bb700..e81e2ee 100644
--- a/package.json
+++ b/package.json
@@ -4,22 +4,25 @@
"description": "DeepSeek 桌面应用——内嵌浏览器,自动识别 AI 回复中的命令和工具调用并执行",
"main": "main.js",
"scripts": {
- "start": "node start.js",
+ "build:shell": "node scripts/build-shell.mjs",
+ "copy:monaco": "node scripts/copy-monaco.mjs",
+ "start": "node scripts/build-shell.mjs && node scripts/copy-monaco.mjs && node start.js",
"test": "node --test --test-concurrency=1 test/tools/*.test.js test/main/*.test.js test/preload/*.test.js",
"test:coverage": "node --test --test-concurrency=1 --experimental-test-coverage --test-reporter=lcov test/tools/*.test.js test/main/*.test.js test/preload/*.test.js > coverage.lcov",
"test:ci": "node --test --test-concurrency=1 test/tools/*.test.js test/main/*.test.js test/preload/*.test.js",
- "build": "electron-builder --publish always",
- "build:win": "electron-builder --win --publish always",
- "build:win:nsis": "electron-builder --win --config.win.target=nsis --publish always",
- "build:win:portable": "electron-builder --win --config.win.target=portable --publish always",
- "build:mac": "electron-builder --mac --publish always",
- "build:mac:dmg": "electron-builder --mac --config.mac.target=dmg --publish always",
- "build:local": "electron-builder --publish never",
- "build:win:local": "electron-builder --win --publish never",
- "build:win:nsis:local": "electron-builder --win --config.win.target=nsis --publish never",
- "build:win:portable:local": "electron-builder --win --config.win.target=portable --publish never",
- "build:mac:local": "electron-builder --mac --publish never",
- "build:mac:dmg:local": "electron-builder --mac --config.mac.target=dmg --publish never"
+ "build": "npm run build:shell && npm run copy:monaco && electron-builder --publish always",
+ "build:win": "npm run build:shell && npm run copy:monaco && electron-builder --win --publish always",
+ "build:win:nsis": "npm run build:shell && npm run copy:monaco && electron-builder --win --config.win.target=nsis --publish always",
+ "build:win:portable": "npm run build:shell && npm run copy:monaco && electron-builder --win --config.win.target=portable --publish always",
+ "build:mac": "npm run build:shell && npm run copy:monaco && electron-builder --mac --publish always",
+ "build:mac:dmg": "npm run build:shell && npm run copy:monaco && electron-builder --mac --config.mac.target=dmg --publish always",
+ "build:local": "npm run build:shell && npm run copy:monaco && electron-builder --publish never",
+ "build:win:local": "npm run build:shell && npm run copy:monaco && electron-builder --win --publish never",
+ "build:win:nsis:local": "npm run build:shell && npm run copy:monaco && electron-builder --win --config.win.target=nsis --publish never",
+ "build:win:portable:local": "npm run build:shell && npm run copy:monaco && electron-builder --win --config.win.target=portable --publish never",
+ "build:mac:local": "npm run build:shell && npm run copy:monaco && electron-builder --mac --publish never",
+ "build:mac:dmg:local": "npm run build:shell && npm run copy:monaco && electron-builder --mac --config.mac.target=dmg --publish never",
+ "build:linux:local": "npm run build:shell && npm run copy:monaco && electron-builder --linux --publish never"
},
"keywords": [
"deepseek",
@@ -44,6 +47,8 @@
},
"homepage": "https://github.com/merfiDEV/Cookie-code#readme",
"devDependencies": {
+ "@types/react": "^18.3.31",
+ "@types/react-dom": "^18.3.7",
"electron": "^33.0.0",
"electron-builder": "^24.13.3",
"prettier": "^3.3.3"
@@ -98,6 +103,15 @@
"icon": "build/icon.png",
"artifactName": "cuckoo-code-mac-v${version}-${arch}.${ext}"
},
+ "linux": {
+ "target": [
+ "AppImage",
+ "tar.gz"
+ ],
+ "icon": "build/icon.png",
+ "category": "Development",
+ "artifactName": "cuckoo-code-linux-v${version}-${arch}.${ext}"
+ },
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
@@ -134,8 +148,13 @@
"docx": "^9.7.1",
"electron-log": "^5.4.4",
"electron-updater": "^6.8.9",
+ "esbuild": "^0.24.0",
+ "katex": "^0.16.11",
"material-icon-theme": "^5.38.1",
+ "monaco-editor": "^0.52.0",
"mysql2": "^3.24.2",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
"turndown": "^7.2.4"
},
"allowScripts": {
diff --git a/release.bat b/release.bat
deleted file mode 100644
index 783753c..0000000
--- a/release.bat
+++ /dev/null
@@ -1,62 +0,0 @@
-@echo off
-chcp 1251 > nul
-setlocal
-
-echo ============================================
-echo Cuckoo Code - Publikatsiya obnovleniya
-echo ============================================
-echo.
-echo Versiya budet avtomaticheski uvelichena CI.
-echo Prosto vvedite kommentariy k izmeneniyam.
-echo.
-
-cd /d "%~dp0"
-
-:: Proverit chto est izmeneniya
-git status --short
-echo.
-
-:: Vvesti soobshchenie kommita
-set /p MSG=Kommentariy k komitu (Enter = "update"):
-
-if "%MSG%"=="" set MSG=update
-
-echo.
-echo ==== 1/3 Dobavit vse izmeneniya ====
-git add -A
-if errorlevel 1 (
- echo Oshibka git add!
- pause
- exit /b 1
-)
-
-echo.
-echo ==== 2/3 Commit: %MSG% ====
-git commit -m "%MSG%"
-if errorlevel 1 (
- echo Nechego kommitit - net izmeneniy!
- pause
- exit /b 1
-)
-
-echo.
-echo ==== 3/3 Push na GitHub (master) ====
-git push origin master
-if errorlevel 1 (
- echo Push ne udalsya! Proverte set ili proksi.
- pause
- exit /b 1
-)
-
-echo.
-echo ============================================
-echo Uspeshno! GitHub Actions avtomaticheski:
-echo 1. Uvelichit patch-versiyu (+1)
-echo 2. Sozdat tag vX.Y.Z
-echo 3. Soberet i opublikuet reliz
-echo.
-echo Progress: https://github.com/merfiDEV/Cookie-code/actions
-echo Relizy: https://github.com/merfiDEV/Cookie-code/releases
-echo ============================================
-echo.
-pause
\ No newline at end of file
diff --git a/scripts/build-shell.mjs b/scripts/build-shell.mjs
new file mode 100644
index 0000000..166785b
--- /dev/null
+++ b/scripts/build-shell.mjs
@@ -0,0 +1,71 @@
+/**
+ * Сборка shell.html из src/ui/shell/ (ESM)
+ */
+import { build } from "esbuild";
+import fs from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const ROOT = path.resolve(__dirname, "..");
+const SRC_DIR = path.join(ROOT, "src", "ui", "shell");
+const OUT = path.join(ROOT, "src", "ui", "shell.html");
+
+function readSrc(rel) {
+ return fs.readFileSync(path.join(SRC_DIR, rel), "utf8");
+}
+function expandIncludes(html, depth = 0) {
+ if (depth > 10) throw new Error("@include nested too deep");
+ return html.replace(//g, (_, rel) =>
+ expandIncludes(readSrc(rel.trim()), depth + 1),
+ );
+}
+function expandCssIncludes(css, depth = 0) {
+ if (depth > 10) throw new Error("CSS @include nested too deep");
+ return css.replace(/\/\*@include:([^*]+?)\*\//g, (_, rel) =>
+ expandCssIncludes(readSrc(rel.trim()), depth + 1),
+ );
+}
+
+async function main() {
+ let html = expandIncludes(readSrc("index.html"));
+ html = html.replace(/\/\*@include:styles\/([^*]+?)\*\//g, (_, rel) =>
+ expandCssIncludes(readSrc("styles/" + rel.trim())),
+ );
+
+ const result = await build({
+ entryPoints: [path.join(SRC_DIR, "scripts", "main.ts")],
+ bundle: true,
+ write: false,
+ format: "iife",
+ platform: "browser",
+ target: "es2020",
+ minify: false,
+ legalComments: "none",
+ logLevel: "warning",
+ jsx: "automatic",
+ jsxImportSource: "react",
+ loader: { ".tsx": "tsx", ".ts": "ts" },
+ define: { "process.env.NODE_ENV": '"production"' },
+ });
+ const js = result.outputFiles[0].text;
+
+ if (!html.includes("//@bundle")) throw new Error("missing //@bundle");
+ // КРИТИЧНО: экранируем внутри bundle, иначе inline
+
+
+
+
+
+
+
+
+
+
+
+ 对话上下文:
+ 0
+
+
+ 输出速度:
+ --
+ t/s
+
+
+
+
+
+
+
+