Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Unreleased

- Base protection now also refuses any use of CanvasTTY's own private data by an agent's shell or file tool: reading, copying or encoding the agent-control token and descriptor, the gateways' connection records, the provider and plugin secret stores, account homes, the GitHub sign-in and prepared launch runs (by any program, interpreter one-liners and heredocs included), and connecting to CanvasTTY's control or runtime sockets (`curl --unix-socket`, `nc -U`, `socat`, a Python socket). The model is told calmly that agents cannot control CanvasTTY this way and to ask the person for an **Orchestrator** launch, which brings the `canvastty_agents` tools. The paths come from the app's own userData folder; the project, the app's settings, other sockets and the bundled control CLI are unaffected. The control endpoint now answers an unauthenticated or malformed request, and an HTTP request (a minimal 403), with the same guidance instead of a bare error, and closes the connection.
- Added an **Auto** launch profile for agents whose CLI has a native auto mode, next to Normal (still the default) and YOLO: Codex `--approve-for-me` (its own reviewer in its `workspace-write` sandbox), Claude Code `--permission-mode auto` with its sandbox (`sandbox.enabled`, `autoAllowBashIfSandboxed: false`, merged into the one `--settings`), Grok `--permission-mode auto`; also the control CLI's `create --profile auto` and plugin `sessions.create`. A launch contributor may answer `thirdPartyModel: true` (an API or Ollama account): Auto then runs as the CLI's accept-edits mode in the same sandbox, and the card shows **auto · edits**. Codex no longer stops at "Hooks need review" for the hooks CanvasTTY adds itself (per-run `-c hooks.state`, nothing written to `~/.codex`; plugins cannot pass `-c hooks…`), and a Codex subagent in (or below) the folder the person chose for its orchestrator is not asked to trust it again (per-run `-c projects`); plugins get that folder as `trustedFolder`. Claude Code's «✳» title now reads as idle: a hooked Claude card leaves `needs_approval` only through its hooks, or, when the person declined its prompt, a moment after the answer. Example: `examples/plugins/launch-env` (Local model profile).
- Added two launch points for account plugins. A launcher `select` may declare `"optionsFrom": "service"`: the launcher asks the service `canvastty.launch.options` (3 s) and lists up to 64 more choices after the declared ones, such as the plugin's own accounts; the saved value is then checked by the service when it prepares. Orchestrators may pass plugin launch options to `spawn_agent` as `launchOptions`, checked exactly like the launcher's. A plugin's inline Claude `--settings` is merged into CanvasTTY's own (Claude Code keeps only the last one, which dropped the lifecycle and decision hooks); approval and hook keys in it are refused. Example: `examples/plugins/launch-env` (Profile).
- Added plugin services (manifest apiVersion 2, `services`): bundled single-file JavaScript that runs as a supervised child process only after the separate per-plugin **Extension native code** confirmation in Settings → Agents (off by default, never granted by install, revoked by update, module change, disable, or a changed entry file). Services get a minimal environment without keys or CanvasTTY internals, speak JSON-RPC over stdio with 1 MB messages and 15 s timeouts, restart with backoff, stop on disable, uninstall, update and quit, and log to a bounded per-plugin log. Plugin surfaces call their own plugin's services through `host.service.request` and receive `host.service.onEvent`; services may call back `log`, own-plugin `storage` and `event`, and read their own plugin's secrets with `secrets.get` (needs `secrets`). Example: `examples/plugins/service-echo` (its service also reads a token the page saved).
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Unreleased

