Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
artifact: canvastty-macos
runs-on: ${{ matrix.runner }}
steps:
- name: Note plugin showcase sign-in availability
if: ${{ vars.CANVASTTY_GITHUB_CLIENT_ID == '' }}
run: echo "::warning::CANVASTTY_GITHUB_CLIENT_ID is not set. The plugin showcase still works anonymously; GitHub sign-in is unavailable in this build."
- name: Check out repository
uses: actions/checkout@v7
- name: Set up Node.js
Expand All @@ -47,6 +50,8 @@ jobs:
run: npm test
- name: Build installers
run: npm run ${{ matrix.script }}
- name: Audit built bundle secrets
run: npm run audit:secrets
- name: Verify macOS app signature
if: runner.os == 'macOS'
run: |
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

[English](CHANGELOG.md) · [Русский](CHANGELOG.ru.md) · [简体中文](CHANGELOG.zh-CN.md)

## Unreleased

- Added Cursor, MiniMax Code, Devin and Antigravity agents (PR #63).
- Added provider API keys, API profiles and agent-to-agent delegation through the orchestration MCP (PR #64).
- Added saved SSH servers with automatic placement, remote terminals and agents, data-handling classes D0–D3 and several accounts per provider (PR #65).
- Added task capsules, isolated worktrees and Docker/Podman container runs on this computer and on servers (PRs #66 and #67).
- Added ACP conversations for Kimi, Cursor and MiniMax Code, plus account connection settings (PR #67).
- Added project context: scoped rules, convention imports and learning from explicit corrections (PR #68).
- Added opt-in launch routing with rules and Jev, reasoning effort, one-click server preparation, per-launch API-key forwarding and sign-in through the app (PR #69).
- The plugin showcase works without a GitHub account; signing in is optional and only raises GitHub's limits (issue #22). The HOME clock shows the date (issue #53).
- The default session denies web permissions, a crashed renderer reloads, long agent answers keep their turn, and the secret audit also checks the built bundle (from PRs #35 and #51).

## 1.5.2

- Fixed terminal history jumping to the beginning when Codex clears and redraws its history after a card resize. Readers retain their relative scroll position, while terminals at the bottom continue following new output.
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

[English](CHANGELOG.md) · [Русский](CHANGELOG.ru.md) · [简体中文](CHANGELOG.zh-CN.md)

## Unreleased

- Добавлены агенты Cursor, MiniMax Code, Devin и Antigravity (PR #63).
- Добавлены API-ключи провайдеров, API-профили и делегирование между агентами через MCP оркестрации (PR #64).
- Добавлены сохранённые SSH-серверы с автоматическим выбором сервера, удалённые терминалы и агенты, классы данных D0–D3 и несколько аккаунтов на провайдера (PR #65).
- Добавлены капсулы задач, изолированные рабочие копии и запуск в контейнерах Docker/Podman на этом компьютере и на серверах (PR #66 и #67).
- Добавлены разговоры ACP для Kimi, Cursor и MiniMax Code и настройки подключений аккаунтов (PR #67).
- Добавлен контекст проекта: правила по областям, импорт соглашений проекта и обучение на явных исправлениях (PR #68).
- Добавлены маршрутизация запусков по правилам и Jev (по желанию), уровень рассуждения, подготовка серверов одной кнопкой, передача API-ключа на сервер при запуске и вход через приложение (PR #69).
- Витрина плагинов работает без аккаунта GitHub; вход необязателен и только повышает лимиты GitHub (issue #22). Часы на HOME показывают дату (issue #53).
- Основная сессия отклоняет веб-разрешения, упавший интерфейс перезагружается, длинные ответы агентов сохраняют свой ход, а проверка секретов проверяет и собранный бандл (из PR #35 и #51).

## 1.5.2

- Исправлен прыжок терминала в начало истории, когда Codex очищает и заново рисует её после изменения размера карточки. При чтении сохраняется относительная позиция прокрутки, а терминал в конце истории продолжает следить за новым выводом.
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

[English](CHANGELOG.md) · [Русский](CHANGELOG.ru.md) · [简体中文](CHANGELOG.zh-CN.md)

## Unreleased

- 新增 Cursor、MiniMax Code、Devin 和 Antigravity 智能体(PR #63)。
- 新增提供商 API 密钥、API 配置文件,以及通过编排 MCP 在智能体之间委派任务(PR #64)。
- 新增已保存的 SSH 服务器:自动选择服务器、远程终端和智能体、D0–D3 数据处理等级,以及每个提供商的多个账号(PR #65)。
- 新增任务胶囊、隔离的工作副本,以及在本机和服务器上的 Docker/Podman 容器运行(PR #66 和 #67)。
- 新增 Kimi、Cursor 和 MiniMax Code 的 ACP 对话,以及账号连接设置(PR #67)。
- 新增项目上下文:分范围的规则、项目约定导入,以及从明确更正中学习(PR #68)。
- 新增可选的启动路由(规则和 Jev)、推理强度、一键准备服务器、每次启动时转发 API 密钥,以及在应用内登录(PR #69)。
- 插件展示页无需 GitHub 账号即可使用;登录是可选的,只会提高 GitHub 限额(issue #22)。HOME 时钟显示日期(issue #53)。
- 默认会话拒绝网页权限,渲染进程崩溃后会重新加载,较长的智能体回答会保留其轮次,密钥审计也会检查构建产物(来自 PR #35 和 #51)。

## 1.5.2

- 修复调整卡片大小后,Codex 清空并重新绘制历史时终端跳到历史开头的问题。阅读时保留相对滚动位置,位于底部的终端继续跟随新输出。
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ npm run dev
| [Built-in browser and audit log](docs/browser.md) | [Bundled agent browser skill](agent/browser/SKILL.md) |
| [Install, releases, and local data](docs/installing-and-security.md) | [Security policy](SECURITY.md) |
| [Architecture](docs/ARCHITECTURE.md) | [UI contract](docs/UI_CONTRACT.md) |
| [Project context and learning](docs/context.md) | [Docker/Podman across computers](docs/container-overview.md) |
| [Runtime plugin authoring](docs/plugins.md) | [Typed plugin SDK](docs/plugin-api.d.ts) |
| [Changelog](CHANGELOG.md) | [MIT license](LICENSE) |

Expand Down
4 changes: 2 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Electron main process
- `src/main/services/LimitsService.ts` reads Codex through the installed CLI's app-server protocol and Claude, Kimi, OpenCode Go, and Grok Build through their provider usage or billing endpoints. Qwen Code is multi-provider and exposes no provider-neutral read-only quota protocol, so its adapter reports `cli-not-found` or `unsupported-protocol` and never invents percentages. Provider credentials are read only inside the trusted main process, sent only to the matching provider over HTTPS, and never logged or exposed over IPC. The service owns timeout, structural normalization, caching, stale fallback, and subprocess cleanup; raw provider responses never cross IPC.
- `src/main/services/SettingsStore.ts` normalizes every update and persists through a serialized atomic write. Canvas regions and sticky notes have independent persistence gates: disabling one keeps its live objects for the current process but omits that collection from the disk snapshot and therefore from the next launch. The configurable canvas launcher and UI scale use the same boundary; transient window stacking does not.
- `src/main/services/PluginManager.ts` installs ready-to-run repositories without executing package scripts during install/update, rejects symlinks and oversized packages, persists the enabled registry, serves only contained package files, and enforces per-plugin permissions/storage quotas. Optional native agent-hook entries remain off by default; explicit per-hook trust is persisted in the plugin registry and compiled into a separate private atomic runtime registry. Update, module replacement, plugin disable, and uninstall revoke that trust before executable files change.
- `src/main/services/PluginSecretsService.ts` serializes per-plugin secret writes, encrypts the complete bounded payload through Electron `safeStorage`, rejects plaintext-only backends, and removes each encrypted file on uninstall.
- `src/main/services/PluginSecretsService.ts` serializes per-plugin secret writes, encrypts the complete bounded payload through Electron `safeStorage`, rejects plaintext-only backends, and removes each encrypted file on uninstall. `ProviderSecretsService.ts` applies the same architecture to provider API keys for BYOK-capable CLIs: values stay in the main process, and the renderer contract exposes only per-key `configured` flags plus set/clear actions. `ApiProfile` settings entries name model backends (protocol, HTTPS base URL, secret reference) for the same BYOK runtimes; they are not agent providers, and the settings normalizer drops invalid profiles instead of repairing them.
- `src/main/services/PluginMediaService.ts` persists per-plugin grants only after a native folder choice, hides absolute paths, skips symlinks, and serves contained audio with HTTP Range semantics. Playlist reads stay inside granted libraries; writes are bounded and atomic under the library's `Playlists/` directory.
- `src/main/services/HermesHudService.ts` is the only plugin-facing native application controller. It resolves the installed Hermes CLI through the immutable provider registry, sends only the fixed `--hud`/`--quit` control commands, and derives visible state from Hermes Desktop's validated live runtime record. It never accepts executable paths, arguments, PIDs, or arbitrary commands from plugin code.
- `src/main/services/BrowserService.ts` is the only owner of the built-in browser's `WebContentsView` tabs and shared persistent partition. Remote pages have no preload or Node access, keep context isolation and sandbox enabled, and cannot request hardware, location, notification, clipboard-read, certificate-bypass, or external-protocol capabilities. HTTP(S) popups are adopted as internal tabs; other schemes are rejected.
Expand All @@ -48,7 +48,7 @@ Electron main process
- `src/main/services/agent-runtime/` is a separate lifecycle boundary and is not controlled by the Browser access switch. When CanvasTTY status hooks are enabled, every agent PTY receives a distinct capability for a protected user-local socket/pipe. Provider command hooks and the OpenCode event plugin may report only the fixed status enum, bounded event name, and optional opaque turn/prompt ID; prompt text, responses, tool input, and arbitrary telemetry are rejected by the exact gateway schema. Electron helper commands carry `ELECTRON_RUN_AS_NODE=1` inside the exact hook command only; the provider PTY never inherits that process-mode flag, so a provider cannot accidentally launch a second CanvasTTY GUI instance. The user can revoke this capability from Agents settings, immediately returning live agent status to `unavailable`; re-enabling requires a new/restarted PTY. Explicitly trusted plugin hooks use a separate process runner which re-checks the private PluginManager registry on every invocation and strips CanvasTTY internal capabilities before passing the provider payload to third-party code. Provider-native review remains an independent gate; CanvasTTY does not bypass Codex hook trust globally.
- Lifecycle adapters use launch-only settings for Claude, Codex, Qwen, and OpenCode. Kimi, Hermes, and Grok, whose hook discovery is home-config based, receive ownership-checked temporary entries shared across live CanvasTTY sessions. Kimi and Hermes keep recovery journals and exact backups; Grok uses a dedicated owned hook file. Cleanup restores exact original bytes when no concurrent edit occurred and otherwise removes only CanvasTTY-owned entries.
- `TerminalManager` injects the MCP helper per launch without leaving permanent provider configuration. Claude Code, Codex, and Qwen Code receive CLI arguments; Qwen gets one inline `--mcp-config` entry that overrides only the CanvasTTY server name and leaves unrelated user servers available. OpenCode receives a merged launch-only `OPENCODE_CONFIG_CONTENT` entry plus one scoped browser-tool permission; Kimi uses its per-run MCP configuration when supported. Older Kimi versions receive a compare-and-swap temporary CanvasTTY entry and one exact permission rule with an atomic recovery journal. Hermes receives a temporary `mcp_servers.canvastty_browser` entry in `HERMES_HOME/config.yaml` (defaulting to `~/.hermes/config.yaml` on POSIX or `%LOCALAPPDATA%\hermes\config.yaml` on Windows); sensitive capability values stay as child-environment placeholders. Temporary Kimi and Hermes configuration remains until the final owning PTY session ends, then exact original bytes are restored when safe. A journal repairs an interrupted Hermes launch at the next CanvasTTY startup, while compare-and-swap checks preserve concurrent user edits. Unrelated MCP entries, credentials, and file/shell permissions are preserved. Qwen, OpenCode, and Hermes YOLO remain launch-only and do not change persistent permission settings.
- `src/main/services/providerCliRegistry.ts` is the single owner of provider CLI discovery. During main-process startup it creates a shared snapshot for Codex, Claude, Qwen Code, Kimi, OpenCode, Hermes, Grok Build, OMP, and Pi by checking smoke-only overrides, the inherited `PATH`, platform defaults, and known per-user/provider directories in that order. Available entries retain an absolute executable, launcher kind, and supplemented child `PATH`; POSIX entries must be executable files and Windows entries must be supported native or batch launchers. `TerminalManager`, `LimitsService`, agent-browser probes, and provider smoke tests consume that same snapshot and never repeat command lookup. Missing entries produce a failed session with copyable checked-path diagnostics before PTY or temporary browser configuration creation, while the limit adapter reports `cli-not-found`; its HOME row is hidden until explicitly selected after CLI detection. CanvasTTY never reads shell startup scripts. Agents settings can recheck candidate paths, atomically replace the registry snapshot, reconcile saved launcher and limit selections, and refresh CLI-bound adapters without restarting the app. Existing sessions keep running; a newly found CLI remains disabled until selected.
- `src/main/services/providerCliRegistry.ts` is the single owner of provider CLI discovery. During main-process startup it creates a shared snapshot for every provider in `PROVIDER_CLI_DEFINITIONS` — each definition declares the executable command names it may install as (which may differ from the provider ID, e.g. a provider shipping as `mcode`) and optional known home-relative or Windows LOCALAPPDATA-relative directories — by checking smoke-only overrides, the inherited `PATH`, platform defaults, and those known directories in that order. Available entries retain an absolute executable, launcher kind, and supplemented child `PATH`; POSIX entries must be executable files and Windows entries must be supported native or batch launchers. `TerminalManager`, `LimitsService`, agent-browser probes, and provider smoke tests consume that same snapshot and never repeat command lookup. Missing entries produce a failed session with copyable checked-path diagnostics before PTY or temporary browser configuration creation, while the limit adapter reports `cli-not-found`; its HOME row is hidden until explicitly selected after CLI detection. Launchers keep a provider without a local CLI visible when an account bound to a remote computer or a saved container profile provides another route. CanvasTTY never reads shell startup scripts. Agents settings can recheck candidate paths, atomically replace the registry snapshot, reconcile saved launcher and limit selections, and refresh CLI-bound adapters without restarting the app. Existing sessions keep running; a newly found CLI remains disabled until selected.

The primary `BrowserWindow` is created and shown with a lightweight local startup page before settings, plugins, media, and IPC services initialize. Successful initialization replaces that page with the trusted renderer; bootstrap failures replace it with a visible error page and retain a native-dialog fallback. The main process holds Electron's single-instance lock; a rejected second launch raises the running window through the `second-instance` handler so the app never appears to ignore a launch, while background plugin and browser requests never restore, show, or focus an existing window. Native browser contents are focused programmatically only while their owner `BrowserWindow` is already focused; explicit user pointer input remains the only cross-surface focus route.

Expand Down
Loading