- Базовая защита теперь также запрещает shell- и файловым инструментам агента любые обращения к собственным закрытым данным CanvasTTY: чтение, копирование или кодирование токена и дескриптора agent-control, файлов подключения шлюзов, хранилищ секретов провайдеров и плагинов, домашних папок аккаунтов, входа GitHub и подготовленных запусков (любой программой, включая однострочники интерпретаторов и heredoc), а также подключение к управляющим и runtime-сокетам CanvasTTY (`curl --unix-socket`, `nc -U`, `socat`, сокет Python). Модель спокойно получает объяснение, что так управлять CanvasTTY нельзя, и совет попросить человека запустить её с ролью **Orchestrator**, которая даёт инструменты `canvastty_agents`. Пути берутся из собственной папки userData приложения; проект, настройки приложения, другие сокеты и встроенный CLI управления не затронуты. Управляющий endpoint теперь отвечает на неаутентифицированный или некорректный запрос, а также на HTTP-запрос (минимальный 403) тем же объяснением вместо голой ошибки и закрывает соединение.
- Добавлен профиль запуска **Авто** для агентов, у чьего CLI есть собственный авторежим, рядом с «Обычным» (он остаётся по умолчанию) и YOLO: Codex `--approve-for-me` (его собственная проверка в песочнице `workspace-write`), Claude Code `--permission-mode auto` с его песочницей (`sandbox.enabled`, `autoAllowBashIfSandboxed: false`, в единственном `--settings`), Grok `--permission-mode auto`; также `create --profile auto` в CLI управления и `sessions.create` плагинов. Вклад запуска может ответить `thirdPartyModel: true` (аккаунт API или Ollama): тогда «Авто» работает как режим «только правки» того же CLI в той же песочнице, а окно показывает **авто · правки**. Codex больше не останавливается на «Hooks need review» для хуков, которые добавляет сам CanvasTTY (`-c hooks.state` на этот запуск, в `~/.codex` ничего не пишется; плагины не могут передать `-c hooks…`), а субагента Codex в папке, выбранной человеком для его оркестратора (или внутри неё), не спрашивают о доверии к ней снова (`-c projects` на этот запуск); плагины получают эту папку как `trustedFolder`. Заголовок Claude Code «✳» теперь читается как «ожидает»: окно Claude с хуками выходит из `needs_approval` только по хукам, а если человек отклонил запрос — вскоре после ответа. Пример: `examples/plugins/launch-env` (профиль «Local model»).
- Добавлены две точки запуска для плагинов учётных записей. Список (`select`) в параметрах запуска может объявить `"optionsFrom": "service"`: окно запуска спрашивает сервис `canvastty.launch.options` (3 с) и показывает до 64 дополнительных вариантов после объявленных, например учётные записи самого плагина; сохранённое значение проверяет сервис при подготовке запуска. Оркестраторы могут передать параметры запуска плагинов в `spawn_agent` как `launchOptions`; они проверяются так же, как в окне запуска. Встроенный `--settings` плагина для Claude сливается с собственным JSON CanvasTTY (Claude Code применяет только последний, из-за чего пропадали хуки состояния и решений); ключи подтверждений и хуков в нём отклоняются. Пример: `examples/plugins/launch-env` (Profile).
- Добавлены сервисы плагинов (манифест apiVersion 2, `services`): собранный одним файлом JavaScript, который запускается отдельным дочерним процессом под надзором хоста только после отдельного подтверждения **Нативный код расширений** для плагина в Настройки → Агенты (по умолчанию выключено, установка его не даёт, обновление, смена модулей, выключение или изменённый файл entry его снимают). Сервис получает минимальное окружение без ключей и внутренних переменных CanvasTTY, общается по JSON-RPC через stdio (сообщения до 1 МБ, таймаут 15 с), перезапускается с паузами, останавливается при выключении, удалении, обновлении и выходе и пишет в ограниченный журнал плагина. Поверхности плагина обращаются к сервисам своего плагина через `host.service.request` и получают `host.service.onEvent`; сервис может вызывать `log`, `storage` своего плагина и `event` и читать секреты своего плагина через `secrets.get` (нужно `secrets`). Пример: `examples/plugins/service-echo` (его сервис ещё и читает токен, сохранённый страницей).
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Unreleased

- 基础保护现在还会拒绝智能体的 shell 或文件工具使用 CanvasTTY 自己的私有数据:读取、复制或编码 agent-control 令牌与描述文件、各网关的连接记录、提供商与插件的密钥存储、账户主目录、GitHub 登录信息和已准备的启动运行(任何程序,包括解释器单行命令和 heredoc),以及连接 CanvasTTY 的控制或运行时套接字(`curl --unix-socket`、`nc -U`、`socat`、Python 套接字)。模型会平静地得知智能体不能以这种方式控制 CanvasTTY,并被建议请用户以 **Orchestrator** 角色启动它,从而获得 `canvastty_agents` 工具。路径来自应用自己的 userData 文件夹;项目、应用设置、其他套接字和内置控制 CLI 不受影响。控制端点现在对未认证或格式错误的请求,以及 HTTP 请求(最小的 403),都以相同的指引代替简单错误作答,并关闭连接。
- 为 CLI 自带自动模式的智能体新增 **Auto** 启动配置档,与 Normal(仍为默认)和 YOLO 并列:Codex `--approve-for-me`(其自身审查,位于 `workspace-write` 沙箱),Claude Code `--permission-mode auto` 及其沙箱(`sandbox.enabled`、`autoAllowBashIfSandboxed: false`,合并进唯一的 `--settings`),Grok `--permission-mode auto`;控制 CLI 的 `create --profile auto` 和插件的 `sessions.create` 也支持。启动贡献者可回答 `thirdPartyModel: true`(API 或 Ollama 账户):此时 Auto 以同一沙箱中 CLI 的“仅接受编辑”模式运行,卡片显示 **auto · edits**。Codex 不再因 CanvasTTY 自己添加的 hook 停在 “Hooks need review”(本次运行的 `-c hooks.state`,不写入 `~/.codex`;插件不能传递 `-c hooks…`),位于用户为其编排者所选文件夹(或其子目录)中的 Codex 子智能体不再被再次询问是否信任(本次运行的 `-c projects`);插件以 `trustedFolder` 获得该文件夹。Claude Code 的 «✳» 标题现在表示空闲:带 hook 的 Claude 卡片仅通过 hook 离开 `needs_approval`,或在用户拒绝其提示后稍候离开。示例:`examples/plugins/launch-env`(Local model 配置档)。
- 新增两个供账户插件使用的启动扩展点。启动选项中的 `select` 可以声明 `"optionsFrom": "service"`:启动器向服务发送 `canvastty.launch.options`(3 秒),并在声明的选项之后列出最多 64 个额外选项,例如插件自己的账户;保存的值由服务在准备启动时检查。编排器可以把插件启动选项作为 `launchOptions` 传给 `spawn_agent`,校验方式与启动器相同。插件为 Claude 提供的内联 `--settings` 会合并进 CanvasTTY 自己的 JSON(Claude Code 只保留最后一个,此前会丢失生命周期和决策 hook);其中的审批和 hook 键会被拒绝。示例:`examples/plugins/launch-env`(Profile)。
- 新增插件服务(manifest apiVersion 2,`services`):打包为单文件的 JavaScript,仅在 设置 → Agents 中为该插件单独确认 **Extension native code** 后才作为受监管的子进程运行(默认关闭,安装不会授予;更新、更换模块、禁用或 entry 文件被修改都会撤销)。服务获得不含密钥和 CanvasTTY 内部变量的最小环境,通过 stdio 使用 JSON-RPC(消息上限 1 MB,超时 15 秒),退避重启,在禁用、卸载、更新和退出时停止,并写入有界的插件日志。插件界面通过 `host.service.request` 调用自身插件的服务,并通过 `host.service.onEvent` 接收事件;服务可回调 `log`、自身插件的 `storage` 和 `event`,并可用 `secrets.get` 读取自身插件的机密(需要 `secrets`)。示例:`examples/plugins/service-echo`(其服务还会读取页面保存的令牌)。
Expand Down
2 changes: 1 addition & 1 deletion docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ The full example is [`examples/plugins/collect-demo`](../examples/plugins/collec

Two safety parts are built in and need no plugin:

- **Base protection** (Settings → Agents, on by default; the person can turn it off) denies, through the same hook, sudo and other elevation, piping downloaded or generated text into a shell, download-and-run, disk and format commands, fork bombs, and writing or deleting outside the working folder: the home folder, other projects and `/tmp` included, and deleting the working folder itself. An agent's own plan and memory folders (`~/.claude/plans`, `~/.claude/projects/<project>/memory`, and the same inside the run's `CLAUDE_CONFIG_DIR`) are not "outside". It only ever denies; each reason tells the model what to do instead (a write to `/tmp` suggests a scratch folder inside the project).
- **Base protection** (Settings → Agents, on by default; the person can turn it off) denies, through the same hook, sudo and other elevation, piping downloaded or generated text into a shell, download-and-run, disk and format commands, fork bombs, and writing or deleting outside the working folder: the home folder, other projects and `/tmp` included, and deleting the working folder itself. An agent's own plan and memory folders (`~/.claude/plans`, `~/.claude/projects/<project>/memory`, and the same inside the run's `CLAUDE_CONFIG_DIR`) are not "outside". It also denies any use of CanvasTTY's own private data (from the app's userData folder: the agent-control token and descriptor, the gateways' connection records and sockets, the secret stores, account homes; and the control/runtime socket folders under the temporary folder), by any program, interpreter one-liners and socket clients included; the reason points the model at an **Orchestrator** launch and the `canvastty_agents` tools. The bundled control CLI may name its descriptor. It only ever denies; each reason tells the model what to do instead (a write to `/tmp` suggests a scratch folder inside the project).
- **Secret redaction**: every text CanvasTTY hands from one agent to another (`observe_agent`, `get_agent_result`, the control CLI's `screen`, `result` and failure details) is masked: provider keys CanvasTTY holds, launch `secretEnv` values, values a service registered with `redaction.register`, also when the terminal wrapped them over lines, plus common key shapes (`sk-…`, GitHub, Slack, AWS, Google, JWT, `Bearer …`, `"apiKey": "…"`, PEM private keys, long random runs). Plugin tool answers, `screen` in session events, card badges and card action messages are masked the same way.

host.onStorageChange(listener) notifies every live contribution of the same plugin — canvases, HOME widgets, and separate windows — of writes made through host.storage.set, avoiding polling when a plugin coordinates several surfaces.
Expand Down
2 changes: 1 addition & 1 deletion docs/plugins.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ interface PluginSessionEvent {

两项安全功能内置,无需插件:

- **基础保护**(设置 → Agents → Base protection,默认开启;用户可以关闭)通过同一个 hook 拒绝:sudo 及其他提权、把下载或生成的文本管道给 shell、下载后直接运行、磁盘和格式化命令、fork 炸弹,以及在工作文件夹之外写入或删除(包括主目录、其他项目和 `/tmp`),以及删除工作文件夹本身。agent 自己的计划和记忆文件夹(`~/.claude/plans`、`~/.claude/projects/<project>/memory`,以及本次运行 `CLAUDE_CONFIG_DIR` 中的相同位置)不算"外部"。它只会拒绝;每条原因都告诉模型应当改做什么(写入 `/tmp` 时建议在项目内建立临时文件夹)。
- **基础保护**(设置 → Agents → Base protection,默认开启;用户可以关闭)通过同一个 hook 拒绝:sudo 及其他提权、把下载或生成的文本管道给 shell、下载后直接运行、磁盘和格式化命令、fork 炸弹,以及在工作文件夹之外写入或删除(包括主目录、其他项目和 `/tmp`),以及删除工作文件夹本身。agent 自己的计划和记忆文件夹(`~/.claude/plans`、`~/.claude/projects/<project>/memory`,以及本次运行 `CLAUDE_CONFIG_DIR` 中的相同位置)不算"外部"。它还会拒绝任何程序(包括解释器单行命令和套接字客户端)使用 CanvasTTY 自己的私有数据(来自应用的 userData 文件夹:agent-control 令牌与描述文件、各网关的连接记录与套接字、密钥存储、账户主目录;以及临时文件夹下的控制/运行时套接字文件夹);拒绝原因会引导模型改用 **Orchestrator** 启动和 `canvastty_agents` 工具。内置控制 CLI 可以引用它的描述文件。它只会拒绝;每条原因都告诉模型应当改做什么(写入 `/tmp` 时建议在项目内建立临时文件夹)。
- **密钥遮蔽**:CanvasTTY 从一个 agent 交给另一个 agent 的所有文本(`observe_agent`、`get_agent_result`,以及 control CLI 的 `screen`、`result` 和失败详情)都会被遮蔽:CanvasTTY 保存的服务商密钥、启动时的 `secretEnv` 值、服务通过 `redaction.register` 注册的值(包括被终端折行拆开的情况),以及常见密钥形式(`sk-…`、GitHub、Slack、AWS、Google、JWT、`Bearer …`、`"apiKey": "…"`、PEM 私钥、长随机串)。插件工具的回答、会话事件中的 `screen`、卡片标记和卡片动作消息也以同样方式遮蔽。

host.onStorageChange(listener) 会把 host.storage.set 的写入通知给同一插件的所有活动界面——画布卡片、HOME 小组件和独立窗口——从而避免轮询。
Expand Down
Loading
Loading