diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec083ccbd7..5d58bec5eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -355,6 +355,9 @@ jobs: - name: Check repository hygiene run: pnpm run check:repo-hygiene + - name: Validate interactive capability contract + run: pnpm run capabilities:check && pnpm run capabilities:test && pnpm run website:test && pnpm run website:build + - name: Check core boundaries run: node --test scripts/check-core-boundaries.test.mjs diff --git a/deploy/openbitfun-host/README.md b/deploy/openbitfun-host/README.md index 4288347a15..b241d05d4b 100644 --- a/deploy/openbitfun-host/README.md +++ b/deploy/openbitfun-host/README.md @@ -28,6 +28,7 @@ clone、`crontab` 整表安装、市场 first-install 或空 volume 的 `deploy. | 产品 | 公网 | 源站 | 仓库内入口 | | --- | --- | --- | --- | | 官网 + 下载页 | `https://openbitfun.com/` 、`/download` | Nginx → `BitFun-Website/dist` | 本文「官网」 | +| BitFun Playbook | `https://playbook.openbitfun.com/` | Nginx → `/srv/bitfun-playbook/current` | 本文「BitFun Playbook」 | | Release 镜像 | `https://openbitfun.com/release/` | cron → `/srv/bitfun-release` | 本文「Release 镜像」;脚本在 `scripts/openbitfun-release-sync.sh` | | Relay | `https://remote.openbit.fun/relay` | `bitfun-relay:9700` | `src/apps/relay-server/README.md` + 本文 Nginx | | MiniApp 市场 | `https://market.openbitfun.com/miniapp/` | `127.0.0.1:9710` | [../miniapp-market/README.md](../miniapp-market/README.md) | @@ -45,6 +46,7 @@ clone、`crontab` 整表安装、市场 first-install 或空 volume 的 `deploy. | `/root/repos/BitFun` | BitFun checkout。Relay 静态页和同步脚本从这里读 | | `/root/repos/BitFun-Website` | 官网独立仓库 `GCWing/BitFun-Website` | | `/srv/bitfun-release` | GitHub Release 镜像(禁止放进 Website `dist/`) | +| `/srv/bitfun-playbook` | Playbook 的不可变静态版本与 `current` 软链接 | | `/srv/bitfun-miniapp-market` | MiniApp 专用 checkout / 数据 / 备份 | | `/srv/bitfun-skin-market` | Skin 专用 checkout / 数据 / 备份 | | `/etc/bitfun-miniapp-market/market.env` | MiniApp secrets,`root:root` `0600` | @@ -284,6 +286,50 @@ curl -fsS -o /dev/null -w "%{http_code}\n" \ 更新官网:在 Website 仓库拉代码后只跑 `npm run build`,不要动 `/srv/bitfun-release`。 +### 5.1 BitFun Playbook + +Playbook 源码在 BitFun 仓库的 `website/`。功能与设置的唯一人工维护数据源是 +`src/shared/interactive-capabilities/catalog.json`;网站只读取由它生成的 +`docs/interactive-capabilities/capabilities.json`。构建与上传从开发机执行;源站只保存 +不可变静态版本,不需要 Node 运行时。 + +```bash +pnpm run capabilities:check +pnpm run capabilities:test +pnpm run website:test +pnpm run website:build +PLAYBOOK_RELEASE="$(node -e 'const r=require("./website/dist/release.json");process.stdout.write(r.releaseId)')" +PLAYBOOK_SAMPLE_ID="$(node -e 'const c=require("./docs/interactive-capabilities/capabilities.json");process.stdout.write(c.capabilities[0].id)')" +test -n "$PLAYBOOK_RELEASE" +test -n "$PLAYBOOK_SAMPLE_ID" +ssh lwb "install -d -m 0755 /srv/bitfun-playbook/releases/$PLAYBOOK_RELEASE" +rsync -a --delete website/dist/ \ + "lwb:/srv/bitfun-playbook/releases/$PLAYBOOK_RELEASE/" +rsync -a deploy/openbitfun-host/nginx-playbook.openbitfun.com.conf \ + lwb:/tmp/nginx-playbook.openbitfun.com.conf +ssh lwb "set -eu +install -m 0644 /tmp/nginx-playbook.openbitfun.com.conf \ + /etc/nginx/sites-available/playbook.openbitfun.com +ln -sfn /srv/bitfun-playbook/releases/$PLAYBOOK_RELEASE \ + /srv/bitfun-playbook/current +ln -sfn /etc/nginx/sites-available/playbook.openbitfun.com \ + /etc/nginx/sites-enabled/playbook.openbitfun.com +nginx -t +systemctl reload nginx +curl --retry 5 --retry-delay 1 --retry-all-errors -fsS -o /dev/null \ + -H 'Host: playbook.openbitfun.com' http://127.0.0.1/ +curl --retry 5 --retry-delay 1 --retry-all-errors -fsS -o /dev/null \ + -H 'Host: playbook.openbitfun.com' \ + http://127.0.0.1/capabilities/$PLAYBOOK_SAMPLE_ID/ +curl --retry 5 --retry-delay 1 --retry-all-errors -fsS -o /dev/null \ + -H 'Host: playbook.openbitfun.com' \ + http://127.0.0.1/data/capabilities.json" +``` + +`systemctl reload` 返回时旧 worker 可能仍短暂接请求,所以源站验收必须带重试。 +最后通过公网检查首页、任一详情页和 `/data/capabilities.json`;若源站 Host 检查为 200、 +公网仍失败,应在云 WAF / DNS 增加该主机名,源站不要自行配置 443。 + ### 6. Relay 必须先恢复两个 volume,再启动容器。先跑 `deploy.sh` 会建空卷,账号、同步和 @@ -413,6 +459,11 @@ install -m 0644 \ /root/repos/BitFun/deploy/openbitfun-host/nginx-openbit.fun.conf \ /etc/nginx/sites-available/openbit.fun ln -sfn /etc/nginx/sites-available/openbit.fun /etc/nginx/sites-enabled/openbit.fun +install -m 0644 \ + /root/repos/BitFun/deploy/openbitfun-host/nginx-playbook.openbitfun.com.conf \ + /etc/nginx/sites-available/playbook.openbitfun.com +ln -sfn /etc/nginx/sites-available/playbook.openbitfun.com \ + /etc/nginx/sites-enabled/playbook.openbitfun.com install -m 0644 \ /root/repos/BitFun/deploy/openbitfun-host/nginx-remote.openbit.fun.conf \ /etc/nginx/sites-available/remote.openbit.fun @@ -482,6 +533,7 @@ docker exec bitfun-relay /app/relay-admin --db /app/data/bitfun_relay.db list-us | 更新 Relay | 源码更新后 `cd src/apps/relay-server && BITFUN_MIRROR=auto bash deploy.sh`。账号 volume 会留下。 | | 更新 Release 镜像脚本 | 只改仓库里的 `scripts/openbitfun-release-sync.sh`。cron 已经跑这份文件。 | | 更新官网 | 在 `BitFun-Website` 拉代码,`source ~/.nvm/nvm.sh && nvm use 20.20.2 && npm run build`。 | +| 更新 Playbook | 在开发机校验能力契约并运行 `pnpm run website:build`,再按「BitFun Playbook」使用 `dist/release.json` 的版本目录上传和切换 `current`。 | | 更新市场 | 只用对应市场手册。 | 更新 BitFun 源码**不会**自动更新官网、New API 或市场容器。 diff --git a/deploy/openbitfun-host/nginx-playbook.openbitfun.com.conf b/deploy/openbitfun-host/nginx-playbook.openbitfun.com.conf new file mode 100644 index 0000000000..fa86daa442 --- /dev/null +++ b/deploy/openbitfun-host/nginx-playbook.openbitfun.com.conf @@ -0,0 +1,31 @@ +server { + listen 80; + listen [::]:80; + + server_name playbook.openbitfun.com; + + root /srv/bitfun-playbook/current; + index index.html; + + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header X-Frame-Options "SAMEORIGIN" always; + + location / { + try_files $uri/index.html $uri =404; + } + + location = /data/capabilities.json { + expires 5m; + add_header Cache-Control "public, max-age=300"; + } + + location ~* \.(js|css|png|ico)$ { + expires 1h; + add_header Cache-Control "public, max-age=3600"; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml; + gzip_min_length 1024; +} diff --git a/docs/interactive-capabilities/README.md b/docs/interactive-capabilities/README.md new file mode 100644 index 0000000000..9dccf58b8c --- /dev/null +++ b/docs/interactive-capabilities/README.md @@ -0,0 +1,46 @@ + +# BitFun 功能与设置目录 / BitFun Features & Settings + +BitFun Playbook 当前包含 **22 个功能**和 **16 个设置页**,共 **38 个**用户可理解的条目、**297 项**有源码证据的子能力。每个条目有独立 Markdown,并直接服务于说明书网站、BitFun 全局搜索和 `BitFunControl` Agent 工具。 + +BitFun Playbook currently contains **22 features**, **16 settings pages**, and **297** source-backed sub-capabilities across **38** user-facing entries. Every entry has its own Markdown page and directly powers the website, in-app global search, and the `BitFunControl` agent tool. + +## 唯一事实源 / Single source of truth + +- 手工维护的唯一语义目录:`src/shared/interactive-capabilities/catalog.json` +- 生成的公开目录:`docs/interactive-capabilities/capabilities.json` +- 生成的前端运行目录:`src/web-ui/src/app/global-search/generated/interactive-capabilities.json` +- 生成的底层审计表:`docs/interactive-capabilities/technical/tauri-command-map.json` +- 生成的可见交互审计表:`docs/interactive-capabilities/technical/ui-interaction-inventory.json` + +说明书、网站、搜索和 Agent 只看“功能 + 设置 + 子能力”。每项子能力都必须引用已注册 Tauri Command 或可解析的源码标记;这些证据不会进入公开目录。当前 **692** 个 Tauri 命令,以及 **370** 个产品交互源码文件中的 **4441** 个交互候选,只用于实现覆盖审计。 + +Docs, website, search, and agents see only features, settings, and documented sub-capabilities. Every sub-capability must reference a registered Tauri command or a resolvable source marker; evidence is stripped from public projections. The **692** Tauri commands and **4441** interaction candidates across **370** product UI source files remain implementation-audit evidence only. + +## 控制边界 / Control boundary + +- 每个功能或设置都有可执行的产品入口;存在多视图的设置页还必须把每个视图映射到至少一个子能力,搜索和 Agent 可携带子能力 ID 精确跳转。 +- 简单、稳定且适合自动化的行为才声明为类型化 `operations` 或 `options`。复杂流程由 Agent 打开对应界面交给用户继续,不向 Agent 暴露原始 Tauri Command。 +- `BitFunControl list` 一次返回完整的精简目录(目录上限 50 项);`search` 默认只返回前 20 项。完整目录和 297 项子能力都不会写入 system prompt。 +- Desktop 只有在前端控制监听器完成握手后才发布工具;CLI、Detached Dispatch 等没有交互界面的运行方式明确不提供该工具。只读 Agent 只能发现和读取目录。 + +- Every feature or setting has an executable product destination. Multi-view settings pages must map every registered view to at least one documented item, so search and agents can carry an item ID for exact navigation. +- Only simple, stable, automation-safe behavior becomes a typed `operation` or `option`. Complex flows open their owning UI instead of exposing raw Tauri commands to agents. +- One default `BitFunControl list` call returns the complete curated catalog (hard limit: 50); `search` defaults to 20 results. Neither the full catalog nor its 297 documented items enters the system prompt. +- Desktop advertises the tool only after the frontend control listener completes its readiness handshake. Headless surfaces such as CLI and Detached Dispatch explicitly omit it, and read-only agents may only discover and inspect entries. + +## 防腐化门禁 / Anti-drift gates + +- 设置页、产品动作与场景注册表必须全部映射到一个语义条目。 +- 所有设置子视图必须有同源的子能力直达目标,失效的页签 ID 会阻断生成。 +- 每个功能至少 6 项、每个设置至少 4 项子能力,且中英文、稳定 ID 与证据缺一不可。 +- 当前操作处理器不接受参数;若目录误声明参数,生成会失败,避免 Agent 看到实际不会生效的参数。 +- Tauri 模块命令数和用户可见交互源码摘要均为 reviewed contract;变化会让 `capabilities:check` 失败并给出新的摘要值。 +- 维护者必须先核对功能清单与证据,再只在本语义源中更新 reviewed count/digest,随后运行 `pnpm run capabilities:generate`。 + +- Every settings page, product action, and scene registration must map to one semantic entry. +- Every settings subview needs a same-source item destination; stale view IDs fail generation. +- Features need at least six documented items and settings need at least four, each with bilingual text, a stable ID, and source evidence. +- Current operation handlers accept no arguments, and generation fails if the catalog advertises arguments that would be ignored. +- Reviewed Tauri module counts and the user-visible interaction-source digest fail `capabilities:check` on drift. +- Maintainers review the inventories and evidence first, update the reviewed count/digest only in this semantic source, then run `pnpm run capabilities:generate`. diff --git a/docs/interactive-capabilities/capabilities.json b/docs/interactive-capabilities/capabilities.json new file mode 100644 index 0000000000..c4283dbe4e --- /dev/null +++ b/docs/interactive-capabilities/capabilities.json @@ -0,0 +1,6010 @@ +{ + "schemaVersion": 3, + "product": "BitFun", + "title": "BitFun Playbook", + "origin": "https://playbook.openbitfun.com", + "source": "src/shared/interactive-capabilities/catalog.json", + "digest": "3207e4dc899c9109f0be952b9497d2f6169f9e2bb3ba9a859dda7e6959903470", + "counts": { + "features": 22, + "settings": 16, + "userFacing": 38, + "documentedItems": 297 + }, + "categories": { + "assistant": { + "titleZh": "AI 与协作", + "titleEn": "AI & collaboration", + "descriptionZh": "会话、Agent、记忆与智能协作。", + "descriptionEn": "Sessions, agents, memory, and AI collaboration." + }, + "workspace": { + "titleZh": "项目与开发", + "titleEn": "Projects & development", + "descriptionZh": "项目、文件、终端、Git、浏览器与开发工具。", + "descriptionEn": "Projects, files, terminal, Git, browser, and development tools." + }, + "automation": { + "titleZh": "扩展与自动化", + "titleEn": "Extensions & automation", + "descriptionZh": "Skills、Mini Apps、任务、Hooks 与生态兼容。", + "descriptionEn": "Skills, Mini Apps, tasks, hooks, and ecosystem compatibility." + }, + "connect": { + "titleZh": "连接与发布", + "titleEn": "Connect & publish", + "descriptionZh": "远程工作、多设备控制、派发与页面发布。", + "descriptionEn": "Remote work, multi-device control, dispatch, and publishing." + }, + "application": { + "titleZh": "应用设置", + "titleEn": "Application settings", + "descriptionZh": "外观、输入、开发环境与应用行为。", + "descriptionEn": "Appearance, input, development environment, and app behavior." + }, + "data": { + "titleZh": "数据与诊断", + "titleEn": "Data & diagnostics", + "descriptionZh": "用量、归档、日志与问题诊断。", + "descriptionEn": "Usage, archives, logs, and troubleshooting." + } + }, + "capabilities": [ + { + "id": "feature.ai-assistant", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "AI 助手与会话", + "titleEn": "AI assistant & sessions", + "summaryZh": "在项目上下文中与 AI 协作,创建会话、继续任务、处理权限请求,并保留完整的工作记录。", + "summaryEn": "Work with AI in project context, create sessions, continue tasks, answer permission requests, and keep a durable work record.", + "keywordsZh": [ + "对话", + "聊天", + "会话", + "新建会话", + "继续任务", + "权限", + "目标" + ], + "keywordsEn": [ + "chat", + "conversation", + "session", + "new session", + "continue task", + "permission", + "goal" + ], + "highlightsZh": [ + "创建、归档、恢复和分叉会话", + "暂停、继续或引导正在运行的任务", + "查看工具调用、权限请求和用量" + ], + "highlightsEn": [ + "Create, archive, restore, and fork sessions", + "Pause, continue, or steer running work", + "Inspect tool calls, permission requests, and usage" + ], + "items": [ + { + "id": "session-lifecycle", + "titleZh": "新建、重命名、归档、恢复、删除、分叉与导出会话", + "titleEn": "Create, rename, archive, restore, delete, fork, and export sessions" + }, + { + "id": "model-mode-permissions", + "titleZh": "为会话选择模型、工作模式、记忆模式与权限模式", + "titleEn": "Choose the model, work mode, memory mode, and permission mode per session" + }, + { + "id": "turn-control", + "titleZh": "开始、引导、打断、取消或恢复一次 Agent 运行", + "titleEn": "Start, steer, interrupt, cancel, or recover an agent turn" + }, + { + "id": "permission-mailbox", + "titleZh": "查看并逐个或批量回答等待中的权限请求", + "titleEn": "Review and answer pending permission requests individually or in a batch" + }, + { + "id": "history-search", + "titleZh": "分页加载、搜索和回填历史消息与会话内容", + "titleEn": "Page through, search, and backfill historical turns and session content" + }, + { + "id": "tool-activity", + "titleZh": "查看工具调用与后台命令,读取输出并继续输入或停止", + "titleEn": "Inspect tool calls and background commands, read output, send input, or stop them" + }, + { + "id": "goals", + "titleZh": "创建会话目标、更新目标内容与状态并清除目标", + "titleEn": "Create session goals, update their objective and status, and clear them" + }, + { + "id": "usage", + "titleZh": "查看单个会话的请求、Token 与成本用量报告", + "titleEn": "View request, token, and cost usage for an individual session" + }, + { + "id": "context-memory", + "titleZh": "重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆", + "titleEn": "Reload session context, initialize AGENTS.md, and manage long-term memory" + }, + { + "id": "btw-editor-ai", + "titleZh": "使用 BTW 轻量问答与编辑器内联 AI,并可随时取消", + "titleEn": "Use lightweight BTW questions and inline editor AI, with cancellation" + } + ], + "stepsZh": [ + "打开 AI 助手或新建会话", + "选择项目、模型和工作模式", + "描述目标;BitFun 会在会话中持续记录进度" + ], + "stepsEn": [ + "Open the AI assistant or create a session", + "Choose a project, model, and working mode", + "Describe the goal; BitFun keeps progress in the session" + ], + "agentExamplesZh": [ + "新建一个会话,我们来排查这个构建错误", + "打开 AI 助手,我想继续刚才的任务" + ], + "agentExamplesEn": [ + "Start a new session so we can debug this build error", + "Open the AI assistant; I want to continue my previous task" + ], + "destination": { + "kind": "scene", + "sceneId": "session" + }, + "operations": [ + { + "id": "new-session", + "titleZh": "新建会话", + "titleEn": "Create a session", + "descriptionZh": "打开一个新的 AI 会话。", + "descriptionEn": "Open a new AI session.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + } + } + ], + "options": [], + "searchTerms": [ + "feature.ai-assistant", + "AI 助手与会话", + "AI assistant & sessions", + "AI 与协作", + "AI & collaboration", + "对话", + "聊天", + "会话", + "新建会话", + "继续任务", + "权限", + "目标", + "chat", + "conversation", + "session", + "new session", + "continue task", + "permission", + "goal", + "创建、归档、恢复和分叉会话", + "暂停、继续或引导正在运行的任务", + "查看工具调用、权限请求和用量", + "Create, archive, restore, and fork sessions", + "Pause, continue, or steer running work", + "Inspect tool calls, permission requests, and usage", + "新建、重命名、归档、恢复、删除、分叉与导出会话", + "Create, rename, archive, restore, delete, fork, and export sessions", + "为会话选择模型、工作模式、记忆模式与权限模式", + "Choose the model, work mode, memory mode, and permission mode per session", + "开始、引导、打断、取消或恢复一次 Agent 运行", + "Start, steer, interrupt, cancel, or recover an agent turn", + "查看并逐个或批量回答等待中的权限请求", + "Review and answer pending permission requests individually or in a batch", + "分页加载、搜索和回填历史消息与会话内容", + "Page through, search, and backfill historical turns and session content", + "查看工具调用与后台命令,读取输出并继续输入或停止", + "Inspect tool calls and background commands, read output, send input, or stop them", + "创建会话目标、更新目标内容与状态并清除目标", + "Create session goals, update their objective and status, and clear them", + "查看单个会话的请求、Token 与成本用量报告", + "View request, token, and cost usage for an individual session", + "重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆", + "Reload session context, initialize AGENTS.md, and manage long-term memory", + "使用 BTW 轻量问答与编辑器内联 AI,并可随时取消", + "Use lightweight BTW questions and inline editor AI, with cancellation" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.ai-assistant/" + }, + { + "id": "feature.agents", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "Agent 管理", + "titleEn": "Agents", + "summaryZh": "管理内置、自定义和子 Agent,让不同角色分工处理研究、编码、评审等任务。", + "summaryEn": "Manage built-in, custom, and subagents so specialized roles can handle research, coding, review, and more.", + "keywordsZh": [ + "智能体", + "子 Agent", + "自定义 Agent", + "多 Agent", + "并行协作" + ], + "keywordsEn": [ + "agent", + "subagent", + "custom agent", + "multi-agent", + "parallel collaboration" + ], + "highlightsZh": [ + "查看可用 Agent", + "创建和编辑自定义 Agent", + "让主 Agent 委派并行任务" + ], + "highlightsEn": [ + "Browse available agents", + "Create and edit custom agents", + "Let the primary agent delegate parallel work" + ], + "items": [ + { + "id": "browse-agents", + "titleZh": "查看内置、用户、项目与当前环境可见的 Agent", + "titleEn": "Browse built-in, user, project, and currently visible agents" + }, + { + "id": "custom-agent-create", + "titleZh": "创建自定义 Agent 并设置名称、说明和角色", + "titleEn": "Create custom agents with a name, description, and role" + }, + { + "id": "custom-agent-manage", + "titleZh": "读取、编辑、重新加载或删除自定义 Agent", + "titleEn": "Inspect, edit, reload, or delete custom agents" + }, + { + "id": "subagent-manage", + "titleZh": "创建、配置、查看和删除可委派的子 Agent", + "titleEn": "Create, configure, inspect, and delete delegatable subagents" + }, + { + "id": "capability-summary", + "titleZh": "查看每个 Agent 的工具、Skills、只读状态和能力摘要", + "titleEn": "Inspect each agent's tools, Skills, read-only state, and capability summary" + }, + { + "id": "tools-skills", + "titleZh": "按 Agent 选择工具组、单个工具、Skill 组与 Skills", + "titleEn": "Choose tool groups, individual tools, skill groups, and Skills per agent" + }, + { + "id": "delegation", + "titleZh": "让主 Agent 委派并行研究、编码和评审任务并设置超时", + "titleEn": "Let the primary agent delegate parallel research, coding, and review work with timeouts" + } + ], + "stepsZh": [ + "打开 Agents", + "选择现有 Agent 或创建一个角色", + "在会话中指定角色,或让主 Agent 自动委派" + ], + "stepsEn": [ + "Open Agents", + "Choose an existing agent or create a role", + "Select the role in a session or let the primary agent delegate" + ], + "agentExamplesZh": [ + "打开 Agents,我想看看有哪些专门角色", + "帮我进入 Agent 管理页" + ], + "agentExamplesEn": [ + "Open Agents so I can see the specialized roles", + "Take me to agent management" + ], + "destination": { + "kind": "action", + "actionId": "surface.agents.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.agents", + "Agent 管理", + "Agents", + "AI 与协作", + "AI & collaboration", + "智能体", + "子 Agent", + "自定义 Agent", + "多 Agent", + "并行协作", + "agent", + "subagent", + "custom agent", + "multi-agent", + "parallel collaboration", + "查看可用 Agent", + "创建和编辑自定义 Agent", + "让主 Agent 委派并行任务", + "Browse available agents", + "Create and edit custom agents", + "Let the primary agent delegate parallel work", + "查看内置、用户、项目与当前环境可见的 Agent", + "Browse built-in, user, project, and currently visible agents", + "创建自定义 Agent 并设置名称、说明和角色", + "Create custom agents with a name, description, and role", + "读取、编辑、重新加载或删除自定义 Agent", + "Inspect, edit, reload, or delete custom agents", + "创建、配置、查看和删除可委派的子 Agent", + "Create, configure, inspect, and delete delegatable subagents", + "查看每个 Agent 的工具、Skills、只读状态和能力摘要", + "Inspect each agent's tools, Skills, read-only state, and capability summary", + "按 Agent 选择工具组、单个工具、Skill 组与 Skills", + "Choose tool groups, individual tools, skill groups, and Skills per agent", + "让主 Agent 委派并行研究、编码和评审任务并设置超时", + "Let the primary agent delegate parallel research, coding, and review work with timeouts" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.agents/" + }, + { + "id": "feature.personal-assistants", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "个人助理", + "titleEn": "Personal assistants", + "summaryZh": "在助理空间中创建和管理自己的长期 AI 助理,定义身份与人设、配置默认能力,并从同一处开始会话或安排定时任务。", + "summaryEn": "Create and manage persistent AI assistants, define their identity and persona, configure default capabilities, and start chats or scheduled work from one place.", + "keywordsZh": [ + "助理", + "个人助理", + "育苗场", + "主助理", + "身份", + "头像", + "人设", + "Persona", + "默认工具", + "默认技能" + ], + "keywordsEn": [ + "assistant", + "personal assistant", + "nursery", + "primary assistant", + "identity", + "avatar", + "persona", + "default tools", + "default skills" + ], + "highlightsZh": [ + "创建、设为主助理或删除助理", + "编辑身份、头像与 Persona 文档", + "配置默认 Skills、内置工具和 MCP 工具" + ], + "highlightsEn": [ + "Create, select a primary assistant, or delete assistants", + "Edit identity, avatar, and persona documents", + "Configure default Skills, built-in tools, and MCP tools" + ], + "items": [ + { + "id": "assistant-gallery", + "titleZh": "浏览已有助理、创建新助理并查看每个助理的身份与能力概览", + "titleEn": "Browse existing assistants, create a new one, and review each assistant's identity and capability summary" + }, + { + "id": "primary-delete-reset", + "titleZh": "设为主助理、删除非主助理,或将助理工作区重置为默认状态", + "titleEn": "Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults" + }, + { + "id": "identity-avatar", + "titleZh": "编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符", + "titleEn": "Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character" + }, + { + "id": "persona-documents", + "titleZh": "读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter", + "titleEn": "Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter" + }, + { + "id": "default-skills", + "titleZh": "为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态", + "titleEn": "Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability" + }, + { + "id": "default-builtin-tools", + "titleZh": "逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态", + "titleEn": "Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults" + }, + { + "id": "default-mcp-tools", + "titleZh": "按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具", + "titleEn": "Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants" + }, + { + "id": "defaults-discovery-reset", + "titleZh": "按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值", + "titleEn": "Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults" + }, + { + "id": "assistant-sessions", + "titleZh": "从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话", + "titleEn": "Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page" + }, + { + "id": "assistant-schedules", + "titleZh": "查看和管理仅属于当前助理工作区的定时会话与自动任务", + "titleEn": "Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace" + } + ], + "stepsZh": [ + "打开“助理”", + "创建助理或选择现有助理", + "编辑身份与人设,配置默认能力,然后开始会话或定时任务" + ], + "stepsEn": [ + "Open Assistants", + "Create an assistant or choose an existing one", + "Edit its identity and persona, configure defaults, then start a chat or scheduled task" + ], + "agentExamplesZh": [ + "打开我的个人助理", + "带我去育苗场配置助理的默认工具", + "我想修改主助理的人设" + ], + "agentExamplesEn": [ + "Open my personal assistants", + "Take me to the nursery to configure default assistant tools", + "I want to edit my primary assistant's persona" + ], + "destination": { + "kind": "scene", + "sceneId": "profile" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.personal-assistants", + "个人助理", + "Personal assistants", + "AI 与协作", + "AI & collaboration", + "助理", + "育苗场", + "主助理", + "身份", + "头像", + "人设", + "Persona", + "默认工具", + "默认技能", + "assistant", + "personal assistant", + "nursery", + "primary assistant", + "identity", + "avatar", + "persona", + "default tools", + "default skills", + "创建、设为主助理或删除助理", + "编辑身份、头像与 Persona 文档", + "配置默认 Skills、内置工具和 MCP 工具", + "Create, select a primary assistant, or delete assistants", + "Edit identity, avatar, and persona documents", + "Configure default Skills, built-in tools, and MCP tools", + "浏览已有助理、创建新助理并查看每个助理的身份与能力概览", + "Browse existing assistants, create a new one, and review each assistant's identity and capability summary", + "设为主助理、删除非主助理,或将助理工作区重置为默认状态", + "Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults", + "编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符", + "Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character", + "读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter", + "Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter", + "为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态", + "Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability", + "逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态", + "Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults", + "按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具", + "Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants", + "按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值", + "Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults", + "从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话", + "Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page", + "查看和管理仅属于当前助理工作区的定时会话与自动任务", + "Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.personal-assistants/" + }, + { + "id": "feature.projects", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "项目与工作区", + "titleEn": "Projects & workspaces", + "summaryZh": "打开本地目录或创建项目,让文件、会话、终端和 Agent 围绕同一工作区协作。", + "summaryEn": "Open a local directory or create a project so files, sessions, terminals, and agents share one workspace.", + "keywordsZh": [ + "项目", + "工作区", + "打开文件夹", + "新建项目", + "切换项目" + ], + "keywordsEn": [ + "project", + "workspace", + "open folder", + "new project", + "switch project" + ], + "highlightsZh": [ + "打开现有目录", + "创建新项目", + "在多个工作区间切换" + ], + "highlightsEn": [ + "Open an existing directory", + "Create a new project", + "Switch between workspaces" + ], + "items": [ + { + "id": "open-close-switch", + "titleZh": "打开、关闭、切换并重新排序多个工作区", + "titleEn": "Open, close, switch, and reorder multiple workspaces" + }, + { + "id": "recent-workspaces", + "titleZh": "查看、清理和重新打开最近使用的项目", + "titleEn": "Review, clean up, and reopen recently used projects" + }, + { + "id": "workspace-metadata", + "titleZh": "扫描并维护工作区名称、信息、关联目录和 Persona 文件", + "titleEn": "Scan and maintain workspace names, metadata, related directories, and persona files" + }, + { + "id": "file-watch", + "titleZh": "监听项目文件变化并查看当前监听路径", + "titleEn": "Watch project file changes and inspect active watched paths" + }, + { + "id": "workspace-search", + "titleZh": "按文件名、路径或文件内容搜索本地工作区", + "titleEn": "Search local workspaces by filename, path, or file content" + }, + { + "id": "remote-open", + "titleZh": "从项目流程打开 SSH 或其他远程工作区", + "titleEn": "Open SSH and other remote workspaces from the project flow" + }, + { + "id": "project-health", + "titleZh": "查看当前工作区、应用状态、健康状态与统计信息", + "titleEn": "Inspect the current workspace, app state, health, and statistics" + } + ], + "stepsZh": [ + "选择“打开项目”或“新建项目”", + "选择本地目录或配置远程位置", + "从侧边栏进入项目文件与会话" + ], + "stepsEn": [ + "Choose Open Project or New Project", + "Select a local directory or configure a remote location", + "Use the sidebar to access files and sessions" + ], + "agentExamplesZh": [ + "帮我打开一个项目", + "打开新建项目的界面" + ], + "agentExamplesEn": [ + "Help me open a project", + "Open the new-project flow" + ], + "destination": { + "kind": "action", + "actionId": "project.open" + }, + "operations": [ + { + "id": "open-project", + "titleZh": "打开项目", + "titleEn": "Open project", + "descriptionZh": "选择并打开一个已有目录。", + "descriptionEn": "Choose and open an existing directory.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + } + }, + { + "id": "new-project", + "titleZh": "新建项目", + "titleEn": "Create project", + "descriptionZh": "打开新建项目流程。", + "descriptionEn": "Open the new-project flow.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + } + } + ], + "options": [], + "searchTerms": [ + "feature.projects", + "项目与工作区", + "Projects & workspaces", + "项目与开发", + "Projects & development", + "项目", + "工作区", + "打开文件夹", + "新建项目", + "切换项目", + "project", + "workspace", + "open folder", + "new project", + "switch project", + "打开现有目录", + "创建新项目", + "在多个工作区间切换", + "Open an existing directory", + "Create a new project", + "Switch between workspaces", + "打开、关闭、切换并重新排序多个工作区", + "Open, close, switch, and reorder multiple workspaces", + "查看、清理和重新打开最近使用的项目", + "Review, clean up, and reopen recently used projects", + "扫描并维护工作区名称、信息、关联目录和 Persona 文件", + "Scan and maintain workspace names, metadata, related directories, and persona files", + "监听项目文件变化并查看当前监听路径", + "Watch project file changes and inspect active watched paths", + "按文件名、路径或文件内容搜索本地工作区", + "Search local workspaces by filename, path, or file content", + "从项目流程打开 SSH 或其他远程工作区", + "Open SSH and other remote workspaces from the project flow", + "查看当前工作区、应用状态、健康状态与统计信息", + "Inspect the current workspace, app state, health, and statistics" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.projects/" + }, + { + "id": "feature.files-editor", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "文件与代码编辑", + "titleEn": "Files & code editing", + "summaryZh": "浏览、搜索和编辑项目文件,查看差异、代码符号、诊断与 Agent 产生的改动。", + "summaryEn": "Browse, search, and edit project files while inspecting diffs, symbols, diagnostics, and agent changes.", + "keywordsZh": [ + "文件", + "代码", + "编辑器", + "搜索文件", + "差异", + "诊断", + "LSP" + ], + "keywordsEn": [ + "files", + "code", + "editor", + "file search", + "diff", + "diagnostics", + "LSP" + ], + "highlightsZh": [ + "文件树与全文搜索", + "代码导航、格式化和诊断", + "查看、接受或撤销 Agent 改动" + ], + "highlightsEn": [ + "File tree and full-text search", + "Code navigation, formatting, and diagnostics", + "Review, accept, or revert agent changes" + ], + "items": [ + { + "id": "file-tree", + "titleZh": "浏览文件树并创建、重命名、删除或在系统中显示文件和目录", + "titleEn": "Browse the file tree and create, rename, delete, or reveal files and directories" + }, + { + "id": "indexed-search", + "titleZh": "建立或重建索引,按文件名和全文内容流式搜索", + "titleEn": "Build or rebuild an index and stream filename and full-text search results" + }, + { + "id": "edit-save", + "titleZh": "读取、编辑、保存文件并同步编辑器状态", + "titleEn": "Read, edit, and save files while synchronizing editor state" + }, + { + "id": "diffs", + "titleZh": "查看修改文件、会话、轮次和单次操作的差异与统计", + "titleEn": "Inspect diffs and statistics by file, session, turn, or operation" + }, + { + "id": "accept-reject", + "titleZh": "按文件、操作或整个会话接受或拒绝 Agent 改动", + "titleEn": "Accept or reject agent changes by file, operation, or whole session" + }, + { + "id": "snapshots-rollback", + "titleZh": "查看文件变更历史和快照,并回滚整个会话或指定轮次", + "titleEn": "Review file history and snapshots, then roll back a session or selected turn" + }, + { + "id": "lsp-navigation", + "titleZh": "使用 Hover、跳转定义、查找引用、文档符号与高亮", + "titleEn": "Use hover, go to definition, references, document symbols, and highlights" + }, + { + "id": "lsp-editing", + "titleZh": "使用补全、格式化、重命名、代码操作、内联提示与语义高亮", + "titleEn": "Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting" + }, + { + "id": "lsp-plugins", + "titleZh": "检测项目并安装、启动、停止或卸载 LSP 插件", + "titleEn": "Detect projects and install, start, stop, or uninstall LSP plugins" + }, + { + "id": "attachments", + "titleZh": "粘贴、拖放或上传文件与图片作为会话上下文", + "titleEn": "Paste, drop, or upload files and images as session context" + } + ], + "stepsZh": [ + "先打开一个项目", + "打开“文件”", + "选择文件进行编辑,或搜索内容与符号" + ], + "stepsEn": [ + "Open a project first", + "Open Files", + "Choose a file to edit, or search content and symbols" + ], + "agentExamplesZh": [ + "打开项目文件", + "带我去文件和代码编辑器" + ], + "agentExamplesEn": [ + "Open the project files", + "Take me to the file and code editor" + ], + "destination": { + "kind": "action", + "actionId": "surface.files.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.files-editor", + "文件与代码编辑", + "Files & code editing", + "项目与开发", + "Projects & development", + "文件", + "代码", + "编辑器", + "搜索文件", + "差异", + "诊断", + "LSP", + "files", + "code", + "editor", + "file search", + "diff", + "diagnostics", + "文件树与全文搜索", + "代码导航、格式化和诊断", + "查看、接受或撤销 Agent 改动", + "File tree and full-text search", + "Code navigation, formatting, and diagnostics", + "Review, accept, or revert agent changes", + "浏览文件树并创建、重命名、删除或在系统中显示文件和目录", + "Browse the file tree and create, rename, delete, or reveal files and directories", + "建立或重建索引,按文件名和全文内容流式搜索", + "Build or rebuild an index and stream filename and full-text search results", + "读取、编辑、保存文件并同步编辑器状态", + "Read, edit, and save files while synchronizing editor state", + "查看修改文件、会话、轮次和单次操作的差异与统计", + "Inspect diffs and statistics by file, session, turn, or operation", + "按文件、操作或整个会话接受或拒绝 Agent 改动", + "Accept or reject agent changes by file, operation, or whole session", + "查看文件变更历史和快照,并回滚整个会话或指定轮次", + "Review file history and snapshots, then roll back a session or selected turn", + "使用 Hover、跳转定义、查找引用、文档符号与高亮", + "Use hover, go to definition, references, document symbols, and highlights", + "使用补全、格式化、重命名、代码操作、内联提示与语义高亮", + "Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting", + "检测项目并安装、启动、停止或卸载 LSP 插件", + "Detect projects and install, start, stop, or uninstall LSP plugins", + "粘贴、拖放或上传文件与图片作为会话上下文", + "Paste, drop, or upload files and images as session context" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.files-editor/" + }, + { + "id": "feature.terminal", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "终端", + "titleEn": "Terminal", + "summaryZh": "在当前项目中运行 Shell、查看输出、保留命令历史,并让 Agent 与同一终端环境协作。", + "summaryEn": "Run a shell in the current project, inspect output, keep command history, and share the same terminal context with agents.", + "keywordsZh": [ + "终端", + "命令行", + "Shell", + "控制台", + "运行命令" + ], + "keywordsEn": [ + "terminal", + "command line", + "shell", + "console", + "run command" + ], + "highlightsZh": [ + "创建多个终端", + "选择默认 Shell", + "查看运行状态和历史" + ], + "highlightsEn": [ + "Create multiple terminals", + "Choose the default shell", + "Inspect running state and history" + ], + "items": [ + { + "id": "multiple-terminals", + "titleZh": "创建、列出、切换和关闭多个终端会话", + "titleEn": "Create, list, switch, and close multiple terminal sessions" + }, + { + "id": "shells", + "titleZh": "检测可用 Shell,并为终端选择默认或指定 Shell", + "titleEn": "Detect available shells and choose a default or explicit shell" + }, + { + "id": "working-directory", + "titleZh": "在当前项目目录或指定起始目录创建终端", + "titleEn": "Create terminals in the current project or a chosen starting directory" + }, + { + "id": "command-control", + "titleZh": "执行命令、写入输入并发送中断或其他信号", + "titleEn": "Execute commands, write input, and send interrupt or other signals" + }, + { + "id": "resize", + "titleZh": "随终端面板大小变化同步行列尺寸", + "titleEn": "Synchronize terminal rows and columns as the panel resizes" + }, + { + "id": "history-integration", + "titleZh": "查看命令历史并检测 Shell Integration 支持", + "titleEn": "Review command history and detect shell-integration support" + }, + { + "id": "shutdown", + "titleZh": "确认输出接收并安全关闭单个或全部终端", + "titleEn": "Acknowledge output and safely shut down one or all terminals" + } + ], + "stepsZh": [ + "打开终端", + "确认当前目录", + "输入命令;需要时新建额外终端" + ], + "stepsEn": [ + "Open Terminal", + "Confirm the current directory", + "Enter a command and create extra terminals as needed" + ], + "agentExamplesZh": [ + "打开一个终端", + "切到终端界面" + ], + "agentExamplesEn": [ + "Open a terminal", + "Switch to the terminal" + ], + "destination": { + "kind": "action", + "actionId": "surface.terminal.open" + }, + "operations": [ + { + "id": "new-terminal", + "titleZh": "新建终端", + "titleEn": "Create terminal", + "descriptionZh": "在当前工作区创建终端。", + "descriptionEn": "Create a terminal in the current workspace.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + } + } + ], + "options": [], + "searchTerms": [ + "feature.terminal", + "终端", + "Terminal", + "项目与开发", + "Projects & development", + "命令行", + "Shell", + "控制台", + "运行命令", + "terminal", + "command line", + "shell", + "console", + "run command", + "创建多个终端", + "选择默认 Shell", + "查看运行状态和历史", + "Create multiple terminals", + "Choose the default shell", + "Inspect running state and history", + "创建、列出、切换和关闭多个终端会话", + "Create, list, switch, and close multiple terminal sessions", + "检测可用 Shell,并为终端选择默认或指定 Shell", + "Detect available shells and choose a default or explicit shell", + "在当前项目目录或指定起始目录创建终端", + "Create terminals in the current project or a chosen starting directory", + "执行命令、写入输入并发送中断或其他信号", + "Execute commands, write input, and send interrupt or other signals", + "随终端面板大小变化同步行列尺寸", + "Synchronize terminal rows and columns as the panel resizes", + "查看命令历史并检测 Shell Integration 支持", + "Review command history and detect shell-integration support", + "确认输出接收并安全关闭单个或全部终端", + "Acknowledge output and safely shut down one or all terminals" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.terminal/" + }, + { + "id": "feature.git", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "Git 版本控制", + "titleEn": "Git version control", + "summaryZh": "查看改动、分支和提交,完成暂存、提交、合并、Cherry-pick 与 Worktree 工作流。", + "summaryEn": "Inspect changes, branches, and commits; stage, commit, merge, cherry-pick, and work with Git worktrees.", + "keywordsZh": [ + "Git", + "版本控制", + "分支", + "提交", + "暂存", + "合并", + "Worktree" + ], + "keywordsEn": [ + "git", + "source control", + "branch", + "commit", + "stage", + "merge", + "worktree" + ], + "highlightsZh": [ + "查看工作区改动", + "管理分支与提交", + "使用 Worktree 隔离并行任务" + ], + "highlightsEn": [ + "Inspect workspace changes", + "Manage branches and commits", + "Use worktrees to isolate parallel work" + ], + "items": [ + { + "id": "status-diff", + "titleZh": "查看仓库状态、修改文件和逐文件 Diff", + "titleEn": "Inspect repository status, changed files, and per-file diffs" + }, + { + "id": "stage-reset", + "titleZh": "暂存文件、取消暂存并重置到指定提交", + "titleEn": "Stage files, unstage changes, and reset to a selected commit" + }, + { + "id": "commit", + "titleZh": "预览或生成提交信息并创建提交", + "titleEn": "Preview or generate a commit message and create the commit" + }, + { + "id": "sync", + "titleZh": "从远端 Pull 并向远端 Push", + "titleEn": "Pull from and push to remotes" + }, + { + "id": "branches", + "titleZh": "查看、创建、切换和删除本地分支", + "titleEn": "Browse, create, check out, and delete local branches" + }, + { + "id": "graph-history", + "titleZh": "浏览提交图谱与仓库历史并保存最近访问记录", + "titleEn": "Browse the commit graph and repository history, including recent-history persistence" + }, + { + "id": "revision-content", + "titleZh": "解析 Revision 并查看任意提交中的文件内容", + "titleEn": "Resolve revisions and inspect file content from any commit" + }, + { + "id": "cherry-pick", + "titleZh": "执行、继续或中止 Cherry-pick", + "titleEn": "Start, continue, or abort a cherry-pick" + }, + { + "id": "trust-worktrees", + "titleZh": "管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除", + "titleEn": "Manage repository trust and create, bind, promote, recreate, or remove worktrees" + } + ], + "stepsZh": [ + "打开 Git", + "选择改动或分支", + "执行暂存、提交或分支操作" + ], + "stepsEn": [ + "Open Git", + "Choose changes or a branch", + "Stage, commit, or perform a branch operation" + ], + "agentExamplesZh": [ + "打开 Git 面板", + "带我查看当前代码改动" + ], + "agentExamplesEn": [ + "Open the Git panel", + "Show me the current code changes" + ], + "destination": { + "kind": "scene", + "sceneId": "git" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.git", + "Git 版本控制", + "Git version control", + "项目与开发", + "Projects & development", + "Git", + "版本控制", + "分支", + "提交", + "暂存", + "合并", + "Worktree", + "git", + "source control", + "branch", + "commit", + "stage", + "merge", + "worktree", + "查看工作区改动", + "管理分支与提交", + "使用 Worktree 隔离并行任务", + "Inspect workspace changes", + "Manage branches and commits", + "Use worktrees to isolate parallel work", + "查看仓库状态、修改文件和逐文件 Diff", + "Inspect repository status, changed files, and per-file diffs", + "暂存文件、取消暂存并重置到指定提交", + "Stage files, unstage changes, and reset to a selected commit", + "预览或生成提交信息并创建提交", + "Preview or generate a commit message and create the commit", + "从远端 Pull 并向远端 Push", + "Pull from and push to remotes", + "查看、创建、切换和删除本地分支", + "Browse, create, check out, and delete local branches", + "浏览提交图谱与仓库历史并保存最近访问记录", + "Browse the commit graph and repository history, including recent-history persistence", + "解析 Revision 并查看任意提交中的文件内容", + "Resolve revisions and inspect file content from any commit", + "执行、继续或中止 Cherry-pick", + "Start, continue, or abort a cherry-pick", + "管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除", + "Manage repository trust and create, bind, promote, recreate, or remove worktrees" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.git/" + }, + { + "id": "feature.code-review", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "代码评审与 Pull Request", + "titleEn": "Code review & pull requests", + "summaryZh": "阅读改动与 PR 上下文,查看 CI 日志,生成提交信息,并组织深度代码评审。", + "summaryEn": "Review changes and pull-request context, inspect CI logs, generate commit messages, and run deeper code reviews.", + "keywordsZh": [ + "代码评审", + "PR", + "Pull Request", + "CI 日志", + "提交信息", + "Deep Review" + ], + "keywordsEn": [ + "code review", + "PR", + "pull request", + "CI log", + "commit message", + "deep review" + ], + "highlightsZh": [ + "查看 PR、Issue 和 CI 上下文", + "生成提交信息", + "针对改动发起深度评审" + ], + "highlightsEn": [ + "Inspect PR, issue, and CI context", + "Generate commit messages", + "Run deep reviews against changes" + ], + "items": [ + { + "id": "workspace-context", + "titleZh": "读取仓库、分支、工作区快照和评审目标", + "titleEn": "Load repository, branch, workspace snapshot, and review-target context" + }, + { + "id": "pull-request", + "titleZh": "查看 Pull Request 详情、分页内容与关联改动", + "titleEn": "Inspect pull-request details, paged content, and related changes" + }, + { + "id": "ci-logs", + "titleZh": "读取 Pull Request 的 CI 运行日志", + "titleEn": "Read CI run logs for a pull request" + }, + { + "id": "issues", + "titleZh": "读取关联 Issue 的标题、描述与上下文", + "titleEn": "Read the title, body, and context of linked issues" + }, + { + "id": "authentication", + "titleZh": "保存或清除评审平台访问令牌", + "titleEn": "Store or clear review-platform access tokens" + }, + { + "id": "commit-message", + "titleZh": "预览、生成或快速采用提交信息", + "titleEn": "Preview, generate, or quickly apply a commit message" + }, + { + "id": "deep-review", + "titleZh": "针对工作区、提交或 PR 发起 Deep Review 并控制评审队列", + "titleEn": "Run Deep Review against a workspace, commit, or pull request and control its queue" + } + ], + "stepsZh": [ + "打开项目文件或 Git", + "选择改动或评审目标", + "在会话中请求评审或打开对应详情" + ], + "stepsEn": [ + "Open project files or Git", + "Choose a change or review target", + "Ask for a review in the session or open its details" + ], + "agentExamplesZh": [ + "打开文件面板,我要评审当前改动", + "带我查看 Pull Request 相关能力" + ], + "agentExamplesEn": [ + "Open Files so I can review the current changes", + "Take me to the pull-request workflow" + ], + "destination": { + "kind": "action", + "actionId": "surface.files.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.code-review", + "代码评审与 Pull Request", + "Code review & pull requests", + "项目与开发", + "Projects & development", + "代码评审", + "PR", + "Pull Request", + "CI 日志", + "提交信息", + "Deep Review", + "code review", + "pull request", + "CI log", + "commit message", + "deep review", + "查看 PR、Issue 和 CI 上下文", + "生成提交信息", + "针对改动发起深度评审", + "Inspect PR, issue, and CI context", + "Generate commit messages", + "Run deep reviews against changes", + "读取仓库、分支、工作区快照和评审目标", + "Load repository, branch, workspace snapshot, and review-target context", + "查看 Pull Request 详情、分页内容与关联改动", + "Inspect pull-request details, paged content, and related changes", + "读取 Pull Request 的 CI 运行日志", + "Read CI run logs for a pull request", + "读取关联 Issue 的标题、描述与上下文", + "Read the title, body, and context of linked issues", + "保存或清除评审平台访问令牌", + "Store or clear review-platform access tokens", + "预览、生成或快速采用提交信息", + "Preview, generate, or quickly apply a commit message", + "针对工作区、提交或 PR 发起 Deep Review 并控制评审队列", + "Run Deep Review against a workspace, commit, or pull request and control its queue" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.code-review/" + }, + { + "id": "feature.browser", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "内置浏览器", + "titleEn": "Built-in browser", + "summaryZh": "在 BitFun 内打开网页和本地服务;Agent 可直接读取页面、选择元素并点击、填写、滚动或截图。", + "summaryEn": "Open webpages and local services inside BitFun, where an agent can inspect the page and select, click, fill, scroll, or capture elements directly.", + "keywordsZh": [ + "浏览器", + "网页", + "URL", + "本地预览", + "Webview", + "Agent 控制浏览器", + "网页自动化", + "元素选择", + "点击网页", + "填写表单" + ], + "keywordsEn": [ + "browser", + "web", + "URL", + "local preview", + "webview", + "agent browser control", + "web automation", + "element selection", + "click page", + "fill form" + ], + "highlightsZh": [ + "打开网页和本地开发地址", + "Agent 读取并操作内置网页", + "与外部 CDP 浏览器共用动作契约", + "在会话旁并排查看页面" + ], + "highlightsEn": [ + "Open webpages and local development URLs", + "Let an agent inspect and operate the built-in page", + "Share one action contract with external CDP browsers", + "Keep the page beside a session" + ], + "items": [ + { + "id": "open-urls", + "titleZh": "输入完整网址、本地域名或开发服务端口并在 BitFun 内打开", + "titleEn": "Open full URLs, local hostnames, or development-service ports inside BitFun" + }, + { + "id": "history-navigation", + "titleZh": "使用后退、前进和地址栏浏览页面历史", + "titleEn": "Navigate page history with Back, Forward, and the address bar" + }, + { + "id": "reload-status", + "titleZh": "刷新页面,并同步当前 URL、加载状态与错误提示", + "titleEn": "Reload pages and synchronize the current URL, loading state, and errors" + }, + { + "id": "scene-and-panel", + "titleZh": "既可作为独立浏览器场景,也可在会话旁的辅助面板中打开", + "titleEn": "Use the browser as a standalone scene or an auxiliary panel beside a session" + }, + { + "id": "element-picker", + "titleZh": "启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class", + "titleEn": "Start the element picker to highlight hovered elements and show tag, ID, and class details" + }, + { + "id": "element-context", + "titleZh": "点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文", + "titleEn": "Click an element to capture its CSS path, attributes, text, and HTML into the current session context" + }, + { + "id": "element-picker-cancel", + "titleZh": "再次点击选择按钮或按 Esc 取消元素选择并清理高亮", + "titleEn": "Click the picker again or press Escape to cancel selection and remove overlays" + }, + { + "id": "agent-page-automation", + "titleZh": "让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图", + "titleEn": "Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page" + }, + { + "id": "shared-browser-action-contract", + "titleZh": "内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约", + "titleEn": "Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers" + }, + { + "id": "browser-target-selection", + "titleZh": "通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面", + "titleEn": "Choose the built-in or external browser with target and locate a page by session_id, URL, or title" + }, + { + "id": "embedded-webview", + "titleZh": "桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接", + "titleEn": "Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place" + } + ], + "stepsZh": [ + "打开浏览器并输入网址或本地端口", + "直接告诉 Agent 要在页面上完成什么", + "Agent 先读取页面,再用元素引用执行操作" + ], + "stepsEn": [ + "Open Browser and enter a URL or local port", + "Tell the agent what to accomplish on the page", + "The agent inspects the page, then acts through element refs" + ], + "agentControl": { + "tool": "ControlHub", + "workflowZh": [ + "用 browser.open_builtin 打开网址并取得内置页面的 session_id", + "对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约", + "页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external" + ], + "workflowEn": [ + "Open the URL with browser.open_builtin and keep the returned built-in session_id", + "Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract", + "Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection" + ] + }, + "agentExamplesZh": [ + "在内置浏览器打开这个网址,然后找到登录按钮", + "读取当前内置网页并填写这个表单", + "用内置浏览器点开搜索结果并总结页面" + ], + "agentExamplesEn": [ + "Open this URL in the built-in browser and find the sign-in button", + "Inspect the current built-in page and fill this form", + "Use the built-in browser to open the search result and summarize the page" + ], + "destination": { + "kind": "action", + "actionId": "surface.browser.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.browser", + "内置浏览器", + "Built-in browser", + "项目与开发", + "Projects & development", + "浏览器", + "网页", + "URL", + "本地预览", + "Webview", + "Agent 控制浏览器", + "网页自动化", + "元素选择", + "点击网页", + "填写表单", + "browser", + "web", + "local preview", + "webview", + "agent browser control", + "web automation", + "element selection", + "click page", + "fill form", + "打开网页和本地开发地址", + "Agent 读取并操作内置网页", + "与外部 CDP 浏览器共用动作契约", + "在会话旁并排查看页面", + "Open webpages and local development URLs", + "Let an agent inspect and operate the built-in page", + "Share one action contract with external CDP browsers", + "Keep the page beside a session", + "输入完整网址、本地域名或开发服务端口并在 BitFun 内打开", + "Open full URLs, local hostnames, or development-service ports inside BitFun", + "使用后退、前进和地址栏浏览页面历史", + "Navigate page history with Back, Forward, and the address bar", + "刷新页面,并同步当前 URL、加载状态与错误提示", + "Reload pages and synchronize the current URL, loading state, and errors", + "既可作为独立浏览器场景,也可在会话旁的辅助面板中打开", + "Use the browser as a standalone scene or an auxiliary panel beside a session", + "启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class", + "Start the element picker to highlight hovered elements and show tag, ID, and class details", + "点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文", + "Click an element to capture its CSS path, attributes, text, and HTML into the current session context", + "再次点击选择按钮或按 Esc 取消元素选择并清理高亮", + "Click the picker again or press Escape to cancel selection and remove overlays", + "让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图", + "Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page", + "内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约", + "Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers", + "通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面", + "Choose the built-in or external browser with target and locate a page by session_id, URL, or title", + "桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接", + "Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place", + "用 browser.open_builtin 打开网址并取得内置页面的 session_id", + "对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约", + "页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external", + "Open the URL with browser.open_builtin and keep the returned built-in session_id", + "Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract", + "Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection", + "ControlHub" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.browser/" + }, + { + "id": "feature.computer-use", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "浏览器与桌面控制", + "titleEn": "Browser & desktop control", + "summaryZh": "授权 Agent 操作浏览器或本机界面,并明确管理辅助功能、屏幕录制与浏览器连接。", + "summaryEn": "Allow agents to operate a browser or local UI while explicitly managing accessibility, screen-recording, and browser connection access.", + "keywordsZh": [ + "Computer Use", + "桌面控制", + "浏览器控制", + "CDP", + "辅助功能", + "屏幕录制" + ], + "keywordsEn": [ + "computer use", + "desktop control", + "browser control", + "CDP", + "accessibility", + "screen recording" + ], + "highlightsZh": [ + "启用或停用 Computer Use", + "连接受支持的浏览器", + "检查并打开系统权限设置" + ], + "highlightsEn": [ + "Enable or disable Computer Use", + "Connect a supported browser", + "Inspect and open OS permission settings" + ], + "items": [ + { + "id": "status", + "titleZh": "检查 Computer Use 可用性、辅助功能和屏幕录制授权状态", + "titleEn": "Check Computer Use availability plus accessibility and screen-recording permission status" + }, + { + "id": "request-permissions", + "titleZh": "请求桌面控制所需的系统权限", + "titleEn": "Request the operating-system permissions required for desktop control" + }, + { + "id": "system-settings", + "titleZh": "直接打开对应的系统隐私与安全设置", + "titleEn": "Open the matching operating-system privacy and security settings" + }, + { + "id": "browser-discovery", + "titleZh": "发现受支持的浏览器并查看当前 CDP 连接状态", + "titleEn": "Discover supported browsers and inspect the current CDP connection state" + }, + { + "id": "launch-connect", + "titleZh": "启动浏览器控制或连接已经开放 CDP 的浏览器", + "titleEn": "Launch browser control or connect to a browser that already exposes CDP" + }, + { + "id": "default-cdp", + "titleZh": "启用默认 CDP 配置并按需要重启浏览器", + "titleEn": "Enable the default CDP setup and restart the browser when required" + }, + { + "id": "agent-actions", + "titleZh": "授权后让 Agent 截图、点击、输入、滚动并读取可见界面", + "titleEn": "After authorization, let agents capture, click, type, scroll, and inspect the visible interface" + } + ], + "stepsZh": [ + "打开执行控制设置", + "启用需要的能力", + "按提示授予系统权限或连接浏览器" + ], + "stepsEn": [ + "Open Execution Control settings", + "Enable the required capability", + "Grant OS access or connect a browser when prompted" + ], + "agentExamplesZh": [ + "打开桌面控制设置", + "带我配置浏览器控制" + ], + "agentExamplesEn": [ + "Open desktop-control settings", + "Take me to browser-control setup" + ], + "destination": { + "kind": "settings", + "pageId": "tools.execution" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.computer-use", + "浏览器与桌面控制", + "Browser & desktop control", + "项目与开发", + "Projects & development", + "Computer Use", + "桌面控制", + "浏览器控制", + "CDP", + "辅助功能", + "屏幕录制", + "computer use", + "desktop control", + "browser control", + "accessibility", + "screen recording", + "启用或停用 Computer Use", + "连接受支持的浏览器", + "检查并打开系统权限设置", + "Enable or disable Computer Use", + "Connect a supported browser", + "Inspect and open OS permission settings", + "检查 Computer Use 可用性、辅助功能和屏幕录制授权状态", + "Check Computer Use availability plus accessibility and screen-recording permission status", + "请求桌面控制所需的系统权限", + "Request the operating-system permissions required for desktop control", + "直接打开对应的系统隐私与安全设置", + "Open the matching operating-system privacy and security settings", + "发现受支持的浏览器并查看当前 CDP 连接状态", + "Discover supported browsers and inspect the current CDP connection state", + "启动浏览器控制或连接已经开放 CDP 的浏览器", + "Launch browser control or connect to a browser that already exposes CDP", + "启用默认 CDP 配置并按需要重启浏览器", + "Enable the default CDP setup and restart the browser when required", + "授权后让 Agent 截图、点击、输入、滚动并读取可见界面", + "After authorization, let agents capture, click, type, scroll, and inspect the visible interface" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.computer-use/" + }, + { + "id": "feature.skills", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Skills 技能", + "titleEn": "Skills", + "summaryZh": "为 Agent 安装和管理可复用的专业工作流,并控制哪些模式可以使用它们。", + "summaryEn": "Install and manage reusable expert workflows for agents, and control which modes can use them.", + "keywordsZh": [ + "Skill", + "技能", + "工作流", + "技能市场", + "安装技能" + ], + "keywordsEn": [ + "skill", + "workflow", + "skill market", + "install skill", + "agent capability" + ], + "highlightsZh": [ + "浏览与搜索 Skills", + "安装、更新或移除 Skill", + "按模式启用或停用" + ], + "highlightsEn": [ + "Browse and search Skills", + "Install, update, or remove a Skill", + "Enable or disable by mode" + ], + "items": [ + { + "id": "installed-catalog", + "titleZh": "统一查看用户级、项目级、本地和远程来源的已安装 Skills", + "titleEn": "Browse installed Skills from user, project, local, and remote sources in one catalog" + }, + { + "id": "market", + "titleZh": "浏览、搜索和刷新 Skill 市场", + "titleEn": "Browse, search, and refresh the Skill market" + }, + { + "id": "market-install", + "titleZh": "把市场 Skill 下载到用户级或当前项目", + "titleEn": "Download a market Skill for the user or current project" + }, + { + "id": "local-add", + "titleZh": "校验本地 Skill 路径并添加到用户级或项目级", + "titleEn": "Validate a local Skill path and add it at user or project scope" + }, + { + "id": "remove", + "titleZh": "删除已安装的用户级或项目级 Skill", + "titleEn": "Remove an installed user-level or project-level Skill" + }, + { + "id": "global-enable", + "titleZh": "在全局范围启用或停用单个 Skill", + "titleEn": "Enable or disable an individual Skill globally" + }, + { + "id": "mode-selection", + "titleZh": "按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择", + "titleEn": "Choose Skills and skill groups per agent mode and restore defaults" + }, + { + "id": "shadowing", + "titleZh": "识别同名 Skill 的用户级与项目级遮蔽优先级", + "titleEn": "Understand user-versus-project shadowing precedence for same-named Skills" + } + ], + "stepsZh": [ + "打开 Skills", + "搜索需要的工作流", + "安装后在会话中调用" + ], + "stepsEn": [ + "Open Skills", + "Search for the workflow you need", + "Install it and invoke it from a session" + ], + "agentExamplesZh": [ + "打开 Skills", + "带我去技能管理" + ], + "agentExamplesEn": [ + "Open Skills", + "Take me to skill management" + ], + "destination": { + "kind": "action", + "actionId": "surface.skills.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.skills", + "Skills 技能", + "Skills", + "扩展与自动化", + "Extensions & automation", + "Skill", + "技能", + "工作流", + "技能市场", + "安装技能", + "skill", + "workflow", + "skill market", + "install skill", + "agent capability", + "浏览与搜索 Skills", + "安装、更新或移除 Skill", + "按模式启用或停用", + "Browse and search Skills", + "Install, update, or remove a Skill", + "Enable or disable by mode", + "统一查看用户级、项目级、本地和远程来源的已安装 Skills", + "Browse installed Skills from user, project, local, and remote sources in one catalog", + "浏览、搜索和刷新 Skill 市场", + "Browse, search, and refresh the Skill market", + "把市场 Skill 下载到用户级或当前项目", + "Download a market Skill for the user or current project", + "校验本地 Skill 路径并添加到用户级或项目级", + "Validate a local Skill path and add it at user or project scope", + "删除已安装的用户级或项目级 Skill", + "Remove an installed user-level or project-level Skill", + "在全局范围启用或停用单个 Skill", + "Enable or disable an individual Skill globally", + "按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择", + "Choose Skills and skill groups per agent mode and restore defaults", + "识别同名 Skill 的用户级与项目级遮蔽优先级", + "Understand user-versus-project shadowing precedence for same-named Skills" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.skills/" + }, + { + "id": "feature.miniapps", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Mini Apps 小应用", + "titleEn": "Mini Apps", + "summaryZh": "在 BitFun 内安装、创建和运行轻量应用,让界面、数据与 Agent 工作流组合在一起。", + "summaryEn": "Install, create, and run lightweight apps inside BitFun, combining UI, data, and agent workflows.", + "keywordsZh": [ + "Mini App", + "小应用", + "应用市场", + "创建应用", + "运行应用" + ], + "keywordsEn": [ + "mini app", + "app market", + "create app", + "run app", + "embedded app" + ], + "highlightsZh": [ + "浏览 Mini App 市场", + "安装或创建 Mini App", + "在独立场景中运行并与 Agent 对话" + ], + "highlightsEn": [ + "Browse the Mini App market", + "Install or create a Mini App", + "Run it in its own scene and chat with its agent" + ], + "items": [ + { + "id": "gallery-lifecycle", + "titleZh": "查看、搜索、创建、导入、编辑和删除 Mini App", + "titleEn": "Browse, search, create, import, edit, and delete Mini Apps" + }, + { + "id": "market", + "titleZh": "浏览市场、查看详情并安装或更新发布版本", + "titleEn": "Browse the market, inspect listings, and install or update releases" + }, + { + "id": "market-account", + "titleZh": "登录市场账户并收藏、评分和查看已安装来源", + "titleEn": "Sign in to the market, favorite and rate apps, and inspect installed origins" + }, + { + "id": "permissions", + "titleZh": "按路径或工作区授予权限,并在定制前审查权限差异", + "titleEn": "Grant path or workspace access and review permission changes before customization" + }, + { + "id": "runtime", + "titleZh": "运行 Mini App Host 与 Worker,查看状态并停止后台 Worker", + "titleEn": "Run Mini App host and worker calls, inspect status, and stop background workers" + }, + { + "id": "storage", + "titleZh": "为正式应用和定制草稿分别读取与保存持久状态", + "titleEn": "Read and save persistent state separately for installed apps and customization drafts" + }, + { + "id": "agent-ai", + "titleZh": "在 Mini App 中调用模型补全、聊天和专属 Agent 会话", + "titleEn": "Use model completion, chat, and dedicated agent sessions inside Mini Apps" + }, + { + "id": "customization", + "titleZh": "创建定制草稿、实时预览,并应用、同步或丢弃修改", + "titleEn": "Create customization drafts, preview them live, and apply, sync, or discard changes" + }, + { + "id": "versions", + "titleZh": "查看版本历史并回滚到旧版本", + "titleEn": "Inspect version history and roll back to an earlier release" + }, + { + "id": "publishing", + "titleZh": "提交、撤回和审查市场发布,并可渲染幻灯片页面", + "titleEn": "Submit, withdraw, and review market releases, and render slide pages" + } + ], + "stepsZh": [ + "打开 Mini Apps", + "选择市场、已安装或创建", + "打开应用并按页面提示使用" + ], + "stepsEn": [ + "Open Mini Apps", + "Choose Market, Installed, or Create", + "Launch the app and follow its interface" + ], + "agentExamplesZh": [ + "打开 Mini Apps", + "带我去小应用市场" + ], + "agentExamplesEn": [ + "Open Mini Apps", + "Take me to the Mini App market" + ], + "destination": { + "kind": "action", + "actionId": "surface.miniapps.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.miniapps", + "Mini Apps 小应用", + "Mini Apps", + "扩展与自动化", + "Extensions & automation", + "Mini App", + "小应用", + "应用市场", + "创建应用", + "运行应用", + "mini app", + "app market", + "create app", + "run app", + "embedded app", + "浏览 Mini App 市场", + "安装或创建 Mini App", + "在独立场景中运行并与 Agent 对话", + "Browse the Mini App market", + "Install or create a Mini App", + "Run it in its own scene and chat with its agent", + "查看、搜索、创建、导入、编辑和删除 Mini App", + "Browse, search, create, import, edit, and delete Mini Apps", + "浏览市场、查看详情并安装或更新发布版本", + "Browse the market, inspect listings, and install or update releases", + "登录市场账户并收藏、评分和查看已安装来源", + "Sign in to the market, favorite and rate apps, and inspect installed origins", + "按路径或工作区授予权限,并在定制前审查权限差异", + "Grant path or workspace access and review permission changes before customization", + "运行 Mini App Host 与 Worker,查看状态并停止后台 Worker", + "Run Mini App host and worker calls, inspect status, and stop background workers", + "为正式应用和定制草稿分别读取与保存持久状态", + "Read and save persistent state separately for installed apps and customization drafts", + "在 Mini App 中调用模型补全、聊天和专属 Agent 会话", + "Use model completion, chat, and dedicated agent sessions inside Mini Apps", + "创建定制草稿、实时预览,并应用、同步或丢弃修改", + "Create customization drafts, preview them live, and apply, sync, or discard changes", + "查看版本历史并回滚到旧版本", + "Inspect version history and roll back to an earlier release", + "提交、撤回和审查市场发布,并可渲染幻灯片页面", + "Submit, withdraw, and review market releases, and render slide pages" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.miniapps/" + }, + { + "id": "feature.canvas", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Canvas 与交互产物", + "titleEn": "Canvas & interactive artifacts", + "summaryZh": "在会话旁展示和保存 Agent 生成的可视化、交互页面与结构化产物。", + "summaryEn": "Display and save visualizations, interactive pages, and structured artifacts generated beside a session.", + "keywordsZh": [ + "Canvas", + "画布", + "可视化", + "交互产物", + "Artifact" + ], + "keywordsEn": [ + "canvas", + "visualization", + "interactive artifact", + "artifact", + "preview" + ], + "highlightsZh": [ + "在会话中打开交互内容", + "保留画布状态", + "在面板中查看运行错误" + ], + "highlightsEn": [ + "Open interactive content from a session", + "Persist canvas state", + "Inspect runtime errors in the panel" + ], + "items": [ + { + "id": "artifact-open", + "titleZh": "从会话工具结果加载并打开持久化 Canvas 产物", + "titleEn": "Load and open persistent Canvas artifacts from session tool results" + }, + { + "id": "html-react", + "titleZh": "渲染 HTML 或 React 交互界面、图表和可视化", + "titleEn": "Render HTML or React interfaces, charts, and interactive visualizations" + }, + { + "id": "state", + "titleZh": "在重新打开或刷新 Canvas 时加载和保存交互状态", + "titleEn": "Load and save interactive state when a Canvas is reopened or refreshed" + }, + { + "id": "source-inspection", + "titleZh": "查看 Canvas 源码、编译版本和最后可用版本", + "titleEn": "Inspect Canvas source, compiled revisions, and the last known good revision" + }, + { + "id": "element-context", + "titleZh": "选择 Canvas 内的元素并把元素引用加入会话上下文", + "titleEn": "Select an element inside Canvas and add its reference to session context" + }, + { + "id": "runtime-errors", + "titleZh": "捕获运行错误、上报诊断并请求 Agent 自动修复", + "titleEn": "Capture runtime errors, report diagnostics, and ask the agent to repair them" + }, + { + "id": "export-html", + "titleZh": "把当前 Canvas 导出为可独立打开的 HTML 文件", + "titleEn": "Export the current Canvas as a standalone HTML file" + } + ], + "stepsZh": [ + "打开一个 AI 会话", + "让 Agent 创建可视化或交互工具", + "从工具结果打开 Canvas" + ], + "stepsEn": [ + "Open an AI session", + "Ask the agent for a visualization or interactive tool", + "Open the Canvas from the tool result" + ], + "agentExamplesZh": [ + "打开 AI 助手,我想做一个交互可视化", + "创建一个可交互的 Canvas" + ], + "agentExamplesEn": [ + "Open the AI assistant; I want an interactive visualization", + "Create an interactive Canvas" + ], + "destination": { + "kind": "scene", + "sceneId": "session" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.canvas", + "Canvas 与交互产物", + "Canvas & interactive artifacts", + "扩展与自动化", + "Extensions & automation", + "Canvas", + "画布", + "可视化", + "交互产物", + "Artifact", + "canvas", + "visualization", + "interactive artifact", + "artifact", + "preview", + "在会话中打开交互内容", + "保留画布状态", + "在面板中查看运行错误", + "Open interactive content from a session", + "Persist canvas state", + "Inspect runtime errors in the panel", + "从会话工具结果加载并打开持久化 Canvas 产物", + "Load and open persistent Canvas artifacts from session tool results", + "渲染 HTML 或 React 交互界面、图表和可视化", + "Render HTML or React interfaces, charts, and interactive visualizations", + "在重新打开或刷新 Canvas 时加载和保存交互状态", + "Load and save interactive state when a Canvas is reopened or refreshed", + "查看 Canvas 源码、编译版本和最后可用版本", + "Inspect Canvas source, compiled revisions, and the last known good revision", + "选择 Canvas 内的元素并把元素引用加入会话上下文", + "Select an element inside Canvas and add its reference to session context", + "捕获运行错误、上报诊断并请求 Agent 自动修复", + "Capture runtime errors, report diagnostics, and ask the agent to repair them", + "把当前 Canvas 导出为可独立打开的 HTML 文件", + "Export the current Canvas as a standalone HTML file" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.canvas/" + }, + { + "id": "feature.tasks-automation", + "kind": "feature", + "categoryId": "automation", + "titleZh": "任务板与定时任务", + "titleEn": "Task board & scheduled jobs", + "summaryZh": "集中查看待办事项,并让任务在指定时间或目标主机上持续运行。", + "summaryEn": "Track work in one task board and let scheduled jobs run at a chosen time or host.", + "keywordsZh": [ + "任务板", + "待办", + "Todo", + "定时任务", + "计划任务", + "Cron" + ], + "keywordsEn": [ + "task board", + "todo", + "scheduled job", + "automation", + "cron", + "recurring task" + ], + "highlightsZh": [ + "查看和整理待办", + "创建一次性或重复任务", + "为本地或远程工作区安排执行" + ], + "highlightsEn": [ + "Review and organize todos", + "Create one-time or recurring jobs", + "Schedule work for local or remote workspaces" + ], + "items": [ + { + "id": "board-views", + "titleZh": "按待处理、日历和已停用视图浏览任务", + "titleEn": "Browse tasks in Pending, Calendar, and Inactive views" + }, + { + "id": "create-edit", + "titleZh": "创建、编辑、启用、停用和删除定时任务", + "titleEn": "Create, edit, enable, disable, and delete scheduled jobs" + }, + { + "id": "schedule-types", + "titleZh": "设置一次性、每日、每周或自定义 Cron 时间表", + "titleEn": "Choose one-time, daily, weekly, or custom cron schedules" + }, + { + "id": "calendar-occurrences", + "titleZh": "在日历中预览任务的下一次与后续运行时间", + "titleEn": "Preview the next and future job occurrences on a calendar" + }, + { + "id": "agent-workspace", + "titleZh": "为任务选择 Agent、模型、工作模式和工作区", + "titleEn": "Choose the agent, model, work mode, and workspace for a job" + }, + { + "id": "local-remote-target", + "titleZh": "把任务安排在当前主机或已连接的远程目标上运行", + "titleEn": "Schedule jobs to run on the current host or a connected remote target" + }, + { + "id": "host-readiness", + "titleZh": "查看任务列表并等待桌面 Host 就绪后可靠执行", + "titleEn": "List jobs and wait for desktop-host readiness before reliable execution" + } + ], + "stepsZh": [ + "打开任务板", + "选择待办或定时任务", + "创建任务并确认运行目标与时间" + ], + "stepsEn": [ + "Open the Task Board", + "Choose todos or scheduled jobs", + "Create the job and confirm its target and timing" + ], + "agentExamplesZh": [ + "打开任务板", + "带我去看定时任务" + ], + "agentExamplesEn": [ + "Open the task board", + "Take me to scheduled jobs" + ], + "destination": { + "kind": "action", + "actionId": "surface.todos.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.tasks-automation", + "任务板与定时任务", + "Task board & scheduled jobs", + "扩展与自动化", + "Extensions & automation", + "任务板", + "待办", + "Todo", + "定时任务", + "计划任务", + "Cron", + "task board", + "todo", + "scheduled job", + "automation", + "cron", + "recurring task", + "查看和整理待办", + "创建一次性或重复任务", + "为本地或远程工作区安排执行", + "Review and organize todos", + "Create one-time or recurring jobs", + "Schedule work for local or remote workspaces", + "按待处理、日历和已停用视图浏览任务", + "Browse tasks in Pending, Calendar, and Inactive views", + "创建、编辑、启用、停用和删除定时任务", + "Create, edit, enable, disable, and delete scheduled jobs", + "设置一次性、每日、每周或自定义 Cron 时间表", + "Choose one-time, daily, weekly, or custom cron schedules", + "在日历中预览任务的下一次与后续运行时间", + "Preview the next and future job occurrences on a calendar", + "为任务选择 Agent、模型、工作模式和工作区", + "Choose the agent, model, work mode, and workspace for a job", + "把任务安排在当前主机或已连接的远程目标上运行", + "Schedule jobs to run on the current host or a connected remote target", + "查看任务列表并等待桌面 Host 就绪后可靠执行", + "List jobs and wait for desktop-host readiness before reliable execution" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.tasks-automation/" + }, + { + "id": "feature.insights", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Insights 工作洞察", + "titleEn": "Insights", + "summaryZh": "把会话和项目活动汇总成可读的洞察,帮助回顾工作方式、用量和进展。", + "summaryEn": "Turn session and project activity into readable insights about working patterns, usage, and progress.", + "keywordsZh": [ + "洞察", + "分析", + "统计", + "工作报告", + "用量" + ], + "keywordsEn": [ + "insights", + "analytics", + "statistics", + "work report", + "usage" + ], + "highlightsZh": [ + "生成工作洞察", + "查看最新报告", + "结合 Token 用量理解成本" + ], + "highlightsEn": [ + "Generate work insights", + "Read the latest report", + "Relate activity to token usage" + ], + "items": [ + { + "id": "availability", + "titleZh": "检查当前账户与会话是否已有可分析的洞察数据", + "titleEn": "Check whether the current account and sessions contain analyzable insight data" + }, + { + "id": "generate", + "titleZh": "按所选日期范围和模型生成工作洞察报告", + "titleEn": "Generate a work-insights report for a selected date range and model" + }, + { + "id": "cancel", + "titleZh": "取消正在运行的洞察生成任务", + "titleEn": "Cancel an in-progress insights generation job" + }, + { + "id": "latest-report", + "titleZh": "查看最新报告或加载指定的历史报告", + "titleEn": "Open the latest report or load a selected historical report" + }, + { + "id": "usage-statistics", + "titleZh": "把工作活动与模型、Token 和缓存用量统计关联起来", + "titleEn": "Relate work activity to model, token, and cache-usage statistics" + }, + { + "id": "patterns", + "titleZh": "回顾项目分布、工作时段、任务类型和协作习惯", + "titleEn": "Review project distribution, working hours, task types, and collaboration patterns" + } + ], + "stepsZh": [ + "打开 Insights", + "选择可用的数据范围", + "生成或查看最新报告" + ], + "stepsEn": [ + "Open Insights", + "Choose the available data scope", + "Generate or read the latest report" + ], + "agentExamplesZh": [ + "打开 Insights", + "带我查看工作洞察" + ], + "agentExamplesEn": [ + "Open Insights", + "Show me my work insights" + ], + "destination": { + "kind": "action", + "actionId": "surface.insights.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.insights", + "Insights 工作洞察", + "Insights", + "扩展与自动化", + "Extensions & automation", + "洞察", + "分析", + "统计", + "工作报告", + "用量", + "insights", + "analytics", + "statistics", + "work report", + "usage", + "生成工作洞察", + "查看最新报告", + "结合 Token 用量理解成本", + "Generate work insights", + "Read the latest report", + "Relate activity to token usage", + "检查当前账户与会话是否已有可分析的洞察数据", + "Check whether the current account and sessions contain analyzable insight data", + "按所选日期范围和模型生成工作洞察报告", + "Generate a work-insights report for a selected date range and model", + "取消正在运行的洞察生成任务", + "Cancel an in-progress insights generation job", + "查看最新报告或加载指定的历史报告", + "Open the latest report or load a selected historical report", + "把工作活动与模型、Token 和缓存用量统计关联起来", + "Relate work activity to model, token, and cache-usage statistics", + "回顾项目分布、工作时段、任务类型和协作习惯", + "Review project distribution, working hours, task types, and collaboration patterns" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.insights/" + }, + { + "id": "feature.ecosystem-compatibility", + "kind": "feature", + "categoryId": "automation", + "titleZh": "外部 AI 生态兼容", + "titleEn": "External AI ecosystem compatibility", + "summaryZh": "发现并迁移 OpenCode、Claude Code、Codex 等外部 AI 工具的配置、命令、Hooks 与 MCP 资源。", + "summaryEn": "Discover and migrate configuration, commands, hooks, and MCP resources from OpenCode, Claude Code, Codex, and other AI tools.", + "keywordsZh": [ + "生态兼容", + "外部 AI", + "迁移配置", + "OpenCode", + "Claude Code", + "Codex", + "导入" + ], + "keywordsEn": [ + "ecosystem compatibility", + "external AI", + "configuration migration", + "OpenCode", + "Claude Code", + "Codex", + "import" + ], + "highlightsZh": [ + "扫描外部 AI 应用", + "预览冲突与迁移计划", + "按项导入提示词、Hooks、Agent 与 MCP" + ], + "highlightsEn": [ + "Scan external AI applications", + "Preview conflicts and migration plans", + "Import prompts, hooks, agents, and MCP selectively" + ], + "items": [ + { + "id": "source-discovery", + "titleZh": "发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容", + "titleEn": "Discover OpenCode, Claude Code, Codex, and other external AI sources and content" + }, + { + "id": "source-policy", + "titleZh": "按来源启用或停用集成,并选择管理、预览或只读策略", + "titleEn": "Enable or disable each source and choose managed, preview, or read-only policy" + }, + { + "id": "prompts-commands", + "titleZh": "展开外部 Prompt/Command 内容并处理与原生命令的冲突", + "titleEn": "Expand external prompt/command content and resolve conflicts with native commands" + }, + { + "id": "subagents", + "titleZh": "导入或启用外部 Agent,处理同名冲突并绑定模型", + "titleEn": "Import or enable external agents, resolve naming conflicts, and bind models" + }, + { + "id": "mcp-import", + "titleZh": "预览 MCP 导入计划,逐个处理服务器冲突并应用", + "titleEn": "Preview MCP import plans, resolve server conflicts individually, and apply them" + }, + { + "id": "tool-targets", + "titleZh": "选择外部工具目标、解决冲突并控制是否启用", + "titleEn": "Choose external tool targets, resolve conflicts, and control activation" + }, + { + "id": "hooks", + "titleZh": "查看外部 Hooks 目录、规划导入、修改选择并应用", + "titleEn": "Inspect external hook catalogs, plan imports, edit selections, and apply" + }, + { + "id": "security-review", + "titleZh": "在迁移前查看冲突、安全影响和来源控制快照", + "titleEn": "Review conflicts, security impact, and source-control snapshots before migration" + }, + { + "id": "reveal-source", + "titleZh": "在文件管理器或远程环境中定位外部配置来源", + "titleEn": "Reveal external configuration sources in the file manager or remote environment" + } + ], + "stepsZh": [ + "打开“生态兼容”", + "选择来源并查看扫描结果", + "确认计划后导入需要的内容" + ], + "stepsEn": [ + "Open Ecosystem Compatibility", + "Choose a source and review the scan", + "Confirm the plan and import selected content" + ], + "agentExamplesZh": [ + "打开外部 AI 生态兼容", + "我想迁移 Claude Code 的配置" + ], + "agentExamplesEn": [ + "Open external AI ecosystem compatibility", + "I want to migrate my Claude Code configuration" + ], + "destination": { + "kind": "action", + "actionId": "surface.ecosystemCompatibility.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.ecosystem-compatibility", + "外部 AI 生态兼容", + "External AI ecosystem compatibility", + "扩展与自动化", + "Extensions & automation", + "生态兼容", + "外部 AI", + "迁移配置", + "OpenCode", + "Claude Code", + "Codex", + "导入", + "ecosystem compatibility", + "external AI", + "configuration migration", + "import", + "扫描外部 AI 应用", + "预览冲突与迁移计划", + "按项导入提示词、Hooks、Agent 与 MCP", + "Scan external AI applications", + "Preview conflicts and migration plans", + "Import prompts, hooks, agents, and MCP selectively", + "发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容", + "Discover OpenCode, Claude Code, Codex, and other external AI sources and content", + "按来源启用或停用集成,并选择管理、预览或只读策略", + "Enable or disable each source and choose managed, preview, or read-only policy", + "展开外部 Prompt/Command 内容并处理与原生命令的冲突", + "Expand external prompt/command content and resolve conflicts with native commands", + "导入或启用外部 Agent,处理同名冲突并绑定模型", + "Import or enable external agents, resolve naming conflicts, and bind models", + "预览 MCP 导入计划,逐个处理服务器冲突并应用", + "Preview MCP import plans, resolve server conflicts individually, and apply them", + "选择外部工具目标、解决冲突并控制是否启用", + "Choose external tool targets, resolve conflicts, and control activation", + "查看外部 Hooks 目录、规划导入、修改选择并应用", + "Inspect external hook catalogs, plan imports, edit selections, and apply", + "在迁移前查看冲突、安全影响和来源控制快照", + "Review conflicts, security impact, and source-control snapshots before migration", + "在文件管理器或远程环境中定位外部配置来源", + "Reveal external configuration sources in the file manager or remote environment" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.ecosystem-compatibility/" + }, + { + "id": "feature.remote-workspaces", + "kind": "feature", + "categoryId": "connect", + "titleZh": "远程工作区", + "titleEn": "Remote workspaces", + "summaryZh": "通过 SSH 或容器在远程主机上打开项目,让文件、搜索、终端和 Agent 都在目标环境执行。", + "summaryEn": "Open projects over SSH or in containers so files, search, terminal, and agents all execute in the target environment.", + "keywordsZh": [ + "远程工作区", + "SSH", + "远程项目", + "容器", + "跳板机", + "远程开发" + ], + "keywordsEn": [ + "remote workspace", + "SSH", + "remote project", + "container", + "jump host", + "remote development" + ], + "highlightsZh": [ + "保存 SSH 连接配置", + "上传下载与远程文件操作", + "在远程环境运行终端和 Agent" + ], + "highlightsEn": [ + "Save SSH connection profiles", + "Transfer and edit remote files", + "Run terminals and agents in the remote environment" + ], + "items": [ + { + "id": "ssh-profiles", + "titleZh": "保存、列出、测试和删除 SSH 连接配置", + "titleEn": "Save, list, test, and delete SSH connection profiles" + }, + { + "id": "ssh-auth", + "titleZh": "使用密码、私钥、证书、SSH Config Host 与跳板机连接", + "titleEn": "Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts" + }, + { + "id": "docker", + "titleZh": "发现远程 Docker 容器并把容器作为工作环境", + "titleEn": "Discover remote Docker containers and use a container as the work environment" + }, + { + "id": "remote-open", + "titleZh": "打开、关闭和移除远程工作区,并读取服务器信息", + "titleEn": "Open, close, and remove remote workspaces, and inspect server information" + }, + { + "id": "remote-files", + "titleZh": "浏览、读取、写入、创建、重命名和删除远程文件与目录", + "titleEn": "Browse, read, write, create, rename, and remove remote files and directories" + }, + { + "id": "transfer", + "titleZh": "上传本地文件、下载远程文件并取消进行中的传输", + "titleEn": "Upload local files, download remote files, and cancel active transfers" + }, + { + "id": "remote-execution", + "titleZh": "在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面", + "titleEn": "Execute commands on the target so terminals, search, and agents use the remote data plane" + }, + { + "id": "port-forwarding", + "titleZh": "发现远程监听端口并启动、查看或停止端口转发", + "titleEn": "Discover remote listening ports and start, inspect, or stop port forwarding" + }, + { + "id": "connection-lifecycle", + "titleZh": "查看连接状态并断开单个或全部 SSH 会话", + "titleEn": "Inspect connection status and disconnect one or all SSH sessions" + } + ], + "stepsZh": [ + "打开新建项目", + "选择远程连接方式", + "配置主机并测试连接后打开工作区" + ], + "stepsEn": [ + "Open New Project", + "Choose a remote connection type", + "Configure and test the host, then open the workspace" + ], + "agentExamplesZh": [ + "打开远程项目配置", + "我想连接一个 SSH 工作区" + ], + "agentExamplesEn": [ + "Open remote-project setup", + "I want to connect to an SSH workspace" + ], + "destination": { + "kind": "action", + "actionId": "project.new" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.remote-workspaces", + "远程工作区", + "Remote workspaces", + "连接与发布", + "Connect & publish", + "SSH", + "远程项目", + "容器", + "跳板机", + "远程开发", + "remote workspace", + "remote project", + "container", + "jump host", + "remote development", + "保存 SSH 连接配置", + "上传下载与远程文件操作", + "在远程环境运行终端和 Agent", + "Save SSH connection profiles", + "Transfer and edit remote files", + "Run terminals and agents in the remote environment", + "保存、列出、测试和删除 SSH 连接配置", + "Save, list, test, and delete SSH connection profiles", + "使用密码、私钥、证书、SSH Config Host 与跳板机连接", + "Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts", + "发现远程 Docker 容器并把容器作为工作环境", + "Discover remote Docker containers and use a container as the work environment", + "打开、关闭和移除远程工作区,并读取服务器信息", + "Open, close, and remove remote workspaces, and inspect server information", + "浏览、读取、写入、创建、重命名和删除远程文件与目录", + "Browse, read, write, create, rename, and remove remote files and directories", + "上传本地文件、下载远程文件并取消进行中的传输", + "Upload local files, download remote files, and cancel active transfers", + "在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面", + "Execute commands on the target so terminals, search, and agents use the remote data plane", + "发现远程监听端口并启动、查看或停止端口转发", + "Discover remote listening ports and start, inspect, or stop port forwarding", + "查看连接状态并断开单个或全部 SSH 会话", + "Inspect connection status and disconnect one or all SSH sessions" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.remote-workspaces/" + }, + { + "id": "feature.remote-connect", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Remote Connect 与多设备", + "titleEn": "Remote Connect & devices", + "summaryZh": "从手机、Bot 或另一台 BitFun 设备连接当前主机,远程查看会话、回答权限并继续工作。", + "summaryEn": "Connect to this host from mobile, a bot, or another BitFun device to inspect sessions, answer permissions, and continue work remotely.", + "keywordsZh": [ + "Remote Connect", + "远程控制", + "手机", + "飞书", + "Telegram", + "微信", + "多设备", + "Peer Device", + "账户同步" + ], + "keywordsEn": [ + "remote connect", + "remote control", + "mobile", + "Feishu", + "Telegram", + "WeChat", + "multi-device", + "peer device", + "account sync" + ], + "highlightsZh": [ + "通过局域网、Ngrok 或自建 Relay 连接", + "接入飞书、Telegram 或微信 Bot", + "登录账户、同步会话并进入 Peer Device Mode" + ], + "highlightsEn": [ + "Connect through LAN, Ngrok, or a self-hosted relay", + "Use Feishu, Telegram, or WeChat bots", + "Sign in, sync sessions, and enter Peer Device Mode" + ], + "items": [ + { + "id": "connection-methods", + "titleZh": "选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器", + "titleEn": "Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server" + }, + { + "id": "start-stop-status", + "titleZh": "启动、停止 Remote Connect 并查看实时连接状态和设备信息", + "titleEn": "Start or stop Remote Connect and inspect live status and device information" + }, + { + "id": "network", + "titleZh": "查看局域网 IP、网络信息与可分享的连接配置", + "titleEn": "Inspect LAN IP, network details, and shareable connection configuration" + }, + { + "id": "bots", + "titleZh": "配置飞书、Telegram、微信等 Bot 并单独停止 Bot", + "titleEn": "Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently" + }, + { + "id": "relay-wizard", + "titleZh": "通过向导预检、安装 Docker、部署、注册并验证自建 Relay", + "titleEn": "Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard" + }, + { + "id": "account", + "titleZh": "登录、退出并查看账户状态和凭据提示", + "titleEn": "Sign in, sign out, and inspect account status and credential hints" + }, + { + "id": "devices", + "titleZh": "列出、连接、查看在线状态和删除同账户设备", + "titleEn": "List, connect, inspect online status, and remove same-account devices" + }, + { + "id": "session-sync", + "titleZh": "同步、导出、导入、删除或发送会话到另一台设备", + "titleEn": "Sync, export, import, delete, or send sessions to another device" + }, + { + "id": "settings-sync", + "titleZh": "在设备间自动或手动同步 BitFun 设置", + "titleEn": "Synchronize BitFun settings across devices automatically or on demand" + }, + { + "id": "peer-device", + "titleZh": "进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面", + "titleEn": "Enter Peer Device Mode and use another BitFun device as the command and event data plane" + } + ], + "stepsZh": [ + "打开 Remote Connect", + "选择网络、Bot 或账户", + "按向导连接并确认安全提示" + ], + "stepsEn": [ + "Open Remote Connect", + "Choose Network, Bot, or Account", + "Follow the connection flow and review its security notice" + ], + "agentExamplesZh": [ + "打开 Remote Connect", + "我想配置手机远程控制", + "带我管理已连接设备" + ], + "agentExamplesEn": [ + "Open Remote Connect", + "I want to configure mobile remote control", + "Take me to connected-device management" + ], + "destination": { + "kind": "event", + "eventName": "bitfun:open-remote-connect" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.remote-connect", + "Remote Connect 与多设备", + "Remote Connect & devices", + "连接与发布", + "Connect & publish", + "Remote Connect", + "远程控制", + "手机", + "飞书", + "Telegram", + "微信", + "多设备", + "Peer Device", + "账户同步", + "remote connect", + "remote control", + "mobile", + "Feishu", + "WeChat", + "multi-device", + "peer device", + "account sync", + "通过局域网、Ngrok 或自建 Relay 连接", + "接入飞书、Telegram 或微信 Bot", + "登录账户、同步会话并进入 Peer Device Mode", + "Connect through LAN, Ngrok, or a self-hosted relay", + "Use Feishu, Telegram, or WeChat bots", + "Sign in, sync sessions, and enter Peer Device Mode", + "选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器", + "Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server", + "启动、停止 Remote Connect 并查看实时连接状态和设备信息", + "Start or stop Remote Connect and inspect live status and device information", + "查看局域网 IP、网络信息与可分享的连接配置", + "Inspect LAN IP, network details, and shareable connection configuration", + "配置飞书、Telegram、微信等 Bot 并单独停止 Bot", + "Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently", + "通过向导预检、安装 Docker、部署、注册并验证自建 Relay", + "Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard", + "登录、退出并查看账户状态和凭据提示", + "Sign in, sign out, and inspect account status and credential hints", + "列出、连接、查看在线状态和删除同账户设备", + "List, connect, inspect online status, and remove same-account devices", + "同步、导出、导入、删除或发送会话到另一台设备", + "Sync, export, import, delete, or send sessions to another device", + "在设备间自动或手动同步 BitFun 设置", + "Synchronize BitFun settings across devices automatically or on demand", + "进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面", + "Enter Peer Device Mode and use another BitFun device as the command and event data plane" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.remote-connect/" + }, + { + "id": "feature.detached-dispatch", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Detached Dispatch 远程派发", + "titleEn": "Detached Dispatch", + "summaryZh": "把可持续运行的任务派发到另一台 BitFun 主机;控制端可以断开,目标主机继续执行并保留记录。", + "summaryEn": "Dispatch durable work to another BitFun host; the controller may disconnect while the target continues and keeps the record.", + "keywordsZh": [ + "派发任务", + "Detached Dispatch", + "远程执行", + "目标主机", + "离线任务" + ], + "keywordsEn": [ + "detached dispatch", + "dispatch task", + "remote execution", + "target host", + "offline job" + ], + "highlightsZh": [ + "发现与探测目标主机", + "派发、继续或取消任务", + "断线后重新加载事件与执行记录" + ], + "highlightsEn": [ + "Discover and probe target hosts", + "Dispatch, continue, or cancel jobs", + "Reload events and execution history after reconnecting" + ], + "items": [ + { + "id": "targets", + "titleZh": "列出可派发目标并探测版本、连接和运行能力", + "titleEn": "List dispatch targets and probe their version, connectivity, and runtime capabilities" + }, + { + "id": "provision", + "titleZh": "为目标主机配置运行环境并安装或更新 BitFun CLI", + "titleEn": "Provision the target runtime and install or update the BitFun CLI" + }, + { + "id": "model-sync", + "titleZh": "在提交任务前同步目标所需的模型配置", + "titleEn": "Synchronize required model configuration before submitting a job" + }, + { + "id": "submit", + "titleZh": "把包含工作区、会话、模型和权限策略的持久任务提交到目标", + "titleEn": "Submit a durable job with workspace, session, model, and permission policy to the target" + }, + { + "id": "status-list", + "titleZh": "列出派发任务并查询运行状态、结果和错误", + "titleEn": "List dispatched jobs and query their status, result, and errors" + }, + { + "id": "transcript", + "titleZh": "保存、追加和重新加载可断线恢复的执行记录", + "titleEn": "Save, append, and reload reconnectable execution transcripts" + }, + { + "id": "permission-continuation", + "titleZh": "远程回答权限请求,并继续或取消目标端任务", + "titleEn": "Answer permission requests remotely and continue or cancel target-side work" + }, + { + "id": "result-sync", + "titleZh": "将目标端结果同步回控制端,而不把控制端当作远程文件系统代理", + "titleEn": "Synchronize target-side results back without treating the controller as a remote-filesystem proxy" + } + ], + "stepsZh": [ + "先在 Remote Connect 中登录并连接设备", + "从会话的派发入口选择目标", + "提交任务后在任务状态中跟踪" + ], + "stepsEn": [ + "Sign in and connect devices through Remote Connect", + "Choose a target from the session dispatch flow", + "Submit the work and follow its job status" + ], + "agentExamplesZh": [ + "打开设备管理,我想把任务派发到另一台机器", + "带我配置远程任务派发" + ], + "agentExamplesEn": [ + "Open device management so I can dispatch work to another machine", + "Take me to remote task dispatch setup" + ], + "destination": { + "kind": "event", + "eventName": "bitfun:open-remote-connect", + "detail": { + "group": "account" + } + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.detached-dispatch", + "Detached Dispatch 远程派发", + "Detached Dispatch", + "连接与发布", + "Connect & publish", + "派发任务", + "远程执行", + "目标主机", + "离线任务", + "detached dispatch", + "dispatch task", + "remote execution", + "target host", + "offline job", + "发现与探测目标主机", + "派发、继续或取消任务", + "断线后重新加载事件与执行记录", + "Discover and probe target hosts", + "Dispatch, continue, or cancel jobs", + "Reload events and execution history after reconnecting", + "列出可派发目标并探测版本、连接和运行能力", + "List dispatch targets and probe their version, connectivity, and runtime capabilities", + "为目标主机配置运行环境并安装或更新 BitFun CLI", + "Provision the target runtime and install or update the BitFun CLI", + "在提交任务前同步目标所需的模型配置", + "Synchronize required model configuration before submitting a job", + "把包含工作区、会话、模型和权限策略的持久任务提交到目标", + "Submit a durable job with workspace, session, model, and permission policy to the target", + "列出派发任务并查询运行状态、结果和错误", + "List dispatched jobs and query their status, result, and errors", + "保存、追加和重新加载可断线恢复的执行记录", + "Save, append, and reload reconnectable execution transcripts", + "远程回答权限请求,并继续或取消目标端任务", + "Answer permission requests remotely and continue or cancel target-side work", + "将目标端结果同步回控制端,而不把控制端当作远程文件系统代理", + "Synchronize target-side results back without treating the controller as a remote-filesystem proxy" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.detached-dispatch/" + }, + { + "id": "feature.pages", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Pages 发布", + "titleEn": "Pages publishing", + "summaryZh": "保存页面版本并发布到公开或私有地址,管理标题、可见性、历史版本和分享链接。", + "summaryEn": "Save page versions and publish them to public or private URLs while managing titles, visibility, history, and share links.", + "keywordsZh": [ + "Pages", + "发布网页", + "页面托管", + "分享链接", + "版本", + "部署" + ], + "keywordsEn": [ + "pages", + "publish website", + "page hosting", + "share link", + "version", + "deploy" + ], + "highlightsZh": [ + "保存页面版本", + "发布、取消发布或删除页面", + "更新标题和访问可见性" + ], + "highlightsEn": [ + "Save page versions", + "Publish, unpublish, or delete pages", + "Update titles and access visibility" + ], + "items": [ + { + "id": "pages-list", + "titleZh": "查看账户下的 Pages 与每个页面的当前发布状态", + "titleEn": "List account Pages and inspect each page's current publishing state" + }, + { + "id": "immutable-versions", + "titleZh": "保存不可变页面版本并浏览版本历史", + "titleEn": "Save immutable page versions and browse version history" + }, + { + "id": "publish", + "titleZh": "发布或重新部署选中的页面版本", + "titleEn": "Publish or redeploy a selected page version" + }, + { + "id": "visibility", + "titleZh": "更新标题、公开/私有可见性和访问设置", + "titleEn": "Update titles, public/private visibility, and access settings" + }, + { + "id": "share-open", + "titleZh": "创建可打开和分享的页面链接", + "titleEn": "Create an openable, shareable link for a page" + }, + { + "id": "unpublish", + "titleZh": "取消发布页面,同时保留可再次发布的版本", + "titleEn": "Unpublish a page while retaining versions for later publication" + }, + { + "id": "delete", + "titleZh": "删除单个版本或整个 Page", + "titleEn": "Delete an individual version or an entire Page" + } + ], + "stepsZh": [ + "登录 BitFun 账户", + "打开 Pages", + "选择页面并确认发布与可见性" + ], + "stepsEn": [ + "Sign in to a BitFun account", + "Open Pages", + "Choose a page and confirm publishing and visibility" + ], + "agentExamplesZh": [ + "打开 Pages", + "带我管理已发布的页面" + ], + "agentExamplesEn": [ + "Open Pages", + "Take me to my published pages" + ], + "destination": { + "kind": "scene", + "sceneId": "pages" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.pages", + "Pages 发布", + "Pages publishing", + "连接与发布", + "Connect & publish", + "Pages", + "发布网页", + "页面托管", + "分享链接", + "版本", + "部署", + "pages", + "publish website", + "page hosting", + "share link", + "version", + "deploy", + "保存页面版本", + "发布、取消发布或删除页面", + "更新标题和访问可见性", + "Save page versions", + "Publish, unpublish, or delete pages", + "Update titles and access visibility", + "查看账户下的 Pages 与每个页面的当前发布状态", + "List account Pages and inspect each page's current publishing state", + "保存不可变页面版本并浏览版本历史", + "Save immutable page versions and browse version history", + "发布或重新部署选中的页面版本", + "Publish or redeploy a selected page version", + "更新标题、公开/私有可见性和访问设置", + "Update titles, public/private visibility, and access settings", + "创建可打开和分享的页面链接", + "Create an openable, shareable link for a page", + "取消发布页面,同时保留可再次发布的版本", + "Unpublish a page while retaining versions for later publication", + "删除单个版本或整个 Page", + "Delete an individual version or an entire Page" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.pages/" + }, + { + "id": "feature.voice-input", + "kind": "feature", + "categoryId": "application", + "titleZh": "语音输入", + "titleEn": "Voice input", + "summaryZh": "在聊天输入框中录音并转成文字,可选择本地模型、语言、麦克风与最长录音时间。", + "summaryEn": "Record speech in the chat composer and transcribe it to text, with control over local models, language, microphone, and duration.", + "keywordsZh": [ + "语音输入", + "录音", + "转写", + "麦克风", + "语音模型", + "听写" + ], + "keywordsEn": [ + "voice input", + "recording", + "transcription", + "microphone", + "speech model", + "dictation" + ], + "highlightsZh": [ + "下载和校验本地语音模型", + "选择识别语言与麦克风", + "在发送前编辑转写文本" + ], + "highlightsEn": [ + "Download and verify local speech models", + "Choose a recognition language and microphone", + "Edit transcribed text before sending" + ], + "items": [ + { + "id": "composer-recording", + "titleZh": "从聊天输入框开始、结束或取消一次录音", + "titleEn": "Start, finish, or cancel a recording from the chat composer" + }, + { + "id": "stream-audio", + "titleZh": "录音过程中分块传输音频并显示识别进度", + "titleEn": "Stream audio chunks during recording and show recognition progress" + }, + { + "id": "local-models", + "titleZh": "查看本地语音模型及安装、下载、验证、修复和删除状态", + "titleEn": "Browse local speech models and their install, download, verify, repair, and delete states" + }, + { + "id": "cancel-download", + "titleZh": "取消正在进行的语音模型下载", + "titleEn": "Cancel an in-progress speech-model download" + }, + { + "id": "language-microphone", + "titleZh": "选择自动检测或指定识别语言,并选择系统麦克风", + "titleEn": "Use automatic language detection or choose a language and system microphone" + }, + { + "id": "diagnostic-test", + "titleZh": "在设置页进行麦克风与语音识别测试并查看耗时和错误", + "titleEn": "Test the microphone and speech recognition in Settings, including timing and errors" + }, + { + "id": "edit-transcript", + "titleZh": "把转写结果放回输入框,在发送前继续编辑", + "titleEn": "Return the transcript to the composer for editing before sending" + } + ], + "stepsZh": [ + "打开输入设置的“语音”页", + "启用语音并准备模型", + "在聊天输入框点击麦克风开始录音" + ], + "stepsEn": [ + "Open the Voice input settings view", + "Enable voice and prepare a model", + "Use the microphone button in the chat composer" + ], + "agentExamplesZh": [ + "打开语音输入设置", + "帮我配置听写功能" + ], + "agentExamplesEn": [ + "Open voice-input settings", + "Help me configure dictation" + ], + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.voice-input", + "语音输入", + "Voice input", + "应用设置", + "Application settings", + "录音", + "转写", + "麦克风", + "语音模型", + "听写", + "voice input", + "recording", + "transcription", + "microphone", + "speech model", + "dictation", + "下载和校验本地语音模型", + "选择识别语言与麦克风", + "在发送前编辑转写文本", + "Download and verify local speech models", + "Choose a recognition language and microphone", + "Edit transcribed text before sending", + "从聊天输入框开始、结束或取消一次录音", + "Start, finish, or cancel a recording from the chat composer", + "录音过程中分块传输音频并显示识别进度", + "Stream audio chunks during recording and show recognition progress", + "查看本地语音模型及安装、下载、验证、修复和删除状态", + "Browse local speech models and their install, download, verify, repair, and delete states", + "取消正在进行的语音模型下载", + "Cancel an in-progress speech-model download", + "选择自动检测或指定识别语言,并选择系统麦克风", + "Use automatic language detection or choose a language and system microphone", + "在设置页进行麦克风与语音识别测试并查看耗时和错误", + "Test the microphone and speech recognition in Settings, including timing and errors", + "把转写结果放回输入框,在发送前继续编辑", + "Return the transcript to the composer for editing before sending" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.voice-input/" + }, + { + "id": "feature.desktop-pet", + "kind": "feature", + "categoryId": "application", + "titleZh": "Agent 桌面伙伴", + "titleEn": "Agent desktop companion", + "summaryZh": "在输入框或桌面上显示 Agent 伙伴,并选择、导入或管理 Petdex 角色包。", + "summaryEn": "Show an agent companion in the composer or on the desktop, and choose, import, or manage Petdex character packs.", + "keywordsZh": [ + "桌面宠物", + "Agent 伙伴", + "Petdex", + "像素宠物", + "角色包" + ], + "keywordsEn": [ + "desktop pet", + "agent companion", + "Petdex", + "pixel pet", + "character pack" + ], + "highlightsZh": [ + "在桌面或输入框显示伙伴", + "选择预设角色", + "导入和删除 Petdex 包" + ], + "highlightsEn": [ + "Show the companion on desktop or in the composer", + "Choose a preset character", + "Import and remove Petdex packs" + ], + "items": [ + { + "id": "enable", + "titleZh": "整体启用或停用 Agent 桌面伙伴", + "titleEn": "Enable or disable the agent desktop companion globally" + }, + { + "id": "display-modes", + "titleZh": "选择在聊天输入框、独立桌面窗口或两处显示", + "titleEn": "Show the companion in the chat composer, a desktop window, or both" + }, + { + "id": "presets", + "titleZh": "查看并切换内置 Petdex 角色预设", + "titleEn": "Browse and switch among built-in Petdex character presets" + }, + { + "id": "petdex-import", + "titleZh": "从本地 Petdex 包导入新的角色与动画", + "titleEn": "Import new characters and animations from a local Petdex package" + }, + { + "id": "petdex-delete", + "titleZh": "删除已导入的 Petdex 包并回退到可用角色", + "titleEn": "Delete an imported Petdex package and fall back to an available character" + }, + { + "id": "desktop-window", + "titleZh": "显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口", + "titleEn": "Show, hide, and resize the desktop companion window, and return to the main window" + } + ], + "stepsZh": [ + "打开桌面伙伴设置", + "启用伙伴并选择显示位置", + "选择预设或导入 Petdex 包" + ], + "stepsEn": [ + "Open Companion settings", + "Enable it and choose where it appears", + "Choose a preset or import a Petdex pack" + ], + "agentExamplesZh": [ + "打开桌面宠物设置", + "带我配置 Agent 伙伴" + ], + "agentExamplesEn": [ + "Open desktop-pet settings", + "Take me to agent-companion setup" + ], + "destination": { + "kind": "settings", + "pageId": "application.pet" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.desktop-pet", + "Agent 桌面伙伴", + "Agent desktop companion", + "应用设置", + "Application settings", + "桌面宠物", + "Agent 伙伴", + "Petdex", + "像素宠物", + "角色包", + "desktop pet", + "agent companion", + "pixel pet", + "character pack", + "在桌面或输入框显示伙伴", + "选择预设角色", + "导入和删除 Petdex 包", + "Show the companion on desktop or in the composer", + "Choose a preset character", + "Import and remove Petdex packs", + "整体启用或停用 Agent 桌面伙伴", + "Enable or disable the agent desktop companion globally", + "选择在聊天输入框、独立桌面窗口或两处显示", + "Show the companion in the chat composer, a desktop window, or both", + "查看并切换内置 Petdex 角色预设", + "Browse and switch among built-in Petdex character presets", + "从本地 Petdex 包导入新的角色与动画", + "Import new characters and animations from a local Petdex package", + "删除已导入的 Petdex 包并回退到可用角色", + "Delete an imported Petdex package and fall back to an available character", + "显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口", + "Show, hide, and resize the desktop companion window, and return to the main window" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.desktop-pet/" + }, + { + "id": "setting.application.general", + "kind": "setting", + "categoryId": "application", + "titleZh": "常规设置", + "titleEn": "General settings", + "summaryZh": "管理启动、更新、关闭行为、通知与睡眠保持等应用级偏好。", + "summaryEn": "Manage app-level preferences for startup, updates, close behavior, notifications, and sleep prevention.", + "keywordsZh": [ + "常规设置", + "开机启动", + "自动更新", + "通知", + "关闭按钮", + "阻止睡眠" + ], + "keywordsEn": [ + "general settings", + "launch at login", + "auto update", + "notifications", + "close button", + "prevent sleep" + ], + "highlightsZh": [ + "开机启动与自动更新", + "窗口关闭和托盘行为", + "任务完成、权限请求与启动提示通知" + ], + "highlightsEn": [ + "Launch-at-login and automatic updates", + "Window close and tray behavior", + "Completion, permission, and startup-tip notifications" + ], + "items": [ + { + "id": "automatic-updates", + "titleZh": "启用或停用自动检查更新", + "titleEn": "Enable or disable automatic update checks" + }, + { + "id": "manual-update", + "titleZh": "手动检查、下载并安装可用更新,然后按需重启", + "titleEn": "Check for, download, and install an available update manually, then restart when needed" + }, + { + "id": "launch-at-login", + "titleZh": "控制 BitFun 是否在登录系统后自动启动", + "titleEn": "Choose whether BitFun launches automatically after system sign-in" + }, + { + "id": "prevent-sleep", + "titleZh": "在长任务运行时阻止电脑自动睡眠", + "titleEn": "Prevent the computer from sleeping while long-running work is active" + }, + { + "id": "close-behavior", + "titleZh": "选择关闭主窗口时退出、最小化到托盘或每次询问", + "titleEn": "Choose whether closing the main window quits, minimizes to tray, or asks each time" + }, + { + "id": "notifications", + "titleZh": "分别控制任务完成、权限请求和启动提示通知", + "titleEn": "Control completion, permission-request, and startup-tip notifications independently" + }, + { + "id": "announcements", + "titleZh": "查看、标记已读、忽略或永久隐藏产品公告与提示", + "titleEn": "Review, mark seen, dismiss, or permanently hide product announcements and tips" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 常规”", + "修改开关;变更会自动保存" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > General", + "Change a control; updates are saved automatically" + ], + "agentExamplesZh": [ + "关闭自动更新", + "以后关闭窗口时最小化到托盘", + "打开常规设置" + ], + "agentExamplesEn": [ + "Turn off automatic updates", + "Minimize to tray when I close the window", + "Open General settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.general" + }, + "operations": [], + "options": [ + { + "id": "auto-update", + "titleZh": "自动检查更新", + "titleEn": "Automatic updates", + "descriptionZh": "启动后自动检查可用更新。", + "descriptionEn": "Check for available updates automatically after startup.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "close-button-behavior", + "titleZh": "关闭按钮行为", + "titleEn": "Close button behavior", + "descriptionZh": "选择退出应用或最小化到托盘。", + "descriptionEn": "Choose whether closing quits the app or minimizes it to the tray.", + "valueSchema": { + "type": "string", + "enum": [ + "ask", + "minimize_to_tray", + "quit" + ] + } + }, + { + "id": "completion-notification", + "titleZh": "任务完成通知", + "titleEn": "Completion notifications", + "descriptionZh": "会话任务完成时发送系统通知。", + "descriptionEn": "Send an OS notification when session work completes.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "permission-notification", + "titleZh": "权限请求通知", + "titleEn": "Permission request notifications", + "descriptionZh": "Agent 等待权限确认时发送系统通知。", + "descriptionEn": "Send an OS notification when an agent waits for permission.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "startup-tips", + "titleZh": "启动提示", + "titleEn": "Startup tips", + "descriptionZh": "启动后显示功能提示。", + "descriptionEn": "Show product tips after startup.", + "valueSchema": { + "type": "boolean" + } + } + ], + "searchTerms": [ + "setting.application.general", + "常规设置", + "General settings", + "应用设置", + "Application settings", + "开机启动", + "自动更新", + "通知", + "关闭按钮", + "阻止睡眠", + "general settings", + "launch at login", + "auto update", + "notifications", + "close button", + "prevent sleep", + "开机启动与自动更新", + "窗口关闭和托盘行为", + "任务完成、权限请求与启动提示通知", + "Launch-at-login and automatic updates", + "Window close and tray behavior", + "Completion, permission, and startup-tip notifications", + "启用或停用自动检查更新", + "Enable or disable automatic update checks", + "手动检查、下载并安装可用更新,然后按需重启", + "Check for, download, and install an available update manually, then restart when needed", + "控制 BitFun 是否在登录系统后自动启动", + "Choose whether BitFun launches automatically after system sign-in", + "在长任务运行时阻止电脑自动睡眠", + "Prevent the computer from sleeping while long-running work is active", + "选择关闭主窗口时退出、最小化到托盘或每次询问", + "Choose whether closing the main window quits, minimizes to tray, or asks each time", + "分别控制任务完成、权限请求和启动提示通知", + "Control completion, permission-request, and startup-tip notifications independently", + "查看、标记已读、忽略或永久隐藏产品公告与提示", + "Review, mark seen, dismiss, or permanently hide product announcements and tips" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.general/" + }, + { + "id": "setting.application.appearance", + "kind": "setting", + "categoryId": "application", + "titleZh": "外观与语言", + "titleEn": "Appearance & language", + "summaryZh": "切换主题与语言,调整字体和动效,并安装或导入外观包。", + "summaryEn": "Switch themes and languages, tune typography and motion, and install or import appearance packs.", + "keywordsZh": [ + "外观", + "主题", + "深色模式", + "浅色模式", + "语言", + "字体", + "动效", + "皮肤" + ], + "keywordsEn": [ + "appearance", + "theme", + "dark mode", + "light mode", + "language", + "font", + "motion", + "skin" + ], + "highlightsZh": [ + "系统、深色与浅色主题", + "界面语言与字号", + "鼠标光效、动效和外观包" + ], + "highlightsEn": [ + "System, dark, and light themes", + "UI language and font size", + "Mouse glow, motion, and appearance packs" + ], + "items": [ + { + "id": "built-in-appearance", + "titleZh": "选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观", + "titleEn": "Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances" + }, + { + "id": "language", + "titleZh": "切换简体中文、繁体中文、英文等受支持界面语言", + "titleEn": "Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages" + }, + { + "id": "ui-font-size", + "titleZh": "分别调整整个界面与聊天区字号,并支持自定义像素值", + "titleEn": "Adjust global UI and chat font sizes independently, including custom pixel values" + }, + { + "id": "visual-effects", + "titleZh": "控制鼠标光效,并让动态背景尊重系统的减少动效偏好", + "titleEn": "Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference" + }, + { + "id": "local-packages", + "titleZh": "导入、预览、应用、导出和删除本地外观包", + "titleEn": "Import, preview, apply, export, and delete local appearance packages" + }, + { + "id": "appearance-market", + "titleZh": "浏览、搜索、筛选并安装或更新 Skin 市场外观", + "titleEn": "Browse, search, filter, install, and update appearances from the Skin market" + }, + { + "id": "market-submissions", + "titleZh": "提交、查看和撤回自己的外观市场投稿", + "titleEn": "Submit, review, and withdraw your appearance-market submissions" + }, + { + "id": "market-review", + "titleZh": "在具备权限时查看并批准或拒绝外观投稿", + "titleEn": "When authorized, inspect and approve or reject appearance submissions" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 外观”", + "选择主题、语言或外观效果" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Appearance", + "Choose a theme, language, or visual effect" + ], + "agentExamplesZh": [ + "切换成深色主题", + "把界面语言改成英文", + "打开外观设置" + ], + "agentExamplesEn": [ + "Switch to the dark theme", + "Change the interface language to English", + "Open Appearance settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.appearance" + }, + "operations": [], + "options": [ + { + "id": "theme", + "titleZh": "主题", + "titleEn": "Theme", + "descriptionZh": "使用系统、BitFun 深色或 BitFun 浅色外观。", + "descriptionEn": "Use the system, BitFun dark, or BitFun light appearance.", + "valueSchema": { + "type": "string", + "enum": [ + "system", + "bitfun-dark", + "bitfun-light" + ] + } + }, + { + "id": "language", + "titleZh": "界面语言", + "titleEn": "Interface language", + "descriptionZh": "设置 BitFun 的界面语言。", + "descriptionEn": "Set the BitFun interface language.", + "valueSchema": { + "type": "string", + "enum": [ + "en-US", + "zh-CN", + "zh-TW" + ] + } + } + ], + "searchTerms": [ + "setting.application.appearance", + "外观与语言", + "Appearance & language", + "应用设置", + "Application settings", + "外观", + "主题", + "深色模式", + "浅色模式", + "语言", + "字体", + "动效", + "皮肤", + "appearance", + "theme", + "dark mode", + "light mode", + "language", + "font", + "motion", + "skin", + "系统、深色与浅色主题", + "界面语言与字号", + "鼠标光效、动效和外观包", + "System, dark, and light themes", + "UI language and font size", + "Mouse glow, motion, and appearance packs", + "选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观", + "Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances", + "切换简体中文、繁体中文、英文等受支持界面语言", + "Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages", + "分别调整整个界面与聊天区字号,并支持自定义像素值", + "Adjust global UI and chat font sizes independently, including custom pixel values", + "控制鼠标光效,并让动态背景尊重系统的减少动效偏好", + "Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference", + "导入、预览、应用、导出和删除本地外观包", + "Import, preview, apply, export, and delete local appearance packages", + "浏览、搜索、筛选并安装或更新 Skin 市场外观", + "Browse, search, filter, install, and update appearances from the Skin market", + "提交、查看和撤回自己的外观市场投稿", + "Submit, review, and withdraw your appearance-market submissions", + "在具备权限时查看并批准或拒绝外观投稿", + "When authorized, inspect and approve or reject appearance submissions" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.appearance/" + }, + { + "id": "setting.application.pet", + "kind": "setting", + "categoryId": "application", + "titleZh": "桌面伙伴设置", + "titleEn": "Companion settings", + "summaryZh": "启用 Agent 伙伴、选择显示位置,并管理当前角色。", + "summaryEn": "Enable the agent companion, choose where it appears, and manage the active character.", + "keywordsZh": [ + "桌面伙伴设置", + "桌面宠物", + "显示位置", + "Petdex" + ], + "keywordsEn": [ + "companion settings", + "desktop pet", + "display location", + "Petdex" + ], + "highlightsZh": [ + "启用或停用伙伴", + "桌面与输入框显示模式", + "角色选择与 Petdex 导入" + ], + "highlightsEn": [ + "Enable or disable the companion", + "Desktop and composer display modes", + "Character selection and Petdex import" + ], + "items": [ + { + "id": "enabled", + "titleZh": "整体启用或停用 Agent 伙伴", + "titleEn": "Enable or disable the agent companion" + }, + { + "id": "composer-display", + "titleZh": "控制伙伴是否显示在聊天输入框旁", + "titleEn": "Choose whether the companion appears beside the chat composer" + }, + { + "id": "desktop-display", + "titleZh": "控制伙伴是否显示为独立桌面窗口", + "titleEn": "Choose whether the companion appears as a standalone desktop window" + }, + { + "id": "preset-selection", + "titleZh": "从内置与已导入角色中选择当前伙伴", + "titleEn": "Choose the active companion from built-in and imported characters" + }, + { + "id": "import", + "titleZh": "导入本地 Petdex 角色包", + "titleEn": "Import a local Petdex character package" + }, + { + "id": "delete-refresh", + "titleZh": "刷新角色列表并删除不再需要的导入包", + "titleEn": "Refresh the character list and delete imported packages you no longer need" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 桌面伙伴”", + "选择开关、位置和角色" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Companion", + "Choose its state, location, and character" + ], + "agentExamplesZh": [ + "关闭桌面伙伴", + "把 Agent 伙伴放到输入框里" + ], + "agentExamplesEn": [ + "Turn off the desktop companion", + "Put the agent companion in the composer" + ], + "destination": { + "kind": "settings", + "pageId": "application.pet" + }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用桌面伙伴", + "titleEn": "Enable companion", + "descriptionZh": "显示或隐藏 Agent 伙伴。", + "descriptionEn": "Show or hide the agent companion.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "display-mode", + "titleZh": "显示位置", + "titleEn": "Display location", + "descriptionZh": "在桌面或聊天输入框中显示。", + "descriptionEn": "Show on the desktop or in the chat composer.", + "valueSchema": { + "type": "string", + "enum": [ + "desktop", + "input" + ] + } + } + ], + "searchTerms": [ + "setting.application.pet", + "桌面伙伴设置", + "Companion settings", + "应用设置", + "Application settings", + "桌面宠物", + "显示位置", + "Petdex", + "companion settings", + "desktop pet", + "display location", + "启用或停用伙伴", + "桌面与输入框显示模式", + "角色选择与 Petdex 导入", + "Enable or disable the companion", + "Desktop and composer display modes", + "Character selection and Petdex import", + "整体启用或停用 Agent 伙伴", + "Enable or disable the agent companion", + "控制伙伴是否显示在聊天输入框旁", + "Choose whether the companion appears beside the chat composer", + "控制伙伴是否显示为独立桌面窗口", + "Choose whether the companion appears as a standalone desktop window", + "从内置与已导入角色中选择当前伙伴", + "Choose the active companion from built-in and imported characters", + "导入本地 Petdex 角色包", + "Import a local Petdex character package", + "刷新角色列表并删除不再需要的导入包", + "Refresh the character list and delete imported packages you no longer need" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.pet/" + }, + { + "id": "setting.application.input", + "kind": "setting", + "categoryId": "application", + "titleZh": "输入与快捷键", + "titleEn": "Input & shortcuts", + "summaryZh": "配置语音输入、麦克风、识别语言以及键盘快捷键。", + "summaryEn": "Configure voice input, microphone, recognition language, and keyboard shortcuts.", + "keywordsZh": [ + "输入设置", + "语音", + "麦克风", + "快捷键", + "热键", + "键位" + ], + "keywordsEn": [ + "input settings", + "voice", + "microphone", + "shortcut", + "hotkey", + "keybinding" + ], + "highlightsZh": [ + "语音输入与本地模型", + "识别语言和最长录音时间", + "应用与编辑器快捷键" + ], + "highlightsEn": [ + "Voice input and local models", + "Recognition language and maximum recording time", + "App and editor shortcuts" + ], + "items": [ + { + "id": "voice-enabled", + "titleZh": "在聊天输入框启用或停用语音输入", + "titleEn": "Enable or disable voice input in the chat composer", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "language", + "titleZh": "选择自动检测或中文、粤语、英文、日文等识别语言", + "titleEn": "Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "microphone-test", + "titleZh": "选择麦克风并执行语音识别测试", + "titleEn": "Choose a microphone and run a speech-recognition test", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "local-models", + "titleZh": "下载、选择、验证、修复或删除本地语音模型", + "titleEn": "Download, select, verify, repair, or delete local speech models", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "recording-limit", + "titleZh": "设置单次语音输入的最长录音时间", + "titleEn": "Set the maximum duration of one voice-input recording", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "shortcut-browser", + "titleZh": "搜索和查看全部应用、场景、编辑器与终端快捷键", + "titleEn": "Search and browse all app, scene, editor, and terminal shortcuts", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "shortcuts" + } + }, + { + "id": "shortcut-remap", + "titleZh": "录制新快捷键、检测冲突、恢复单项或重置全部自定义键位", + "titleEn": "Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "shortcuts" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 输入”", + "切换“语音”或“快捷键”视图" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Input", + "Switch between Voice and Shortcuts" + ], + "agentExamplesZh": [ + "打开快捷键设置", + "把语音输入的默认语言设为中文" + ], + "agentExamplesEn": [ + "Open keyboard-shortcut settings", + "Set the voice-input language to Chinese" + ], + "destination": { + "kind": "settings", + "pageId": "application.input" + }, + "operations": [], + "options": [ + { + "id": "voice-enabled", + "titleZh": "启用语音输入", + "titleEn": "Enable voice input", + "descriptionZh": "在聊天输入框显示并启用录音入口。", + "descriptionEn": "Show and enable recording in the chat composer.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "voice-language", + "titleZh": "默认识别语言", + "titleEn": "Default recognition language", + "descriptionZh": "选择自动检测、中文、英文、日文或粤语。", + "descriptionEn": "Choose automatic detection, Chinese, English, Japanese, or Cantonese.", + "valueSchema": { + "type": "string", + "enum": [ + "auto", + "zh", + "en", + "ja", + "yue" + ] + } + }, + { + "id": "max-recording-seconds", + "titleZh": "最长录音时间", + "titleEn": "Maximum recording duration", + "descriptionZh": "单次语音输入允许的最长秒数。", + "descriptionEn": "Maximum seconds allowed for one voice input.", + "valueSchema": { + "type": "integer", + "minimum": 10, + "maximum": 600 + } + } + ], + "searchTerms": [ + "setting.application.input", + "输入与快捷键", + "Input & shortcuts", + "应用设置", + "Application settings", + "输入设置", + "语音", + "麦克风", + "快捷键", + "热键", + "键位", + "input settings", + "voice", + "microphone", + "shortcut", + "hotkey", + "keybinding", + "语音输入与本地模型", + "识别语言和最长录音时间", + "应用与编辑器快捷键", + "Voice input and local models", + "Recognition language and maximum recording time", + "App and editor shortcuts", + "在聊天输入框启用或停用语音输入", + "Enable or disable voice input in the chat composer", + "选择自动检测或中文、粤语、英文、日文等识别语言", + "Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages", + "选择麦克风并执行语音识别测试", + "Choose a microphone and run a speech-recognition test", + "下载、选择、验证、修复或删除本地语音模型", + "Download, select, verify, repair, or delete local speech models", + "设置单次语音输入的最长录音时间", + "Set the maximum duration of one voice-input recording", + "搜索和查看全部应用、场景、编辑器与终端快捷键", + "Search and browse all app, scene, editor, and terminal shortcuts", + "录制新快捷键、检测冲突、恢复单项或重置全部自定义键位", + "Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.input/" + }, + { + "id": "setting.application.development", + "kind": "setting", + "categoryId": "application", + "titleZh": "终端与编辑器设置", + "titleEn": "Terminal & editor settings", + "summaryZh": "选择默认 Shell,并调整代码编辑器的字体、缩进、换行、格式化与 Minimap。", + "summaryEn": "Choose the default shell and tune editor font, indentation, wrapping, formatting, and minimap behavior.", + "keywordsZh": [ + "开发设置", + "默认 Shell", + "编辑器", + "字体大小", + "缩进", + "自动换行", + "Minimap" + ], + "keywordsEn": [ + "development settings", + "default shell", + "editor", + "font size", + "indentation", + "word wrap", + "minimap" + ], + "highlightsZh": [ + "默认终端 Shell", + "编辑器字号与缩进", + "自动换行、格式化和 Minimap" + ], + "highlightsEn": [ + "Default terminal shell", + "Editor font size and indentation", + "Word wrapping, formatting, and minimap" + ], + "items": [ + { + "id": "default-shell", + "titleZh": "自动检测并选择默认终端 Shell", + "titleEn": "Automatically detect and choose the default terminal shell", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "terminal" + } + }, + { + "id": "terminal-position", + "titleZh": "把终端面板放在右侧或底部", + "titleEn": "Place the terminal panel on the right or at the bottom", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "terminal" + } + }, + { + "id": "editor-appearance", + "titleZh": "设置编辑器字体、字重、字号、行高与光标样式", + "titleEn": "Configure editor font, weight, size, line height, and cursor style", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "indent-wrap", + "titleZh": "设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动", + "titleEn": "Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "editor-display", + "titleZh": "控制 Minimap、空白字符、当前行高亮和滚动边界", + "titleEn": "Control the minimap, whitespace rendering, current-line highlight, and scroll bounds", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "editor-advanced", + "titleZh": "控制语义高亮、括号配色、保存/粘贴时格式化和空白清理", + "titleEn": "Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 开发”", + "切换“终端”或“编辑器”视图" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Development", + "Switch between Terminal and Editor" + ], + "agentExamplesZh": [ + "把编辑器字号改成 15", + "打开终端设置" + ], + "agentExamplesEn": [ + "Set the editor font size to 15", + "Open terminal settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.development" + }, + "operations": [], + "options": [ + { + "id": "editor-font-size", + "titleZh": "编辑器字号", + "titleEn": "Editor font size", + "descriptionZh": "设置代码编辑器的字体大小。", + "descriptionEn": "Set the code editor font size.", + "valueSchema": { + "type": "integer", + "minimum": 10, + "maximum": 32 + } + } + ], + "searchTerms": [ + "setting.application.development", + "终端与编辑器设置", + "Terminal & editor settings", + "应用设置", + "Application settings", + "开发设置", + "默认 Shell", + "编辑器", + "字体大小", + "缩进", + "自动换行", + "Minimap", + "development settings", + "default shell", + "editor", + "font size", + "indentation", + "word wrap", + "minimap", + "默认终端 Shell", + "编辑器字号与缩进", + "自动换行、格式化和 Minimap", + "Default terminal shell", + "Editor font size and indentation", + "Word wrapping, formatting, and minimap", + "自动检测并选择默认终端 Shell", + "Automatically detect and choose the default terminal shell", + "把终端面板放在右侧或底部", + "Place the terminal panel on the right or at the bottom", + "设置编辑器字体、字重、字号、行高与光标样式", + "Configure editor font, weight, size, line height, and cursor style", + "设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动", + "Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling", + "控制 Minimap、空白字符、当前行高亮和滚动边界", + "Control the minimap, whitespace rendering, current-line highlight, and scroll bounds", + "控制语义高亮、括号配色、保存/粘贴时格式化和空白清理", + "Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.development/" + }, + { + "id": "setting.ai.models", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "模型与供应商", + "titleEn": "Models & providers", + "summaryZh": "添加 AI 供应商和模型,选择默认模型,配置网络代理、订阅与流式超时。", + "summaryEn": "Add AI providers and models, choose defaults, and configure proxy, subscription, and streaming timeouts.", + "keywordsZh": [ + "模型设置", + "供应商", + "API Key", + "默认模型", + "代理", + "订阅", + "超时" + ], + "keywordsEn": [ + "model settings", + "provider", + "API key", + "default model", + "proxy", + "subscription", + "timeout" + ], + "highlightsZh": [ + "模型与供应商连接", + "主模型、快速模型和任务模型", + "代理、订阅与流式超时" + ], + "highlightsEn": [ + "Model and provider connections", + "Primary, fast, and task-specific defaults", + "Proxy, subscriptions, and streaming timeouts" + ], + "items": [ + { + "id": "providers", + "titleZh": "添加、编辑和删除内置或自定义 AI 供应商", + "titleEn": "Add, edit, and remove built-in or custom AI providers" + }, + { + "id": "credentials-endpoint", + "titleZh": "配置 API Key、Base URL、请求格式和模型列表", + "titleEn": "Configure API keys, base URLs, request formats, and model lists" + }, + { + "id": "subscription-auth", + "titleZh": "登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户", + "titleEn": "Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts" + }, + { + "id": "default-models", + "titleZh": "选择主模型、快速模型以及图像理解、图像生成和语音识别模型", + "titleEn": "Choose primary, fast, image-understanding, image-generation, and speech-recognition models" + }, + { + "id": "reasoning", + "titleZh": "为模型选择推理预设或自定义推理强度", + "titleEn": "Choose reasoning presets or a custom reasoning effort per model" + }, + { + "id": "proxy", + "titleZh": "配置 AI 请求使用的网络代理与绕过规则", + "titleEn": "Configure network proxies and bypass rules for AI requests" + }, + { + "id": "stream-timeouts", + "titleZh": "设置首 Token 等待和流式空闲超时", + "titleEn": "Set time-to-first-token and streaming idle timeouts" + }, + { + "id": "model-catalog", + "titleZh": "查看 models.dev 目录状态、手动刷新并定位本地缓存", + "titleEn": "Inspect models.dev catalog status, refresh it manually, and reveal its local cache" + }, + { + "id": "advanced-request", + "titleZh": "为供应商添加自定义 Header、请求体字段与 SSL 行为", + "titleEn": "Add custom headers, request-body fields, and SSL behavior per provider" + }, + { + "id": "connection-test", + "titleZh": "保存前测试供应商或模型连接并刷新运行时客户端", + "titleEn": "Test provider or model connectivity before saving and refresh the runtime client" + } + ], + "stepsZh": [ + "打开设置", + "进入“AI > 模型”", + "添加供应商并测试连接,再选择默认模型" + ], + "stepsEn": [ + "Open Settings", + "Go to AI > Models", + "Add and test a provider, then choose defaults" + ], + "agentExamplesZh": [ + "打开模型设置", + "带我配置默认模型", + "我想检查代理设置" + ], + "agentExamplesEn": [ + "Open model settings", + "Take me to default-model setup", + "I want to inspect proxy settings" + ], + "destination": { + "kind": "settings", + "pageId": "ai.models" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.ai.models", + "模型与供应商", + "Models & providers", + "AI 与协作", + "AI & collaboration", + "模型设置", + "供应商", + "API Key", + "默认模型", + "代理", + "订阅", + "超时", + "model settings", + "provider", + "API key", + "default model", + "proxy", + "subscription", + "timeout", + "模型与供应商连接", + "主模型、快速模型和任务模型", + "代理、订阅与流式超时", + "Model and provider connections", + "Primary, fast, and task-specific defaults", + "Proxy, subscriptions, and streaming timeouts", + "添加、编辑和删除内置或自定义 AI 供应商", + "Add, edit, and remove built-in or custom AI providers", + "配置 API Key、Base URL、请求格式和模型列表", + "Configure API keys, base URLs, request formats, and model lists", + "登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户", + "Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts", + "选择主模型、快速模型以及图像理解、图像生成和语音识别模型", + "Choose primary, fast, image-understanding, image-generation, and speech-recognition models", + "为模型选择推理预设或自定义推理强度", + "Choose reasoning presets or a custom reasoning effort per model", + "配置 AI 请求使用的网络代理与绕过规则", + "Configure network proxies and bypass rules for AI requests", + "设置首 Token 等待和流式空闲超时", + "Set time-to-first-token and streaming idle timeouts", + "查看 models.dev 目录状态、手动刷新并定位本地缓存", + "Inspect models.dev catalog status, refresh it manually, and reveal its local cache", + "为供应商添加自定义 Header、请求体字段与 SSL 行为", + "Add custom headers, request-body fields, and SSL behavior per provider", + "保存前测试供应商或模型连接并刷新运行时客户端", + "Test provider or model connectivity before saving and refresh the runtime client" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.ai.models/" + }, + { + "id": "setting.ai.memory", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "记忆设置", + "titleEn": "Memory settings", + "summaryZh": "控制 BitFun 是否从会话中提取和使用长期记忆,以及保留、整理和模型策略。", + "summaryEn": "Control whether BitFun extracts and uses long-term memory from sessions, including retention, consolidation, and model policy.", + "keywordsZh": [ + "记忆设置", + "长期记忆", + "学习", + "召回", + "整理", + "保留时间" + ], + "keywordsEn": [ + "memory settings", + "long-term memory", + "learning", + "recall", + "consolidation", + "retention" + ], + "highlightsZh": [ + "启用记忆生成与召回", + "BTW 会话与外部上下文策略", + "提取、整理模型和后台并发" + ], + "highlightsEn": [ + "Enable memory generation and recall", + "BTW sessions and external-context policy", + "Extraction, consolidation models, and background concurrency" + ], + "items": [ + { + "id": "generation-recall", + "titleZh": "分别控制长期记忆生成与会话召回,也可一键同时启用", + "titleEn": "Control long-term memory generation and recall independently or enable both together" + }, + { + "id": "btw", + "titleZh": "决定 BTW 轻量会话是否参与记忆生成", + "titleEn": "Choose whether lightweight BTW sessions contribute memories" + }, + { + "id": "external-context", + "titleZh": "存在外部工具上下文时选择清除工具结果、允许或跳过会话", + "titleEn": "When external tool context exists, clear tool results, allow it, or skip the session" + }, + { + "id": "rollout-policy", + "titleZh": "设置空闲时长、最大年龄、启动处理上限和扫描上限", + "titleEn": "Set idle time, maximum age, startup rollout limit, and scan limit" + }, + { + "id": "extraction", + "titleZh": "选择记忆提取模型、并发数和单次原始候选上限", + "titleEn": "Choose the extraction model, concurrency, and raw-candidate limit" + }, + { + "id": "retention", + "titleZh": "设置未使用记忆的最长保留天数", + "titleEn": "Set how long unused memories are retained" + }, + { + "id": "consolidation", + "titleZh": "选择记忆整理模型并让它跟随主模型或提取模型", + "titleEn": "Choose the consolidation model or make it follow the primary or extraction model" + }, + { + "id": "maintenance", + "titleZh": "打开记忆目录、恢复默认设置或显式清空全部记忆", + "titleEn": "Open the memory directory, restore defaults, or explicitly erase all memories" + } + ], + "stepsZh": [ + "打开设置", + "进入“AI > 记忆”", + "先启用记忆,再按需要调整高级参数" + ], + "stepsEn": [ + "Open Settings", + "Go to AI > Memory", + "Enable memory first, then tune advanced controls if needed" + ], + "agentExamplesZh": [ + "关闭长期记忆", + "允许 BTW 会话生成记忆", + "打开记忆设置" + ], + "agentExamplesEn": [ + "Turn off long-term memory", + "Allow BTW sessions to generate memories", + "Open Memory settings" + ], + "destination": { + "kind": "settings", + "pageId": "ai.memory" + }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用记忆", + "titleEn": "Enable memory", + "descriptionZh": "同时启用记忆生成和召回。", + "descriptionEn": "Enable both memory generation and recall.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "btw-sessions", + "titleZh": "BTW 会话生成记忆", + "titleEn": "Generate memory from BTW sessions", + "descriptionZh": "允许轻量 BTW 会话参与记忆提取。", + "descriptionEn": "Allow lightweight BTW sessions to contribute memories.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "external-context-policy", + "titleZh": "外部上下文策略", + "titleEn": "External context policy", + "descriptionZh": "决定存在外部工具上下文时如何生成记忆。", + "descriptionEn": "Choose how memory generation handles external tool context.", + "valueSchema": { + "type": "string", + "enum": [ + "clear_tool_results", + "allow", + "skip_session" + ] + } + }, + { + "id": "startup-rollout-limit", + "titleZh": "每次启动整理上限", + "titleEn": "Startup rollout limit", + "descriptionZh": "每次启动最多处理的待整理记忆批次。", + "descriptionEn": "Maximum pending memory rollouts processed after startup.", + "valueSchema": { + "type": "integer", + "minimum": 0, + "maximum": 100 + } + } + ], + "searchTerms": [ + "setting.ai.memory", + "记忆设置", + "Memory settings", + "AI 与协作", + "AI & collaboration", + "长期记忆", + "学习", + "召回", + "整理", + "保留时间", + "memory settings", + "long-term memory", + "learning", + "recall", + "consolidation", + "retention", + "启用记忆生成与召回", + "BTW 会话与外部上下文策略", + "提取、整理模型和后台并发", + "Enable memory generation and recall", + "BTW sessions and external-context policy", + "Extraction, consolidation models, and background concurrency", + "分别控制长期记忆生成与会话召回,也可一键同时启用", + "Control long-term memory generation and recall independently or enable both together", + "决定 BTW 轻量会话是否参与记忆生成", + "Choose whether lightweight BTW sessions contribute memories", + "存在外部工具上下文时选择清除工具结果、允许或跳过会话", + "When external tool context exists, clear tool results, allow it, or skip the session", + "设置空闲时长、最大年龄、启动处理上限和扫描上限", + "Set idle time, maximum age, startup rollout limit, and scan limit", + "选择记忆提取模型、并发数和单次原始候选上限", + "Choose the extraction model, concurrency, and raw-candidate limit", + "设置未使用记忆的最长保留天数", + "Set how long unused memories are retained", + "选择记忆整理模型并让它跟随主模型或提取模型", + "Choose the consolidation model or make it follow the primary or extraction model", + "打开记忆目录、恢复默认设置或显式清空全部记忆", + "Open the memory directory, restore defaults, or explicitly erase all memories" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.ai.memory/" + }, + { + "id": "setting.workspace.session", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "会话与工作区设置", + "titleEn": "Session & workspace settings", + "summaryZh": "控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。", + "summaryEn": "Control session-title generation, accelerated workspace search, and project-context behavior.", + "keywordsZh": [ + "会话设置", + "工作区设置", + "标题生成", + "项目搜索", + "索引" + ], + "keywordsEn": [ + "session settings", + "workspace settings", + "title generation", + "project search", + "index" + ], + "highlightsZh": [ + "自动生成会话标题", + "本地工作区加速搜索", + "会话使用的标题模型" + ], + "highlightsEn": [ + "Automatic session titles", + "Accelerated local-workspace search", + "Model used for session titles" + ], + "items": [ + { + "id": "automatic-titles", + "titleZh": "启用或停用根据会话内容自动生成标题", + "titleEn": "Enable or disable automatic titles generated from session content" + }, + { + "id": "title-model", + "titleZh": "让标题模型继承主模型、快速模型或使用指定模型", + "titleEn": "Make title generation inherit the primary or fast model, or use a selected model" + }, + { + "id": "accelerated-search", + "titleZh": "为本地工作区启用 Flashgrep 加速搜索", + "titleEn": "Enable Flashgrep-backed accelerated search for local workspaces" + }, + { + "id": "search-index", + "titleZh": "查看索引状态并在需要时重建工作区索引", + "titleEn": "Inspect index status and rebuild the workspace index when needed" + }, + { + "id": "remote-behavior", + "titleZh": "远程工作区明确降级搜索实现,不把远程路径回退到本机", + "titleEn": "Use an explicit remote-workspace search path without silently falling back to local files" + } + ], + "stepsZh": [ + "打开设置", + "进入“工作区 > 会话与工作区”", + "调整标题或搜索选项" + ], + "stepsEn": [ + "Open Settings", + "Go to Workspace > Session & Workspace", + "Tune title or search controls" + ], + "agentExamplesZh": [ + "关闭自动生成会话标题", + "启用工作区加速搜索" + ], + "agentExamplesEn": [ + "Turn off automatic session titles", + "Enable accelerated workspace search" + ], + "destination": { + "kind": "settings", + "pageId": "workspace.session" + }, + "operations": [], + "options": [ + { + "id": "session-title-generation", + "titleZh": "自动生成会话标题", + "titleEn": "Automatic session titles", + "descriptionZh": "根据会话内容生成易识别的标题。", + "descriptionEn": "Generate a recognizable title from session content.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "workspace-search", + "titleZh": "工作区加速搜索", + "titleEn": "Accelerated workspace search", + "descriptionZh": "为本地项目启用 Flashgrep 加速搜索。", + "descriptionEn": "Enable Flashgrep-backed search for local projects.", + "valueSchema": { + "type": "boolean" + } + } + ], + "searchTerms": [ + "setting.workspace.session", + "会话与工作区设置", + "Session & workspace settings", + "AI 与协作", + "AI & collaboration", + "会话设置", + "工作区设置", + "标题生成", + "项目搜索", + "索引", + "session settings", + "workspace settings", + "title generation", + "project search", + "index", + "自动生成会话标题", + "本地工作区加速搜索", + "会话使用的标题模型", + "Automatic session titles", + "Accelerated local-workspace search", + "Model used for session titles", + "启用或停用根据会话内容自动生成标题", + "Enable or disable automatic titles generated from session content", + "让标题模型继承主模型、快速模型或使用指定模型", + "Make title generation inherit the primary or fast model, or use a selected model", + "为本地工作区启用 Flashgrep 加速搜索", + "Enable Flashgrep-backed accelerated search for local workspaces", + "查看索引状态并在需要时重建工作区索引", + "Inspect index status and rebuild the workspace index when needed", + "远程工作区明确降级搜索实现,不把远程路径回退到本机", + "Use an explicit remote-workspace search path without silently falling back to local files" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.workspace.session/" + }, + { + "id": "setting.workspace.worktrees", + "kind": "setting", + "categoryId": "workspace", + "titleZh": "Worktree 设置", + "titleEn": "Worktree settings", + "summaryZh": "配置 Git Worktree 的根目录、分支前缀和自动清理规则,并查看现有隔离工作区。", + "summaryEn": "Configure the root, branch prefix, and cleanup rules for Git worktrees, and inspect existing isolated workspaces.", + "keywordsZh": [ + "Worktree 设置", + "并行分支", + "隔离工作区", + "分支前缀", + "自动清理" + ], + "keywordsEn": [ + "worktree settings", + "parallel branch", + "isolated workspace", + "branch prefix", + "automatic cleanup" + ], + "highlightsZh": [ + "Worktree 根目录与分支前缀", + "自动清理数量", + "现有 Worktree 和关联会话管理" + ], + "highlightsEn": [ + "Worktree root and branch prefix", + "Automatic cleanup count", + "Existing worktree and linked-session management" + ], + "items": [ + { + "id": "isolation", + "titleZh": "控制新会话是否默认使用独立 Git Worktree", + "titleEn": "Choose whether new sessions use isolated Git worktrees by default" + }, + { + "id": "root-path", + "titleZh": "设置受管 Worktree 的统一根目录", + "titleEn": "Set the common root directory for managed worktrees" + }, + { + "id": "branch-prefix", + "titleZh": "设置自动创建分支使用的名称前缀", + "titleEn": "Set the branch-name prefix used for automatically created branches" + }, + { + "id": "copy-changes", + "titleZh": "创建隔离工作区时选择是否复制当前未提交改动", + "titleEn": "Choose whether current uncommitted changes are copied into a new isolated workspace" + }, + { + "id": "auto-cleanup", + "titleZh": "启用自动清理并设置最多保留的受管 Worktree 数量", + "titleEn": "Enable automatic cleanup and set the maximum number of managed worktrees to retain" + }, + { + "id": "management", + "titleZh": "查看 Worktree 生命周期、脏状态、未发布提交与关联会话", + "titleEn": "Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions" + }, + { + "id": "open-restore-delete", + "titleZh": "打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree", + "titleEn": "Open or restore linked sessions and delete or force-delete a worktree after protection checks" + } + ], + "stepsZh": [ + "打开设置", + "进入“工作区 > Worktrees”", + "保存规则或管理现有 Worktree" + ], + "stepsEn": [ + "Open Settings", + "Go to Workspace > Worktrees", + "Save policy or manage existing worktrees" + ], + "agentExamplesZh": [ + "打开 Worktree 设置", + "带我管理并行工作区" + ], + "agentExamplesEn": [ + "Open Worktree settings", + "Take me to parallel-workspace management" + ], + "destination": { + "kind": "settings", + "pageId": "workspace.worktrees" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.workspace.worktrees", + "Worktree 设置", + "Worktree settings", + "项目与开发", + "Projects & development", + "并行分支", + "隔离工作区", + "分支前缀", + "自动清理", + "worktree settings", + "parallel branch", + "isolated workspace", + "branch prefix", + "automatic cleanup", + "Worktree 根目录与分支前缀", + "自动清理数量", + "现有 Worktree 和关联会话管理", + "Worktree root and branch prefix", + "Automatic cleanup count", + "Existing worktree and linked-session management", + "控制新会话是否默认使用独立 Git Worktree", + "Choose whether new sessions use isolated Git worktrees by default", + "设置受管 Worktree 的统一根目录", + "Set the common root directory for managed worktrees", + "设置自动创建分支使用的名称前缀", + "Set the branch-name prefix used for automatically created branches", + "创建隔离工作区时选择是否复制当前未提交改动", + "Choose whether current uncommitted changes are copied into a new isolated workspace", + "启用自动清理并设置最多保留的受管 Worktree 数量", + "Enable automatic cleanup and set the maximum number of managed worktrees to retain", + "查看 Worktree 生命周期、脏状态、未发布提交与关联会话", + "Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions", + "打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree", + "Open or restore linked sessions and delete or force-delete a worktree after protection checks" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.workspace.worktrees/" + }, + { + "id": "setting.tools.execution", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "执行与权限控制", + "titleEn": "Execution & permissions", + "summaryZh": "管理 Agent 工具权限、并行度、超时、延迟加载、Computer Use 与浏览器控制。", + "summaryEn": "Manage agent tool permissions, concurrency, timeouts, deferred loading, Computer Use, and browser control.", + "keywordsZh": [ + "执行控制", + "工具权限", + "审批", + "并行", + "超时", + "Computer Use", + "浏览器控制", + "JSON 修复" + ], + "keywordsEn": [ + "execution control", + "tool permissions", + "approval", + "parallel", + "timeout", + "computer use", + "browser control", + "JSON repair" + ], + "highlightsZh": [ + "询问、自动批准与完全访问策略", + "子 Agent 并行度和工具超时", + "Computer Use、浏览器连接与工具参数修复" + ], + "highlightsEn": [ + "Ask, auto-approve, and full-access policies", + "Subagent concurrency and tool timeouts", + "Computer Use, browser connection, and tool-argument repair" + ], + "items": [ + { + "id": "permission-mode", + "titleZh": "选择询问、自动批准或完全访问权限模式,并确认高风险警告", + "titleEn": "Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings" + }, + { + "id": "permission-selector", + "titleZh": "控制权限模式选择器是否显示在聊天输入框下方", + "titleEn": "Choose whether the permission-mode selector appears below the chat composer" + }, + { + "id": "global-project-rules", + "titleZh": "创建、排序和保存全局或项目级 Allow、Ask、Deny 规则", + "titleEn": "Create, reorder, and save global or project-level Allow, Ask, and Deny rules" + }, + { + "id": "remembered-grants", + "titleZh": "查看、撤销或清空项目中记住的权限授权与审计记录", + "titleEn": "Review, revoke, or clear remembered project permission grants and audit records" + }, + { + "id": "deferred-tools", + "titleZh": "按需延迟加载大型工具定义以减少 Agent 初始上下文", + "titleEn": "Load large tool definitions on demand to reduce initial agent context" + }, + { + "id": "parallelism", + "titleZh": "设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略", + "titleEn": "Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy" + }, + { + "id": "timeouts", + "titleZh": "设置权限确认等待和单次工具执行超时", + "titleEn": "Set permission-confirmation and per-tool execution timeouts" + }, + { + "id": "review-capacity", + "titleZh": "设置 Deep Review 最大并行评审者和队列等待时间", + "titleEn": "Set the maximum parallel Deep Review workers and queue wait time" + }, + { + "id": "computer-use", + "titleZh": "启用 Computer Use 并查看辅助功能与屏幕录制权限", + "titleEn": "Enable Computer Use and inspect accessibility and screen-recording permissions" + }, + { + "id": "browser-control", + "titleZh": "选择浏览器、配置默认 CDP 并控制启动时自动连接", + "titleEn": "Choose a browser, configure default CDP, and control automatic connection at startup" + }, + { + "id": "json-repair", + "titleZh": "控制是否在安全边界内修复模型生成的非法工具参数 JSON", + "titleEn": "Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > 执行与权限”", + "先确认安全影响,再修改权限或执行参数" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > Execution & Permissions", + "Review the security impact before changing permissions or execution controls" + ], + "agentExamplesZh": [ + "启用 Computer Use", + "把子 Agent 最大并发改为 8", + "打开权限设置" + ], + "agentExamplesEn": [ + "Enable Computer Use", + "Set maximum subagent concurrency to 8", + "Open permission settings" + ], + "destination": { + "kind": "settings", + "pageId": "tools.execution" + }, + "operations": [], + "options": [ + { + "id": "deferred-tool-loading", + "titleZh": "延迟加载工具", + "titleEn": "Deferred tool loading", + "descriptionZh": "按需加载大型工具定义,减少 Agent 初始上下文。", + "descriptionEn": "Load large tool definitions on demand to reduce initial agent context.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "subagent-batch-policy", + "titleZh": "子 Agent 批量执行策略", + "titleEn": "Subagent batch policy", + "descriptionZh": "选择仅安全任务并行、强制并行或串行执行。", + "descriptionEn": "Choose safe-only parallelism, forced parallelism, or serial execution.", + "valueSchema": { + "type": "string", + "enum": [ + "safe_only", + "force_parallel", + "serial" + ] + } + }, + { + "id": "subagent-max-concurrency", + "titleZh": "子 Agent 最大并发", + "titleEn": "Maximum subagent concurrency", + "descriptionZh": "限制同时运行的子 Agent 数量。", + "descriptionEn": "Limit the number of subagents that may run at once.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 32 + } + }, + { + "id": "swarm-max-concurrency", + "titleZh": "Swarm 最大并发", + "titleEn": "Maximum swarm concurrency", + "descriptionZh": "限制 Swarm 中同时执行的工作单元。", + "descriptionEn": "Limit concurrent work units inside a swarm.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 64 + } + }, + { + "id": "tool-timeout-seconds", + "titleZh": "工具执行超时", + "titleEn": "Tool execution timeout", + "descriptionZh": "单次工具调用的超时秒数。", + "descriptionEn": "Timeout in seconds for one tool call.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 86400 + } + }, + { + "id": "computer-use-enabled", + "titleZh": "Computer Use 桌面控制", + "titleEn": "Computer Use", + "descriptionZh": "允许 Agent 使用已授权的桌面控制能力。", + "descriptionEn": "Allow agents to use authorized desktop-control capabilities.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "browser-auto-connect", + "titleZh": "启动时连接浏览器", + "titleEn": "Connect browser on startup", + "descriptionZh": "BitFun 启动后自动尝试连接浏览器控制。", + "descriptionEn": "Automatically try to connect browser control after BitFun starts.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "tool-json-repair", + "titleZh": "工具参数 JSON 修复", + "titleEn": "Tool-argument JSON repair", + "descriptionZh": "允许在安全边界内修复模型生成的轻微 JSON 格式错误。", + "descriptionEn": "Allow minor model-generated JSON formatting errors to be repaired within the safety boundary.", + "valueSchema": { + "type": "boolean" + } + } + ], + "searchTerms": [ + "setting.tools.execution", + "执行与权限控制", + "Execution & permissions", + "AI 与协作", + "AI & collaboration", + "执行控制", + "工具权限", + "审批", + "并行", + "超时", + "Computer Use", + "浏览器控制", + "JSON 修复", + "execution control", + "tool permissions", + "approval", + "parallel", + "timeout", + "computer use", + "browser control", + "JSON repair", + "询问、自动批准与完全访问策略", + "子 Agent 并行度和工具超时", + "Computer Use、浏览器连接与工具参数修复", + "Ask, auto-approve, and full-access policies", + "Subagent concurrency and tool timeouts", + "Computer Use, browser connection, and tool-argument repair", + "选择询问、自动批准或完全访问权限模式,并确认高风险警告", + "Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings", + "控制权限模式选择器是否显示在聊天输入框下方", + "Choose whether the permission-mode selector appears below the chat composer", + "创建、排序和保存全局或项目级 Allow、Ask、Deny 规则", + "Create, reorder, and save global or project-level Allow, Ask, and Deny rules", + "查看、撤销或清空项目中记住的权限授权与审计记录", + "Review, revoke, or clear remembered project permission grants and audit records", + "按需延迟加载大型工具定义以减少 Agent 初始上下文", + "Load large tool definitions on demand to reduce initial agent context", + "设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略", + "Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy", + "设置权限确认等待和单次工具执行超时", + "Set permission-confirmation and per-tool execution timeouts", + "设置 Deep Review 最大并行评审者和队列等待时间", + "Set the maximum parallel Deep Review workers and queue wait time", + "启用 Computer Use 并查看辅助功能与屏幕录制权限", + "Enable Computer Use and inspect accessibility and screen-recording permissions", + "选择浏览器、配置默认 CDP 并控制启动时自动连接", + "Choose a browser, configure default CDP, and control automatic connection at startup", + "控制是否在安全边界内修复模型生成的非法工具参数 JSON", + "Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.execution/" + }, + { + "id": "setting.tools.automation", + "kind": "setting", + "categoryId": "automation", + "titleZh": "快捷操作与 Hooks", + "titleEn": "Quick actions & hooks", + "summaryZh": "自定义编码后的快捷操作,并配置在 Agent 生命周期事件上运行的 Hooks。", + "summaryEn": "Customize post-coding quick actions and configure hooks that run on agent lifecycle events.", + "keywordsZh": [ + "自动化设置", + "快捷操作", + "提交", + "创建 PR", + "Hooks", + "生命周期" + ], + "keywordsEn": [ + "automation settings", + "quick action", + "commit", + "create PR", + "hooks", + "lifecycle" + ], + "highlightsZh": [ + "编码后快捷操作", + "内置提交与创建 PR 动作", + "会话、工具与权限事件 Hooks" + ], + "highlightsEn": [ + "Post-coding quick actions", + "Built-in commit and create-PR actions", + "Hooks for session, tool, and permission events" + ], + "items": [ + { + "id": "built-in-actions", + "titleZh": "启用和调整内置的提交与创建 Pull Request 快捷操作", + "titleEn": "Enable and tune the built-in Commit and Create Pull Request quick actions", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "quick-actions" + } + }, + { + "id": "custom-actions", + "titleZh": "添加、编辑和删除自定义编码后快捷操作及 Prompt", + "titleEn": "Add, edit, and delete custom post-coding quick actions and prompts", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "quick-actions" + } + }, + { + "id": "hooks-enabled", + "titleZh": "整体启用或停用 Agent 生命周期 Hooks", + "titleEn": "Enable or disable agent lifecycle hooks globally", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "project-hooks", + "titleZh": "对可信仓库单独启用项目级 .bitfun/config/hooks.json", + "titleEn": "Enable project-level .bitfun/config/hooks.json separately for trusted repositories", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-files", + "titleZh": "定位用户级和项目级 Hooks 配置文件并在修改后即时生效", + "titleEn": "Locate user and project hook configuration files and apply edits without restarting", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-events", + "titleZh": "在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器", + "titleEn": "Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "external-hooks", + "titleZh": "查看外部 AI 应用的只读 Hook 目录并选择导入项", + "titleEn": "Inspect read-only external-AI hook catalogs and choose entries to import", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-import", + "titleZh": "预览、修改和应用 Hook 导入计划,并保留冲突诊断", + "titleEn": "Preview, edit, and apply hook import plans while retaining conflict diagnostics", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > 自动化”", + "在“快捷操作”或“Hooks”中配置" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > Automation", + "Configure Quick Actions or Hooks" + ], + "agentExamplesZh": [ + "打开 Hooks 设置", + "带我编辑编码后的快捷操作" + ], + "agentExamplesEn": [ + "Open Hooks settings", + "Take me to post-coding quick actions" + ], + "destination": { + "kind": "settings", + "pageId": "tools.automation" + }, + "operations": [], + "options": [ + { + "id": "hooks-enabled", + "titleZh": "启用 Hooks", + "titleEn": "Enable hooks", + "descriptionZh": "允许已配置的 Agent 生命周期 Hooks 运行。", + "descriptionEn": "Allow configured agent lifecycle hooks to run.", + "valueSchema": { + "type": "boolean" + } + }, + { + "id": "project-hooks-enabled", + "titleZh": "启用项目 Hooks", + "titleEn": "Enable project hooks", + "descriptionZh": "允许当前项目中的 Hooks 配置生效。", + "descriptionEn": "Allow hook configuration from the current project.", + "valueSchema": { + "type": "boolean" + } + } + ], + "searchTerms": [ + "setting.tools.automation", + "快捷操作与 Hooks", + "Quick actions & hooks", + "扩展与自动化", + "Extensions & automation", + "自动化设置", + "快捷操作", + "提交", + "创建 PR", + "Hooks", + "生命周期", + "automation settings", + "quick action", + "commit", + "create PR", + "hooks", + "lifecycle", + "编码后快捷操作", + "内置提交与创建 PR 动作", + "会话、工具与权限事件 Hooks", + "Post-coding quick actions", + "Built-in commit and create-PR actions", + "Hooks for session, tool, and permission events", + "启用和调整内置的提交与创建 Pull Request 快捷操作", + "Enable and tune the built-in Commit and Create Pull Request quick actions", + "添加、编辑和删除自定义编码后快捷操作及 Prompt", + "Add, edit, and delete custom post-coding quick actions and prompts", + "整体启用或停用 Agent 生命周期 Hooks", + "Enable or disable agent lifecycle hooks globally", + "对可信仓库单独启用项目级 .bitfun/config/hooks.json", + "Enable project-level .bitfun/config/hooks.json separately for trusted repositories", + "定位用户级和项目级 Hooks 配置文件并在修改后即时生效", + "Locate user and project hook configuration files and apply edits without restarting", + "在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器", + "Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input", + "查看外部 AI 应用的只读 Hook 目录并选择导入项", + "Inspect read-only external-AI hook catalogs and choose entries to import", + "预览、修改和应用 Hook 导入计划,并保留冲突诊断", + "Preview, edit, and apply hook import plans while retaining conflict diagnostics" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.automation/" + }, + { + "id": "setting.tools.mcp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "MCP 服务器", + "titleEn": "MCP servers", + "summaryZh": "添加和管理 Model Context Protocol 服务器,查看工具、资源、提示词与远程授权状态。", + "summaryEn": "Add and manage Model Context Protocol servers, including tools, resources, prompts, and remote authorization state.", + "keywordsZh": [ + "MCP", + "MCP 服务器", + "工具服务器", + "stdio", + "SSE", + "OAuth", + "资源" + ], + "keywordsEn": [ + "MCP", + "MCP server", + "tool server", + "stdio", + "SSE", + "OAuth", + "resource" + ], + "highlightsZh": [ + "添加本地或远程 MCP 服务器", + "查看连接健康与工具清单", + "完成远程 OAuth 授权" + ], + "highlightsEn": [ + "Add local or remote MCP servers", + "Inspect connection health and tool inventory", + "Complete remote OAuth authorization" + ], + "items": [ + { + "id": "json-config", + "titleZh": "用表单或 JSON 查看和保存全部 MCP 服务器配置", + "titleEn": "View and save all MCP server configuration through forms or JSON" + }, + { + "id": "server-types", + "titleZh": "添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器", + "titleEn": "Add local-process, remote HTTP/SSE, or container MCP servers" + }, + { + "id": "lifecycle", + "titleZh": "启动、停止、重启和删除单个 MCP 服务器", + "titleEn": "Start, stop, restart, and delete individual MCP servers" + }, + { + "id": "status", + "titleZh": "查看初始化、连接、健康、重连、鉴权和失败状态", + "titleEn": "Inspect initialization, connection, health, reconnecting, authentication, and failure states" + }, + { + "id": "remote-auth", + "titleZh": "配置远程 Header/环境变量认证或清除已有凭据", + "titleEn": "Configure remote header/environment authentication or clear stored credentials" + }, + { + "id": "oauth", + "titleZh": "发起、轮询、取消或重新连接远程 MCP OAuth", + "titleEn": "Start, poll, cancel, or reconnect remote MCP OAuth" + }, + { + "id": "tools-prompts", + "titleZh": "查看 MCP 工具、Prompt 列表并读取指定 Prompt", + "titleEn": "Browse MCP tools and prompts and load a selected prompt" + }, + { + "id": "resources", + "titleZh": "列出、读取和打开 MCP Resources", + "titleEn": "List, read, and open MCP resources" + }, + { + "id": "mcp-apps", + "titleZh": "打开 MCP App/UI、双向发送消息并回答交互请求", + "titleEn": "Open MCP App/UI surfaces, exchange messages, and answer interaction requests" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > MCP”", + "添加服务器并确认其权限与连接状态" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > MCP", + "Add a server and review its permissions and connection state" + ], + "agentExamplesZh": [ + "打开 MCP 设置", + "带我管理 MCP 服务器" + ], + "agentExamplesEn": [ + "Open MCP settings", + "Take me to MCP server management" + ], + "destination": { + "kind": "settings", + "pageId": "tools.mcp" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.tools.mcp", + "MCP 服务器", + "MCP servers", + "扩展与自动化", + "Extensions & automation", + "MCP", + "工具服务器", + "stdio", + "SSE", + "OAuth", + "资源", + "MCP server", + "tool server", + "resource", + "添加本地或远程 MCP 服务器", + "查看连接健康与工具清单", + "完成远程 OAuth 授权", + "Add local or remote MCP servers", + "Inspect connection health and tool inventory", + "Complete remote OAuth authorization", + "用表单或 JSON 查看和保存全部 MCP 服务器配置", + "View and save all MCP server configuration through forms or JSON", + "添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器", + "Add local-process, remote HTTP/SSE, or container MCP servers", + "启动、停止、重启和删除单个 MCP 服务器", + "Start, stop, restart, and delete individual MCP servers", + "查看初始化、连接、健康、重连、鉴权和失败状态", + "Inspect initialization, connection, health, reconnecting, authentication, and failure states", + "配置远程 Header/环境变量认证或清除已有凭据", + "Configure remote header/environment authentication or clear stored credentials", + "发起、轮询、取消或重新连接远程 MCP OAuth", + "Start, poll, cancel, or reconnect remote MCP OAuth", + "查看 MCP 工具、Prompt 列表并读取指定 Prompt", + "Browse MCP tools and prompts and load a selected prompt", + "列出、读取和打开 MCP Resources", + "List, read, and open MCP resources", + "打开 MCP App/UI、双向发送消息并回答交互请求", + "Open MCP App/UI surfaces, exchange messages, and answer interaction requests" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.mcp/" + }, + { + "id": "setting.tools.acp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "ACP 外部 Agents", + "titleEn": "ACP external agents", + "summaryZh": "配置通过 Agent Client Protocol 接入的外部 Agent,并检查适配器、命令与会话选项。", + "summaryEn": "Configure external agents connected through Agent Client Protocol and inspect adapters, commands, and session options.", + "keywordsZh": [ + "ACP", + "外部 Agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex" + ], + "keywordsEn": [ + "ACP", + "external agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex" + ], + "highlightsZh": [ + "注册外部 Agent", + "探测并安装 CLI 适配器", + "配置 ACP 会话选项" + ], + "highlightsEn": [ + "Register external agents", + "Probe and install CLI adapters", + "Configure ACP session options" + ], + "items": [ + { + "id": "presets", + "titleZh": "使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设", + "titleEn": "Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others" + }, + { + "id": "json-config", + "titleZh": "通过 JSON 查看、添加和保存 ACP Agent 配置", + "titleEn": "View, add, and save ACP agent configuration through JSON" + }, + { + "id": "probe", + "titleZh": "探测 CLI、适配器、路径、版本、连接与权限要求", + "titleEn": "Probe CLI, adapter, path, version, connection, and permission requirements" + }, + { + "id": "install", + "titleZh": "安装外部 Agent CLI 并预下载 ACP 客户端适配器", + "titleEn": "Install external-agent CLIs and predownload ACP client adapters" + }, + { + "id": "remote-detection", + "titleZh": "在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因", + "titleEn": "Detect available external agents in SSH workspaces and show explicit unsupported reasons" + }, + { + "id": "session-model-options", + "titleZh": "为 ACP 会话选择模型并修改客户端声明的配置选项", + "titleEn": "Choose an ACP session model and edit client-declared configuration options" + }, + { + "id": "session-commands", + "titleZh": "查看并执行外部 Agent 暴露的会话命令", + "titleEn": "Browse and run session commands exposed by an external agent" + }, + { + "id": "dialog-permissions", + "titleZh": "开始或取消 ACP 对话,并远程回答外部 Agent 权限请求", + "titleEn": "Start or cancel ACP turns and answer external-agent permission requests remotely" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > ACP”", + "添加客户端并通过探测检查可用性" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > ACP", + "Add a client and probe its availability" + ], + "agentExamplesZh": [ + "打开 ACP 设置", + "带我配置外部 Agent" + ], + "agentExamplesEn": [ + "Open ACP settings", + "Take me to external-agent setup" + ], + "destination": { + "kind": "settings", + "pageId": "tools.acp" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.tools.acp", + "ACP 外部 Agents", + "ACP external agents", + "扩展与自动化", + "Extensions & automation", + "ACP", + "外部 Agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex", + "external agent", + "注册外部 Agent", + "探测并安装 CLI 适配器", + "配置 ACP 会话选项", + "Register external agents", + "Probe and install CLI adapters", + "Configure ACP session options", + "使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设", + "Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others", + "通过 JSON 查看、添加和保存 ACP Agent 配置", + "View, add, and save ACP agent configuration through JSON", + "探测 CLI、适配器、路径、版本、连接与权限要求", + "Probe CLI, adapter, path, version, connection, and permission requirements", + "安装外部 Agent CLI 并预下载 ACP 客户端适配器", + "Install external-agent CLIs and predownload ACP client adapters", + "在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因", + "Detect available external agents in SSH workspaces and show explicit unsupported reasons", + "为 ACP 会话选择模型并修改客户端声明的配置选项", + "Choose an ACP session model and edit client-declared configuration options", + "查看并执行外部 Agent 暴露的会话命令", + "Browse and run session commands exposed by an external agent", + "开始或取消 ACP 对话,并远程回答外部 Agent 权限请求", + "Start or cancel ACP turns and answer external-agent permission requests remotely" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.acp/" + }, + { + "id": "setting.data.usage", + "kind": "setting", + "categoryId": "data", + "titleZh": "Token 用量", + "titleEn": "Token usage", + "summaryZh": "查看请求、输入输出 Token、缓存命中和估算成本等使用统计。", + "summaryEn": "Inspect request counts, input and output tokens, cache hits, and estimated cost statistics.", + "keywordsZh": [ + "Token 用量", + "成本", + "缓存", + "请求统计", + "用量历史" + ], + "keywordsEn": [ + "token usage", + "cost", + "cache", + "request statistics", + "usage history" + ], + "highlightsZh": [ + "按时间查看用量", + "区分输入、输出与缓存 Token", + "理解不同模型和会话的成本" + ], + "highlightsEn": [ + "Review usage over time", + "Separate input, output, and cached tokens", + "Understand cost by model and session" + ], + "items": [ + { + "id": "time-range", + "titleZh": "按最近 24 小时、今天、本周、本月或全部时间查看用量", + "titleEn": "Review usage for the last 24 hours, today, this week, this month, or all time" + }, + { + "id": "granularity", + "titleZh": "按小时或天切换趋势粒度", + "titleEn": "Switch trend granularity between hourly and daily views" + }, + { + "id": "filter", + "titleZh": "按供应商、模型或搜索关键词筛选用量", + "titleEn": "Filter usage by provider, model, or search text" + }, + { + "id": "summary", + "titleZh": "查看请求数、总 Token、缓存 Token 与缓存命中率", + "titleEn": "View request count, total tokens, cached tokens, and cache-hit rate" + }, + { + "id": "distribution", + "titleZh": "按模型、供应商组和请求端点比较分布", + "titleEn": "Compare distributions by model, provider group, and request endpoint" + }, + { + "id": "trend", + "titleZh": "分别查看输入、输出、缓存创建、缓存读取和命中率趋势", + "titleEn": "Track input, output, cache creation, cache read, and hit-rate trends separately" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 用量”", + "选择时间范围并查看统计" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Usage", + "Choose a time range and inspect statistics" + ], + "agentExamplesZh": [ + "打开 Token 用量", + "带我查看使用统计" + ], + "agentExamplesEn": [ + "Open Token usage", + "Show me usage statistics" + ], + "destination": { + "kind": "settings", + "pageId": "data.usage" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.data.usage", + "Token 用量", + "Token usage", + "数据与诊断", + "Data & diagnostics", + "成本", + "缓存", + "请求统计", + "用量历史", + "token usage", + "cost", + "cache", + "request statistics", + "usage history", + "按时间查看用量", + "区分输入、输出与缓存 Token", + "理解不同模型和会话的成本", + "Review usage over time", + "Separate input, output, and cached tokens", + "Understand cost by model and session", + "按最近 24 小时、今天、本周、本月或全部时间查看用量", + "Review usage for the last 24 hours, today, this week, this month, or all time", + "按小时或天切换趋势粒度", + "Switch trend granularity between hourly and daily views", + "按供应商、模型或搜索关键词筛选用量", + "Filter usage by provider, model, or search text", + "查看请求数、总 Token、缓存 Token 与缓存命中率", + "View request count, total tokens, cached tokens, and cache-hit rate", + "按模型、供应商组和请求端点比较分布", + "Compare distributions by model, provider group, and request endpoint", + "分别查看输入、输出、缓存创建、缓存读取和命中率趋势", + "Track input, output, cache creation, cache read, and hit-rate trends separately" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.usage/" + }, + { + "id": "setting.data.archived", + "kind": "setting", + "categoryId": "data", + "titleZh": "已归档会话", + "titleEn": "Archived sessions", + "summaryZh": "查找、恢复或永久删除已归档的会话,管理长期会话历史。", + "summaryEn": "Find, restore, or permanently delete archived sessions and manage long-term conversation history.", + "keywordsZh": [ + "已归档会话", + "会话历史", + "恢复会话", + "取消归档", + "删除历史" + ], + "keywordsEn": [ + "archived sessions", + "session history", + "restore session", + "unarchive", + "delete history" + ], + "highlightsZh": [ + "浏览归档会话", + "恢复到原工作区", + "显式永久删除历史" + ], + "highlightsEn": [ + "Browse archived sessions", + "Restore to the original workspace", + "Explicitly delete history permanently" + ], + "items": [ + { + "id": "browse", + "titleZh": "按工作区浏览分页归档会话及其元数据", + "titleEn": "Browse paged archived sessions and metadata by workspace" + }, + { + "id": "search", + "titleZh": "按标题、内容和工作区搜索已归档会话", + "titleEn": "Search archived sessions by title, content, and workspace" + }, + { + "id": "restore", + "titleZh": "恢复会话、轮次和原工作区视图并取消归档", + "titleEn": "Restore a session, its turns, and original workspace view, then unarchive it" + }, + { + "id": "delete-selected", + "titleZh": "明确确认后永久删除选中的归档会话", + "titleEn": "Permanently delete a selected archived session after explicit confirmation" + }, + { + "id": "delete-all", + "titleZh": "明确确认后永久删除全部归档会话", + "titleEn": "Permanently delete all archived sessions after explicit confirmation" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 已归档会话”", + "选择会话后恢复或删除" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Archived Sessions", + "Choose a session to restore or delete" + ], + "agentExamplesZh": [ + "打开已归档会话", + "带我恢复一个旧会话" + ], + "agentExamplesEn": [ + "Open archived sessions", + "Take me to restore an old session" + ], + "destination": { + "kind": "settings", + "pageId": "data.archived" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.data.archived", + "已归档会话", + "Archived sessions", + "数据与诊断", + "Data & diagnostics", + "会话历史", + "恢复会话", + "取消归档", + "删除历史", + "archived sessions", + "session history", + "restore session", + "unarchive", + "delete history", + "浏览归档会话", + "恢复到原工作区", + "显式永久删除历史", + "Browse archived sessions", + "Restore to the original workspace", + "Explicitly delete history permanently", + "按工作区浏览分页归档会话及其元数据", + "Browse paged archived sessions and metadata by workspace", + "按标题、内容和工作区搜索已归档会话", + "Search archived sessions by title, content, and workspace", + "恢复会话、轮次和原工作区视图并取消归档", + "Restore a session, its turns, and original workspace view, then unarchive it", + "明确确认后永久删除选中的归档会话", + "Permanently delete a selected archived session after explicit confirmation", + "明确确认后永久删除全部归档会话", + "Permanently delete all archived sessions after explicit confirmation" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.archived/" + }, + { + "id": "setting.data.diagnostics", + "kind": "setting", + "categoryId": "data", + "titleZh": "日志与诊断", + "titleEn": "Logs & diagnostics", + "summaryZh": "调整日志级别,查看运行日志路径,并导出用于排查问题的诊断包。", + "summaryEn": "Adjust logging level, inspect runtime log locations, and export diagnostic bundles for troubleshooting.", + "keywordsZh": [ + "诊断", + "日志", + "调试", + "日志级别", + "诊断包", + "故障排查" + ], + "keywordsEn": [ + "diagnostics", + "logs", + "debug", + "log level", + "diagnostic bundle", + "troubleshooting" + ], + "highlightsZh": [ + "调整后端日志级别", + "查看当前与上次异常退出日志", + "导出诊断包并控制敏感信息" + ], + "highlightsEn": [ + "Adjust backend log level", + "Inspect current and previous-crash logs", + "Export bundles and control sensitive diagnostics" + ], + "items": [ + { + "id": "log-level", + "titleZh": "设置 Trace、Debug、Info、Warn、Error 或关闭后端日志", + "titleEn": "Set backend logging to Trace, Debug, Info, Warn, Error, or Off" + }, + { + "id": "sensitive-diagnostics", + "titleZh": "选择诊断中是否允许包含敏感上下文,并在导出前明确提示", + "titleEn": "Choose whether diagnostics may include sensitive context, with an explicit warning before export" + }, + { + "id": "log-path", + "titleZh": "查看日志路径并打开日志文件夹", + "titleEn": "Inspect the log path and open the log folder" + }, + { + "id": "export-bundle", + "titleZh": "导出包含系统、配置健康和日志信息的诊断包", + "titleEn": "Export a diagnostics bundle containing system, configuration-health, and log information" + }, + { + "id": "crash-recovery", + "titleZh": "查看上次崩溃、非正常退出、启动恢复和配置恢复信息", + "titleEn": "Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery" + }, + { + "id": "devtools", + "titleZh": "在开发构建中检查 DevTools 是否可用并打开或关闭", + "titleEn": "In development builds, check DevTools availability and open or close them" + }, + { + "id": "element-inspector", + "titleZh": "在开发构建中启用主窗口元素检查并回传选中的元素", + "titleEn": "In development builds, inspect main-window elements and report the selected element" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 日志与诊断”", + "选择日志级别,或按需导出诊断包" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Logs & Diagnostics", + "Choose a log level or export a bundle when needed" + ], + "agentExamplesZh": [ + "把日志级别改成 debug", + "打开诊断设置", + "带我导出诊断包" + ], + "agentExamplesEn": [ + "Set the log level to debug", + "Open diagnostics settings", + "Take me to export a diagnostic bundle" + ], + "destination": { + "kind": "settings", + "pageId": "data.diagnostics" + }, + "operations": [], + "options": [ + { + "id": "log-level", + "titleZh": "日志级别", + "titleEn": "Log level", + "descriptionZh": "设置后端运行日志的详细程度。", + "descriptionEn": "Set the verbosity of backend runtime logs.", + "valueSchema": { + "type": "string", + "enum": [ + "error", + "warn", + "info", + "debug", + "trace" + ] + } + }, + { + "id": "sensitive-diagnostics", + "titleZh": "诊断包包含敏感信息", + "titleEn": "Include sensitive diagnostics", + "descriptionZh": "仅在明确需要并理解隐私风险时启用。", + "descriptionEn": "Enable only when explicitly needed and after reviewing the privacy risk.", + "valueSchema": { + "type": "boolean" + } + } + ], + "searchTerms": [ + "setting.data.diagnostics", + "日志与诊断", + "Logs & diagnostics", + "数据与诊断", + "Data & diagnostics", + "诊断", + "日志", + "调试", + "日志级别", + "诊断包", + "故障排查", + "diagnostics", + "logs", + "debug", + "log level", + "diagnostic bundle", + "troubleshooting", + "调整后端日志级别", + "查看当前与上次异常退出日志", + "导出诊断包并控制敏感信息", + "Adjust backend log level", + "Inspect current and previous-crash logs", + "Export bundles and control sensitive diagnostics", + "设置 Trace、Debug、Info、Warn、Error 或关闭后端日志", + "Set backend logging to Trace, Debug, Info, Warn, Error, or Off", + "选择诊断中是否允许包含敏感上下文,并在导出前明确提示", + "Choose whether diagnostics may include sensitive context, with an explicit warning before export", + "查看日志路径并打开日志文件夹", + "Inspect the log path and open the log folder", + "导出包含系统、配置健康和日志信息的诊断包", + "Export a diagnostics bundle containing system, configuration-health, and log information", + "查看上次崩溃、非正常退出、启动恢复和配置恢复信息", + "Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery", + "在开发构建中检查 DevTools 是否可用并打开或关闭", + "In development builds, check DevTools availability and open or close them", + "在开发构建中启用主窗口元素检查并回传选中的元素", + "In development builds, inspect main-window elements and report the selected element" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.diagnostics/" + } + ] +} diff --git a/docs/interactive-capabilities/capabilities/feature.agents.md b/docs/interactive-capabilities/capabilities/feature.agents.md new file mode 100644 index 0000000000..51643e0e14 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.agents.md @@ -0,0 +1,67 @@ + +--- +id: feature.agents +kind: feature +category: assistant +title_zh: "Agent 管理" +title_en: "Agents" +--- + +# Agent 管理 / Agents + +> 功能 / Feature + +管理内置、自定义和子 Agent,让不同角色分工处理研究、编码、评审等任务。 + +Manage built-in, custom, and subagents so specialized roles can handle research, coding, review, and more. + +## 完整功能清单 / Everything included + +- 查看内置、用户、项目与当前环境可见的 Agent + - Browse built-in, user, project, and currently visible agents +- 创建自定义 Agent 并设置名称、说明和角色 + - Create custom agents with a name, description, and role +- 读取、编辑、重新加载或删除自定义 Agent + - Inspect, edit, reload, or delete custom agents +- 创建、配置、查看和删除可委派的子 Agent + - Create, configure, inspect, and delete delegatable subagents +- 查看每个 Agent 的工具、Skills、只读状态和能力摘要 + - Inspect each agent's tools, Skills, read-only state, and capability summary +- 按 Agent 选择工具组、单个工具、Skill 组与 Skills + - Choose tool groups, individual tools, skill groups, and Skills per agent +- 让主 Agent 委派并行研究、编码和评审任务并设置超时 + - Let the primary agent delegate parallel research, coding, and review work with timeouts + +## 怎么用 / How to use it + +1. 打开 Agents + Open Agents +2. 选择现有 Agent 或创建一个角色 + Choose an existing agent or create a role +3. 在会话中指定角色,或让主 Agent 自动委派 + Select the role in a session or let the primary agent delegate + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Agents,我想看看有哪些专门角色” + - “Open Agents so I can see the specialized roles” +- “帮我进入 Agent 管理页” + - “Take me to agent management” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.ai-assistant.md b/docs/interactive-capabilities/capabilities/feature.ai-assistant.md new file mode 100644 index 0000000000..2322564e33 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.ai-assistant.md @@ -0,0 +1,73 @@ + +--- +id: feature.ai-assistant +kind: feature +category: assistant +title_zh: "AI 助手与会话" +title_en: "AI assistant & sessions" +--- + +# AI 助手与会话 / AI assistant & sessions + +> 功能 / Feature + +在项目上下文中与 AI 协作,创建会话、继续任务、处理权限请求,并保留完整的工作记录。 + +Work with AI in project context, create sessions, continue tasks, answer permission requests, and keep a durable work record. + +## 完整功能清单 / Everything included + +- 新建、重命名、归档、恢复、删除、分叉与导出会话 + - Create, rename, archive, restore, delete, fork, and export sessions +- 为会话选择模型、工作模式、记忆模式与权限模式 + - Choose the model, work mode, memory mode, and permission mode per session +- 开始、引导、打断、取消或恢复一次 Agent 运行 + - Start, steer, interrupt, cancel, or recover an agent turn +- 查看并逐个或批量回答等待中的权限请求 + - Review and answer pending permission requests individually or in a batch +- 分页加载、搜索和回填历史消息与会话内容 + - Page through, search, and backfill historical turns and session content +- 查看工具调用与后台命令,读取输出并继续输入或停止 + - Inspect tool calls and background commands, read output, send input, or stop them +- 创建会话目标、更新目标内容与状态并清除目标 + - Create session goals, update their objective and status, and clear them +- 查看单个会话的请求、Token 与成本用量报告 + - View request, token, and cost usage for an individual session +- 重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆 + - Reload session context, initialize AGENTS.md, and manage long-term memory +- 使用 BTW 轻量问答与编辑器内联 AI,并可随时取消 + - Use lightweight BTW questions and inline editor AI, with cancellation + +## 怎么用 / How to use it + +1. 打开 AI 助手或新建会话 + Open the AI assistant or create a session +2. 选择项目、模型和工作模式 + Choose a project, model, and working mode +3. 描述目标;BitFun 会在会话中持续记录进度 + Describe the goal; BitFun keeps progress in the session + +入口 / Entry: BitFun 对应场景 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 新建会话 / Create a session | 打开一个新的 AI 会话。 | Open a new AI session. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “新建一个会话,我们来排查这个构建错误” + - “Start a new session so we can debug this build error” +- “打开 AI 助手,我想继续刚才的任务” + - “Open the AI assistant; I want to continue my previous task” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.browser.md b/docs/interactive-capabilities/capabilities/feature.browser.md new file mode 100644 index 0000000000..b43de58ab7 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.browser.md @@ -0,0 +1,79 @@ + +--- +id: feature.browser +kind: feature +category: workspace +title_zh: "内置浏览器" +title_en: "Built-in browser" +--- + +# 内置浏览器 / Built-in browser + +> 功能 / Feature + +在 BitFun 内打开网页和本地服务;Agent 可直接读取页面、选择元素并点击、填写、滚动或截图。 + +Open webpages and local services inside BitFun, where an agent can inspect the page and select, click, fill, scroll, or capture elements directly. + +## 完整功能清单 / Everything included + +- 输入完整网址、本地域名或开发服务端口并在 BitFun 内打开 + - Open full URLs, local hostnames, or development-service ports inside BitFun +- 使用后退、前进和地址栏浏览页面历史 + - Navigate page history with Back, Forward, and the address bar +- 刷新页面,并同步当前 URL、加载状态与错误提示 + - Reload pages and synchronize the current URL, loading state, and errors +- 既可作为独立浏览器场景,也可在会话旁的辅助面板中打开 + - Use the browser as a standalone scene or an auxiliary panel beside a session +- 启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class + - Start the element picker to highlight hovered elements and show tag, ID, and class details +- 点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文 + - Click an element to capture its CSS path, attributes, text, and HTML into the current session context +- 再次点击选择按钮或按 Esc 取消元素选择并清理高亮 + - Click the picker again or press Escape to cancel selection and remove overlays +- 让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图 + - Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page +- 内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约 + - Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers +- 通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面 + - Choose the built-in or external browser with target and locate a page by session_id, URL, or title +- 桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接 + - Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place + +## 怎么用 / How to use it + +1. 打开浏览器并输入网址或本地端口 + Open Browser and enter a URL or local port +2. 直接告诉 Agent 要在页面上完成什么 + Tell the agent what to accomplish on the page +3. Agent 先读取页面,再用元素引用执行操作 + The agent inspects the page, then acts through element refs + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| ControlHub · 1 | 用 browser.open_builtin 打开网址并取得内置页面的 session_id | Open the URL with browser.open_builtin and keep the returned built-in session_id | +| ControlHub · 2 | 对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约 | Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract | +| ControlHub · 3 | 页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external | Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “在内置浏览器打开这个网址,然后找到登录按钮” + - “Open this URL in the built-in browser and find the sign-in button” +- “读取当前内置网页并填写这个表单” + - “Inspect the current built-in page and fill this form” +- “用内置浏览器点开搜索结果并总结页面” + - “Use the built-in browser to open the search result and summarize the page” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.canvas.md b/docs/interactive-capabilities/capabilities/feature.canvas.md new file mode 100644 index 0000000000..36aa1f1854 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.canvas.md @@ -0,0 +1,67 @@ + +--- +id: feature.canvas +kind: feature +category: automation +title_zh: "Canvas 与交互产物" +title_en: "Canvas & interactive artifacts" +--- + +# Canvas 与交互产物 / Canvas & interactive artifacts + +> 功能 / Feature + +在会话旁展示和保存 Agent 生成的可视化、交互页面与结构化产物。 + +Display and save visualizations, interactive pages, and structured artifacts generated beside a session. + +## 完整功能清单 / Everything included + +- 从会话工具结果加载并打开持久化 Canvas 产物 + - Load and open persistent Canvas artifacts from session tool results +- 渲染 HTML 或 React 交互界面、图表和可视化 + - Render HTML or React interfaces, charts, and interactive visualizations +- 在重新打开或刷新 Canvas 时加载和保存交互状态 + - Load and save interactive state when a Canvas is reopened or refreshed +- 查看 Canvas 源码、编译版本和最后可用版本 + - Inspect Canvas source, compiled revisions, and the last known good revision +- 选择 Canvas 内的元素并把元素引用加入会话上下文 + - Select an element inside Canvas and add its reference to session context +- 捕获运行错误、上报诊断并请求 Agent 自动修复 + - Capture runtime errors, report diagnostics, and ask the agent to repair them +- 把当前 Canvas 导出为可独立打开的 HTML 文件 + - Export the current Canvas as a standalone HTML file + +## 怎么用 / How to use it + +1. 打开一个 AI 会话 + Open an AI session +2. 让 Agent 创建可视化或交互工具 + Ask the agent for a visualization or interactive tool +3. 从工具结果打开 Canvas + Open the Canvas from the tool result + +入口 / Entry: BitFun 对应场景 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 AI 助手,我想做一个交互可视化” + - “Open the AI assistant; I want an interactive visualization” +- “创建一个可交互的 Canvas” + - “Create an interactive Canvas” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.code-review.md b/docs/interactive-capabilities/capabilities/feature.code-review.md new file mode 100644 index 0000000000..8d72ceeb77 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.code-review.md @@ -0,0 +1,67 @@ + +--- +id: feature.code-review +kind: feature +category: workspace +title_zh: "代码评审与 Pull Request" +title_en: "Code review & pull requests" +--- + +# 代码评审与 Pull Request / Code review & pull requests + +> 功能 / Feature + +阅读改动与 PR 上下文,查看 CI 日志,生成提交信息,并组织深度代码评审。 + +Review changes and pull-request context, inspect CI logs, generate commit messages, and run deeper code reviews. + +## 完整功能清单 / Everything included + +- 读取仓库、分支、工作区快照和评审目标 + - Load repository, branch, workspace snapshot, and review-target context +- 查看 Pull Request 详情、分页内容与关联改动 + - Inspect pull-request details, paged content, and related changes +- 读取 Pull Request 的 CI 运行日志 + - Read CI run logs for a pull request +- 读取关联 Issue 的标题、描述与上下文 + - Read the title, body, and context of linked issues +- 保存或清除评审平台访问令牌 + - Store or clear review-platform access tokens +- 预览、生成或快速采用提交信息 + - Preview, generate, or quickly apply a commit message +- 针对工作区、提交或 PR 发起 Deep Review 并控制评审队列 + - Run Deep Review against a workspace, commit, or pull request and control its queue + +## 怎么用 / How to use it + +1. 打开项目文件或 Git + Open project files or Git +2. 选择改动或评审目标 + Choose a change or review target +3. 在会话中请求评审或打开对应详情 + Ask for a review in the session or open its details + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开文件面板,我要评审当前改动” + - “Open Files so I can review the current changes” +- “带我查看 Pull Request 相关能力” + - “Take me to the pull-request workflow” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.computer-use.md b/docs/interactive-capabilities/capabilities/feature.computer-use.md new file mode 100644 index 0000000000..2bb3b6755c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.computer-use.md @@ -0,0 +1,67 @@ + +--- +id: feature.computer-use +kind: feature +category: workspace +title_zh: "浏览器与桌面控制" +title_en: "Browser & desktop control" +--- + +# 浏览器与桌面控制 / Browser & desktop control + +> 功能 / Feature + +授权 Agent 操作浏览器或本机界面,并明确管理辅助功能、屏幕录制与浏览器连接。 + +Allow agents to operate a browser or local UI while explicitly managing accessibility, screen-recording, and browser connection access. + +## 完整功能清单 / Everything included + +- 检查 Computer Use 可用性、辅助功能和屏幕录制授权状态 + - Check Computer Use availability plus accessibility and screen-recording permission status +- 请求桌面控制所需的系统权限 + - Request the operating-system permissions required for desktop control +- 直接打开对应的系统隐私与安全设置 + - Open the matching operating-system privacy and security settings +- 发现受支持的浏览器并查看当前 CDP 连接状态 + - Discover supported browsers and inspect the current CDP connection state +- 启动浏览器控制或连接已经开放 CDP 的浏览器 + - Launch browser control or connect to a browser that already exposes CDP +- 启用默认 CDP 配置并按需要重启浏览器 + - Enable the default CDP setup and restart the browser when required +- 授权后让 Agent 截图、点击、输入、滚动并读取可见界面 + - After authorization, let agents capture, click, type, scroll, and inspect the visible interface + +## 怎么用 / How to use it + +1. 打开执行控制设置 + Open Execution Control settings +2. 启用需要的能力 + Enable the required capability +3. 按提示授予系统权限或连接浏览器 + Grant OS access or connect a browser when prompted + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开桌面控制设置” + - “Open desktop-control settings” +- “带我配置浏览器控制” + - “Take me to browser-control setup” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.desktop-pet.md b/docs/interactive-capabilities/capabilities/feature.desktop-pet.md new file mode 100644 index 0000000000..e8d4efc3e1 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.desktop-pet.md @@ -0,0 +1,65 @@ + +--- +id: feature.desktop-pet +kind: feature +category: application +title_zh: "Agent 桌面伙伴" +title_en: "Agent desktop companion" +--- + +# Agent 桌面伙伴 / Agent desktop companion + +> 功能 / Feature + +在输入框或桌面上显示 Agent 伙伴,并选择、导入或管理 Petdex 角色包。 + +Show an agent companion in the composer or on the desktop, and choose, import, or manage Petdex character packs. + +## 完整功能清单 / Everything included + +- 整体启用或停用 Agent 桌面伙伴 + - Enable or disable the agent desktop companion globally +- 选择在聊天输入框、独立桌面窗口或两处显示 + - Show the companion in the chat composer, a desktop window, or both +- 查看并切换内置 Petdex 角色预设 + - Browse and switch among built-in Petdex character presets +- 从本地 Petdex 包导入新的角色与动画 + - Import new characters and animations from a local Petdex package +- 删除已导入的 Petdex 包并回退到可用角色 + - Delete an imported Petdex package and fall back to an available character +- 显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口 + - Show, hide, and resize the desktop companion window, and return to the main window + +## 怎么用 / How to use it + +1. 打开桌面伙伴设置 + Open Companion settings +2. 启用伙伴并选择显示位置 + Enable it and choose where it appears +3. 选择预设或导入 Petdex 包 + Choose a preset or import a Petdex pack + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开桌面宠物设置” + - “Open desktop-pet settings” +- “带我配置 Agent 伙伴” + - “Take me to agent-companion setup” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.detached-dispatch.md b/docs/interactive-capabilities/capabilities/feature.detached-dispatch.md new file mode 100644 index 0000000000..f48346061c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.detached-dispatch.md @@ -0,0 +1,69 @@ + +--- +id: feature.detached-dispatch +kind: feature +category: connect +title_zh: "Detached Dispatch 远程派发" +title_en: "Detached Dispatch" +--- + +# Detached Dispatch 远程派发 / Detached Dispatch + +> 功能 / Feature + +把可持续运行的任务派发到另一台 BitFun 主机;控制端可以断开,目标主机继续执行并保留记录。 + +Dispatch durable work to another BitFun host; the controller may disconnect while the target continues and keeps the record. + +## 完整功能清单 / Everything included + +- 列出可派发目标并探测版本、连接和运行能力 + - List dispatch targets and probe their version, connectivity, and runtime capabilities +- 为目标主机配置运行环境并安装或更新 BitFun CLI + - Provision the target runtime and install or update the BitFun CLI +- 在提交任务前同步目标所需的模型配置 + - Synchronize required model configuration before submitting a job +- 把包含工作区、会话、模型和权限策略的持久任务提交到目标 + - Submit a durable job with workspace, session, model, and permission policy to the target +- 列出派发任务并查询运行状态、结果和错误 + - List dispatched jobs and query their status, result, and errors +- 保存、追加和重新加载可断线恢复的执行记录 + - Save, append, and reload reconnectable execution transcripts +- 远程回答权限请求,并继续或取消目标端任务 + - Answer permission requests remotely and continue or cancel target-side work +- 将目标端结果同步回控制端,而不把控制端当作远程文件系统代理 + - Synchronize target-side results back without treating the controller as a remote-filesystem proxy + +## 怎么用 / How to use it + +1. 先在 Remote Connect 中登录并连接设备 + Sign in and connect devices through Remote Connect +2. 从会话的派发入口选择目标 + Choose a target from the session dispatch flow +3. 提交任务后在任务状态中跟踪 + Submit the work and follow its job status + +入口 / Entry: BitFun 内的对应控制界面 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开设备管理,我想把任务派发到另一台机器” + - “Open device management so I can dispatch work to another machine” +- “带我配置远程任务派发” + - “Take me to remote task dispatch setup” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.ecosystem-compatibility.md b/docs/interactive-capabilities/capabilities/feature.ecosystem-compatibility.md new file mode 100644 index 0000000000..20e2ecbc5c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.ecosystem-compatibility.md @@ -0,0 +1,71 @@ + +--- +id: feature.ecosystem-compatibility +kind: feature +category: automation +title_zh: "外部 AI 生态兼容" +title_en: "External AI ecosystem compatibility" +--- + +# 外部 AI 生态兼容 / External AI ecosystem compatibility + +> 功能 / Feature + +发现并迁移 OpenCode、Claude Code、Codex 等外部 AI 工具的配置、命令、Hooks 与 MCP 资源。 + +Discover and migrate configuration, commands, hooks, and MCP resources from OpenCode, Claude Code, Codex, and other AI tools. + +## 完整功能清单 / Everything included + +- 发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容 + - Discover OpenCode, Claude Code, Codex, and other external AI sources and content +- 按来源启用或停用集成,并选择管理、预览或只读策略 + - Enable or disable each source and choose managed, preview, or read-only policy +- 展开外部 Prompt/Command 内容并处理与原生命令的冲突 + - Expand external prompt/command content and resolve conflicts with native commands +- 导入或启用外部 Agent,处理同名冲突并绑定模型 + - Import or enable external agents, resolve naming conflicts, and bind models +- 预览 MCP 导入计划,逐个处理服务器冲突并应用 + - Preview MCP import plans, resolve server conflicts individually, and apply them +- 选择外部工具目标、解决冲突并控制是否启用 + - Choose external tool targets, resolve conflicts, and control activation +- 查看外部 Hooks 目录、规划导入、修改选择并应用 + - Inspect external hook catalogs, plan imports, edit selections, and apply +- 在迁移前查看冲突、安全影响和来源控制快照 + - Review conflicts, security impact, and source-control snapshots before migration +- 在文件管理器或远程环境中定位外部配置来源 + - Reveal external configuration sources in the file manager or remote environment + +## 怎么用 / How to use it + +1. 打开“生态兼容” + Open Ecosystem Compatibility +2. 选择来源并查看扫描结果 + Choose a source and review the scan +3. 确认计划后导入需要的内容 + Confirm the plan and import selected content + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开外部 AI 生态兼容” + - “Open external AI ecosystem compatibility” +- “我想迁移 Claude Code 的配置” + - “I want to migrate my Claude Code configuration” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.files-editor.md b/docs/interactive-capabilities/capabilities/feature.files-editor.md new file mode 100644 index 0000000000..8d73200fde --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.files-editor.md @@ -0,0 +1,73 @@ + +--- +id: feature.files-editor +kind: feature +category: workspace +title_zh: "文件与代码编辑" +title_en: "Files & code editing" +--- + +# 文件与代码编辑 / Files & code editing + +> 功能 / Feature + +浏览、搜索和编辑项目文件,查看差异、代码符号、诊断与 Agent 产生的改动。 + +Browse, search, and edit project files while inspecting diffs, symbols, diagnostics, and agent changes. + +## 完整功能清单 / Everything included + +- 浏览文件树并创建、重命名、删除或在系统中显示文件和目录 + - Browse the file tree and create, rename, delete, or reveal files and directories +- 建立或重建索引,按文件名和全文内容流式搜索 + - Build or rebuild an index and stream filename and full-text search results +- 读取、编辑、保存文件并同步编辑器状态 + - Read, edit, and save files while synchronizing editor state +- 查看修改文件、会话、轮次和单次操作的差异与统计 + - Inspect diffs and statistics by file, session, turn, or operation +- 按文件、操作或整个会话接受或拒绝 Agent 改动 + - Accept or reject agent changes by file, operation, or whole session +- 查看文件变更历史和快照,并回滚整个会话或指定轮次 + - Review file history and snapshots, then roll back a session or selected turn +- 使用 Hover、跳转定义、查找引用、文档符号与高亮 + - Use hover, go to definition, references, document symbols, and highlights +- 使用补全、格式化、重命名、代码操作、内联提示与语义高亮 + - Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting +- 检测项目并安装、启动、停止或卸载 LSP 插件 + - Detect projects and install, start, stop, or uninstall LSP plugins +- 粘贴、拖放或上传文件与图片作为会话上下文 + - Paste, drop, or upload files and images as session context + +## 怎么用 / How to use it + +1. 先打开一个项目 + Open a project first +2. 打开“文件” + Open Files +3. 选择文件进行编辑,或搜索内容与符号 + Choose a file to edit, or search content and symbols + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开项目文件” + - “Open the project files” +- “带我去文件和代码编辑器” + - “Take me to the file and code editor” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.git.md b/docs/interactive-capabilities/capabilities/feature.git.md new file mode 100644 index 0000000000..b41864c1d1 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.git.md @@ -0,0 +1,71 @@ + +--- +id: feature.git +kind: feature +category: workspace +title_zh: "Git 版本控制" +title_en: "Git version control" +--- + +# Git 版本控制 / Git version control + +> 功能 / Feature + +查看改动、分支和提交,完成暂存、提交、合并、Cherry-pick 与 Worktree 工作流。 + +Inspect changes, branches, and commits; stage, commit, merge, cherry-pick, and work with Git worktrees. + +## 完整功能清单 / Everything included + +- 查看仓库状态、修改文件和逐文件 Diff + - Inspect repository status, changed files, and per-file diffs +- 暂存文件、取消暂存并重置到指定提交 + - Stage files, unstage changes, and reset to a selected commit +- 预览或生成提交信息并创建提交 + - Preview or generate a commit message and create the commit +- 从远端 Pull 并向远端 Push + - Pull from and push to remotes +- 查看、创建、切换和删除本地分支 + - Browse, create, check out, and delete local branches +- 浏览提交图谱与仓库历史并保存最近访问记录 + - Browse the commit graph and repository history, including recent-history persistence +- 解析 Revision 并查看任意提交中的文件内容 + - Resolve revisions and inspect file content from any commit +- 执行、继续或中止 Cherry-pick + - Start, continue, or abort a cherry-pick +- 管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除 + - Manage repository trust and create, bind, promote, recreate, or remove worktrees + +## 怎么用 / How to use it + +1. 打开 Git + Open Git +2. 选择改动或分支 + Choose changes or a branch +3. 执行暂存、提交或分支操作 + Stage, commit, or perform a branch operation + +入口 / Entry: BitFun 对应场景 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Git 面板” + - “Open the Git panel” +- “带我查看当前代码改动” + - “Show me the current code changes” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.insights.md b/docs/interactive-capabilities/capabilities/feature.insights.md new file mode 100644 index 0000000000..02e3b79c8d --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.insights.md @@ -0,0 +1,65 @@ + +--- +id: feature.insights +kind: feature +category: automation +title_zh: "Insights 工作洞察" +title_en: "Insights" +--- + +# Insights 工作洞察 / Insights + +> 功能 / Feature + +把会话和项目活动汇总成可读的洞察,帮助回顾工作方式、用量和进展。 + +Turn session and project activity into readable insights about working patterns, usage, and progress. + +## 完整功能清单 / Everything included + +- 检查当前账户与会话是否已有可分析的洞察数据 + - Check whether the current account and sessions contain analyzable insight data +- 按所选日期范围和模型生成工作洞察报告 + - Generate a work-insights report for a selected date range and model +- 取消正在运行的洞察生成任务 + - Cancel an in-progress insights generation job +- 查看最新报告或加载指定的历史报告 + - Open the latest report or load a selected historical report +- 把工作活动与模型、Token 和缓存用量统计关联起来 + - Relate work activity to model, token, and cache-usage statistics +- 回顾项目分布、工作时段、任务类型和协作习惯 + - Review project distribution, working hours, task types, and collaboration patterns + +## 怎么用 / How to use it + +1. 打开 Insights + Open Insights +2. 选择可用的数据范围 + Choose the available data scope +3. 生成或查看最新报告 + Generate or read the latest report + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Insights” + - “Open Insights” +- “带我查看工作洞察” + - “Show me my work insights” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.miniapps.md b/docs/interactive-capabilities/capabilities/feature.miniapps.md new file mode 100644 index 0000000000..3cf735a5e0 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.miniapps.md @@ -0,0 +1,73 @@ + +--- +id: feature.miniapps +kind: feature +category: automation +title_zh: "Mini Apps 小应用" +title_en: "Mini Apps" +--- + +# Mini Apps 小应用 / Mini Apps + +> 功能 / Feature + +在 BitFun 内安装、创建和运行轻量应用,让界面、数据与 Agent 工作流组合在一起。 + +Install, create, and run lightweight apps inside BitFun, combining UI, data, and agent workflows. + +## 完整功能清单 / Everything included + +- 查看、搜索、创建、导入、编辑和删除 Mini App + - Browse, search, create, import, edit, and delete Mini Apps +- 浏览市场、查看详情并安装或更新发布版本 + - Browse the market, inspect listings, and install or update releases +- 登录市场账户并收藏、评分和查看已安装来源 + - Sign in to the market, favorite and rate apps, and inspect installed origins +- 按路径或工作区授予权限,并在定制前审查权限差异 + - Grant path or workspace access and review permission changes before customization +- 运行 Mini App Host 与 Worker,查看状态并停止后台 Worker + - Run Mini App host and worker calls, inspect status, and stop background workers +- 为正式应用和定制草稿分别读取与保存持久状态 + - Read and save persistent state separately for installed apps and customization drafts +- 在 Mini App 中调用模型补全、聊天和专属 Agent 会话 + - Use model completion, chat, and dedicated agent sessions inside Mini Apps +- 创建定制草稿、实时预览,并应用、同步或丢弃修改 + - Create customization drafts, preview them live, and apply, sync, or discard changes +- 查看版本历史并回滚到旧版本 + - Inspect version history and roll back to an earlier release +- 提交、撤回和审查市场发布,并可渲染幻灯片页面 + - Submit, withdraw, and review market releases, and render slide pages + +## 怎么用 / How to use it + +1. 打开 Mini Apps + Open Mini Apps +2. 选择市场、已安装或创建 + Choose Market, Installed, or Create +3. 打开应用并按页面提示使用 + Launch the app and follow its interface + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Mini Apps” + - “Open Mini Apps” +- “带我去小应用市场” + - “Take me to the Mini App market” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.pages.md b/docs/interactive-capabilities/capabilities/feature.pages.md new file mode 100644 index 0000000000..8a9ade76d1 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.pages.md @@ -0,0 +1,67 @@ + +--- +id: feature.pages +kind: feature +category: connect +title_zh: "Pages 发布" +title_en: "Pages publishing" +--- + +# Pages 发布 / Pages publishing + +> 功能 / Feature + +保存页面版本并发布到公开或私有地址,管理标题、可见性、历史版本和分享链接。 + +Save page versions and publish them to public or private URLs while managing titles, visibility, history, and share links. + +## 完整功能清单 / Everything included + +- 查看账户下的 Pages 与每个页面的当前发布状态 + - List account Pages and inspect each page's current publishing state +- 保存不可变页面版本并浏览版本历史 + - Save immutable page versions and browse version history +- 发布或重新部署选中的页面版本 + - Publish or redeploy a selected page version +- 更新标题、公开/私有可见性和访问设置 + - Update titles, public/private visibility, and access settings +- 创建可打开和分享的页面链接 + - Create an openable, shareable link for a page +- 取消发布页面,同时保留可再次发布的版本 + - Unpublish a page while retaining versions for later publication +- 删除单个版本或整个 Page + - Delete an individual version or an entire Page + +## 怎么用 / How to use it + +1. 登录 BitFun 账户 + Sign in to a BitFun account +2. 打开 Pages + Open Pages +3. 选择页面并确认发布与可见性 + Choose a page and confirm publishing and visibility + +入口 / Entry: BitFun 对应场景 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Pages” + - “Open Pages” +- “带我管理已发布的页面” + - “Take me to my published pages” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.personal-assistants.md b/docs/interactive-capabilities/capabilities/feature.personal-assistants.md new file mode 100644 index 0000000000..bca74e2902 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.personal-assistants.md @@ -0,0 +1,75 @@ + +--- +id: feature.personal-assistants +kind: feature +category: assistant +title_zh: "个人助理" +title_en: "Personal assistants" +--- + +# 个人助理 / Personal assistants + +> 功能 / Feature + +在助理空间中创建和管理自己的长期 AI 助理,定义身份与人设、配置默认能力,并从同一处开始会话或安排定时任务。 + +Create and manage persistent AI assistants, define their identity and persona, configure default capabilities, and start chats or scheduled work from one place. + +## 完整功能清单 / Everything included + +- 浏览已有助理、创建新助理并查看每个助理的身份与能力概览 + - Browse existing assistants, create a new one, and review each assistant's identity and capability summary +- 设为主助理、删除非主助理,或将助理工作区重置为默认状态 + - Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults +- 编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符 + - Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character +- 读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter + - Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter +- 为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态 + - Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability +- 逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态 + - Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults +- 按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具 + - Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants +- 按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值 + - Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults +- 从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话 + - Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page +- 查看和管理仅属于当前助理工作区的定时会话与自动任务 + - Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace + +## 怎么用 / How to use it + +1. 打开“助理” + Open Assistants +2. 创建助理或选择现有助理 + Create an assistant or choose an existing one +3. 编辑身份与人设,配置默认能力,然后开始会话或定时任务 + Edit its identity and persona, configure defaults, then start a chat or scheduled task + +入口 / Entry: BitFun 对应场景 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开我的个人助理” + - “Open my personal assistants” +- “带我去育苗场配置助理的默认工具” + - “Take me to the nursery to configure default assistant tools” +- “我想修改主助理的人设” + - “I want to edit my primary assistant's persona” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.projects.md b/docs/interactive-capabilities/capabilities/feature.projects.md new file mode 100644 index 0000000000..66df133bb5 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.projects.md @@ -0,0 +1,68 @@ + +--- +id: feature.projects +kind: feature +category: workspace +title_zh: "项目与工作区" +title_en: "Projects & workspaces" +--- + +# 项目与工作区 / Projects & workspaces + +> 功能 / Feature + +打开本地目录或创建项目,让文件、会话、终端和 Agent 围绕同一工作区协作。 + +Open a local directory or create a project so files, sessions, terminals, and agents share one workspace. + +## 完整功能清单 / Everything included + +- 打开、关闭、切换并重新排序多个工作区 + - Open, close, switch, and reorder multiple workspaces +- 查看、清理和重新打开最近使用的项目 + - Review, clean up, and reopen recently used projects +- 扫描并维护工作区名称、信息、关联目录和 Persona 文件 + - Scan and maintain workspace names, metadata, related directories, and persona files +- 监听项目文件变化并查看当前监听路径 + - Watch project file changes and inspect active watched paths +- 按文件名、路径或文件内容搜索本地工作区 + - Search local workspaces by filename, path, or file content +- 从项目流程打开 SSH 或其他远程工作区 + - Open SSH and other remote workspaces from the project flow +- 查看当前工作区、应用状态、健康状态与统计信息 + - Inspect the current workspace, app state, health, and statistics + +## 怎么用 / How to use it + +1. 选择“打开项目”或“新建项目” + Choose Open Project or New Project +2. 选择本地目录或配置远程位置 + Select a local directory or configure a remote location +3. 从侧边栏进入项目文件与会话 + Use the sidebar to access files and sessions + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开项目 / Open project | 选择并打开一个已有目录。 | Choose and open an existing directory. | +| 新建项目 / Create project | 打开新建项目流程。 | Open the new-project flow. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “帮我打开一个项目” + - “Help me open a project” +- “打开新建项目的界面” + - “Open the new-project flow” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.remote-connect.md b/docs/interactive-capabilities/capabilities/feature.remote-connect.md new file mode 100644 index 0000000000..222928e70c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.remote-connect.md @@ -0,0 +1,75 @@ + +--- +id: feature.remote-connect +kind: feature +category: connect +title_zh: "Remote Connect 与多设备" +title_en: "Remote Connect & devices" +--- + +# Remote Connect 与多设备 / Remote Connect & devices + +> 功能 / Feature + +从手机、Bot 或另一台 BitFun 设备连接当前主机,远程查看会话、回答权限并继续工作。 + +Connect to this host from mobile, a bot, or another BitFun device to inspect sessions, answer permissions, and continue work remotely. + +## 完整功能清单 / Everything included + +- 选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器 + - Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server +- 启动、停止 Remote Connect 并查看实时连接状态和设备信息 + - Start or stop Remote Connect and inspect live status and device information +- 查看局域网 IP、网络信息与可分享的连接配置 + - Inspect LAN IP, network details, and shareable connection configuration +- 配置飞书、Telegram、微信等 Bot 并单独停止 Bot + - Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently +- 通过向导预检、安装 Docker、部署、注册并验证自建 Relay + - Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard +- 登录、退出并查看账户状态和凭据提示 + - Sign in, sign out, and inspect account status and credential hints +- 列出、连接、查看在线状态和删除同账户设备 + - List, connect, inspect online status, and remove same-account devices +- 同步、导出、导入、删除或发送会话到另一台设备 + - Sync, export, import, delete, or send sessions to another device +- 在设备间自动或手动同步 BitFun 设置 + - Synchronize BitFun settings across devices automatically or on demand +- 进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面 + - Enter Peer Device Mode and use another BitFun device as the command and event data plane + +## 怎么用 / How to use it + +1. 打开 Remote Connect + Open Remote Connect +2. 选择网络、Bot 或账户 + Choose Network, Bot, or Account +3. 按向导连接并确认安全提示 + Follow the connection flow and review its security notice + +入口 / Entry: BitFun 内的对应控制界面 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Remote Connect” + - “Open Remote Connect” +- “我想配置手机远程控制” + - “I want to configure mobile remote control” +- “带我管理已连接设备” + - “Take me to connected-device management” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.remote-workspaces.md b/docs/interactive-capabilities/capabilities/feature.remote-workspaces.md new file mode 100644 index 0000000000..15fb70f4f5 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.remote-workspaces.md @@ -0,0 +1,71 @@ + +--- +id: feature.remote-workspaces +kind: feature +category: connect +title_zh: "远程工作区" +title_en: "Remote workspaces" +--- + +# 远程工作区 / Remote workspaces + +> 功能 / Feature + +通过 SSH 或容器在远程主机上打开项目,让文件、搜索、终端和 Agent 都在目标环境执行。 + +Open projects over SSH or in containers so files, search, terminal, and agents all execute in the target environment. + +## 完整功能清单 / Everything included + +- 保存、列出、测试和删除 SSH 连接配置 + - Save, list, test, and delete SSH connection profiles +- 使用密码、私钥、证书、SSH Config Host 与跳板机连接 + - Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts +- 发现远程 Docker 容器并把容器作为工作环境 + - Discover remote Docker containers and use a container as the work environment +- 打开、关闭和移除远程工作区,并读取服务器信息 + - Open, close, and remove remote workspaces, and inspect server information +- 浏览、读取、写入、创建、重命名和删除远程文件与目录 + - Browse, read, write, create, rename, and remove remote files and directories +- 上传本地文件、下载远程文件并取消进行中的传输 + - Upload local files, download remote files, and cancel active transfers +- 在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面 + - Execute commands on the target so terminals, search, and agents use the remote data plane +- 发现远程监听端口并启动、查看或停止端口转发 + - Discover remote listening ports and start, inspect, or stop port forwarding +- 查看连接状态并断开单个或全部 SSH 会话 + - Inspect connection status and disconnect one or all SSH sessions + +## 怎么用 / How to use it + +1. 打开新建项目 + Open New Project +2. 选择远程连接方式 + Choose a remote connection type +3. 配置主机并测试连接后打开工作区 + Configure and test the host, then open the workspace + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开远程项目配置” + - “Open remote-project setup” +- “我想连接一个 SSH 工作区” + - “I want to connect to an SSH workspace” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.skills.md b/docs/interactive-capabilities/capabilities/feature.skills.md new file mode 100644 index 0000000000..d0dc3aae75 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.skills.md @@ -0,0 +1,69 @@ + +--- +id: feature.skills +kind: feature +category: automation +title_zh: "Skills 技能" +title_en: "Skills" +--- + +# Skills 技能 / Skills + +> 功能 / Feature + +为 Agent 安装和管理可复用的专业工作流,并控制哪些模式可以使用它们。 + +Install and manage reusable expert workflows for agents, and control which modes can use them. + +## 完整功能清单 / Everything included + +- 统一查看用户级、项目级、本地和远程来源的已安装 Skills + - Browse installed Skills from user, project, local, and remote sources in one catalog +- 浏览、搜索和刷新 Skill 市场 + - Browse, search, and refresh the Skill market +- 把市场 Skill 下载到用户级或当前项目 + - Download a market Skill for the user or current project +- 校验本地 Skill 路径并添加到用户级或项目级 + - Validate a local Skill path and add it at user or project scope +- 删除已安装的用户级或项目级 Skill + - Remove an installed user-level or project-level Skill +- 在全局范围启用或停用单个 Skill + - Enable or disable an individual Skill globally +- 按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择 + - Choose Skills and skill groups per agent mode and restore defaults +- 识别同名 Skill 的用户级与项目级遮蔽优先级 + - Understand user-versus-project shadowing precedence for same-named Skills + +## 怎么用 / How to use it + +1. 打开 Skills + Open Skills +2. 搜索需要的工作流 + Search for the workflow you need +3. 安装后在会话中调用 + Install it and invoke it from a session + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Skills” + - “Open Skills” +- “带我去技能管理” + - “Take me to skill management” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.tasks-automation.md b/docs/interactive-capabilities/capabilities/feature.tasks-automation.md new file mode 100644 index 0000000000..2c229f9beb --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.tasks-automation.md @@ -0,0 +1,67 @@ + +--- +id: feature.tasks-automation +kind: feature +category: automation +title_zh: "任务板与定时任务" +title_en: "Task board & scheduled jobs" +--- + +# 任务板与定时任务 / Task board & scheduled jobs + +> 功能 / Feature + +集中查看待办事项,并让任务在指定时间或目标主机上持续运行。 + +Track work in one task board and let scheduled jobs run at a chosen time or host. + +## 完整功能清单 / Everything included + +- 按待处理、日历和已停用视图浏览任务 + - Browse tasks in Pending, Calendar, and Inactive views +- 创建、编辑、启用、停用和删除定时任务 + - Create, edit, enable, disable, and delete scheduled jobs +- 设置一次性、每日、每周或自定义 Cron 时间表 + - Choose one-time, daily, weekly, or custom cron schedules +- 在日历中预览任务的下一次与后续运行时间 + - Preview the next and future job occurrences on a calendar +- 为任务选择 Agent、模型、工作模式和工作区 + - Choose the agent, model, work mode, and workspace for a job +- 把任务安排在当前主机或已连接的远程目标上运行 + - Schedule jobs to run on the current host or a connected remote target +- 查看任务列表并等待桌面 Host 就绪后可靠执行 + - List jobs and wait for desktop-host readiness before reliable execution + +## 怎么用 / How to use it + +1. 打开任务板 + Open the Task Board +2. 选择待办或定时任务 + Choose todos or scheduled jobs +3. 创建任务并确认运行目标与时间 + Create the job and confirm its target and timing + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开任务板” + - “Open the task board” +- “带我去看定时任务” + - “Take me to scheduled jobs” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.terminal.md b/docs/interactive-capabilities/capabilities/feature.terminal.md new file mode 100644 index 0000000000..4991af527f --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.terminal.md @@ -0,0 +1,67 @@ + +--- +id: feature.terminal +kind: feature +category: workspace +title_zh: "终端" +title_en: "Terminal" +--- + +# 终端 / Terminal + +> 功能 / Feature + +在当前项目中运行 Shell、查看输出、保留命令历史,并让 Agent 与同一终端环境协作。 + +Run a shell in the current project, inspect output, keep command history, and share the same terminal context with agents. + +## 完整功能清单 / Everything included + +- 创建、列出、切换和关闭多个终端会话 + - Create, list, switch, and close multiple terminal sessions +- 检测可用 Shell,并为终端选择默认或指定 Shell + - Detect available shells and choose a default or explicit shell +- 在当前项目目录或指定起始目录创建终端 + - Create terminals in the current project or a chosen starting directory +- 执行命令、写入输入并发送中断或其他信号 + - Execute commands, write input, and send interrupt or other signals +- 随终端面板大小变化同步行列尺寸 + - Synchronize terminal rows and columns as the panel resizes +- 查看命令历史并检测 Shell Integration 支持 + - Review command history and detect shell-integration support +- 确认输出接收并安全关闭单个或全部终端 + - Acknowledge output and safely shut down one or all terminals + +## 怎么用 / How to use it + +1. 打开终端 + Open Terminal +2. 确认当前目录 + Confirm the current directory +3. 输入命令;需要时新建额外终端 + Enter a command and create extra terminals as needed + +入口 / Entry: BitFun 功能入口 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 新建终端 / Create terminal | 在当前工作区创建终端。 | Create a terminal in the current workspace. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开一个终端” + - “Open a terminal” +- “切到终端界面” + - “Switch to the terminal” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/feature.voice-input.md b/docs/interactive-capabilities/capabilities/feature.voice-input.md new file mode 100644 index 0000000000..9873faa4ce --- /dev/null +++ b/docs/interactive-capabilities/capabilities/feature.voice-input.md @@ -0,0 +1,67 @@ + +--- +id: feature.voice-input +kind: feature +category: application +title_zh: "语音输入" +title_en: "Voice input" +--- + +# 语音输入 / Voice input + +> 功能 / Feature + +在聊天输入框中录音并转成文字,可选择本地模型、语言、麦克风与最长录音时间。 + +Record speech in the chat composer and transcribe it to text, with control over local models, language, microphone, and duration. + +## 完整功能清单 / Everything included + +- 从聊天输入框开始、结束或取消一次录音 + - Start, finish, or cancel a recording from the chat composer +- 录音过程中分块传输音频并显示识别进度 + - Stream audio chunks during recording and show recognition progress +- 查看本地语音模型及安装、下载、验证、修复和删除状态 + - Browse local speech models and their install, download, verify, repair, and delete states +- 取消正在进行的语音模型下载 + - Cancel an in-progress speech-model download +- 选择自动检测或指定识别语言,并选择系统麦克风 + - Use automatic language detection or choose a language and system microphone +- 在设置页进行麦克风与语音识别测试并查看耗时和错误 + - Test the microphone and speech recognition in Settings, including timing and errors +- 把转写结果放回输入框,在发送前继续编辑 + - Return the transcript to the composer for editing before sending + +## 怎么用 / How to use it + +1. 打开输入设置的“语音”页 + Open the Voice input settings view +2. 启用语音并准备模型 + Enable voice and prepare a model +3. 在聊天输入框点击麦克风开始录音 + Use the microphone button in the chat composer + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开语音输入设置” + - “Open voice-input settings” +- “帮我配置听写功能” + - “Help me configure dictation” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.ai.memory.md b/docs/interactive-capabilities/capabilities/setting.ai.memory.md new file mode 100644 index 0000000000..310842f387 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.ai.memory.md @@ -0,0 +1,74 @@ + +--- +id: setting.ai.memory +kind: setting +category: assistant +title_zh: "记忆设置" +title_en: "Memory settings" +--- + +# 记忆设置 / Memory settings + +> 设置 / Setting + +控制 BitFun 是否从会话中提取和使用长期记忆,以及保留、整理和模型策略。 + +Control whether BitFun extracts and uses long-term memory from sessions, including retention, consolidation, and model policy. + +## 完整功能清单 / Everything included + +- 分别控制长期记忆生成与会话召回,也可一键同时启用 + - Control long-term memory generation and recall independently or enable both together +- 决定 BTW 轻量会话是否参与记忆生成 + - Choose whether lightweight BTW sessions contribute memories +- 存在外部工具上下文时选择清除工具结果、允许或跳过会话 + - When external tool context exists, clear tool results, allow it, or skip the session +- 设置空闲时长、最大年龄、启动处理上限和扫描上限 + - Set idle time, maximum age, startup rollout limit, and scan limit +- 选择记忆提取模型、并发数和单次原始候选上限 + - Choose the extraction model, concurrency, and raw-candidate limit +- 设置未使用记忆的最长保留天数 + - Set how long unused memories are retained +- 选择记忆整理模型并让它跟随主模型或提取模型 + - Choose the consolidation model or make it follow the primary or extraction model +- 打开记忆目录、恢复默认设置或显式清空全部记忆 + - Open the memory directory, restore defaults, or explicitly erase all memories + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“AI > 记忆” + Go to AI > Memory +3. 先启用记忆,再按需要调整高级参数 + Enable memory first, then tune advanced controls if needed + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 启用记忆 / Enable memory | `boolean` | 同时启用记忆生成和召回。 | Enable both memory generation and recall. | +| BTW 会话生成记忆 / Generate memory from BTW sessions | `boolean` | 允许轻量 BTW 会话参与记忆提取。 | Allow lightweight BTW sessions to contribute memories. | +| 外部上下文策略 / External context policy | `clear_tool_results` / `allow` / `skip_session` | 决定存在外部工具上下文时如何生成记忆。 | Choose how memory generation handles external tool context. | +| 每次启动整理上限 / Startup rollout limit | `integer` (0–100) | 每次启动最多处理的待整理记忆批次。 | Maximum pending memory rollouts processed after startup. | + +## 可以直接对 Agent 说 / Try saying + +- “关闭长期记忆” + - “Turn off long-term memory” +- “允许 BTW 会话生成记忆” + - “Allow BTW sessions to generate memories” +- “打开记忆设置” + - “Open Memory settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.ai.models.md b/docs/interactive-capabilities/capabilities/setting.ai.models.md new file mode 100644 index 0000000000..30e28930d2 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.ai.models.md @@ -0,0 +1,75 @@ + +--- +id: setting.ai.models +kind: setting +category: assistant +title_zh: "模型与供应商" +title_en: "Models & providers" +--- + +# 模型与供应商 / Models & providers + +> 设置 / Setting + +添加 AI 供应商和模型,选择默认模型,配置网络代理、订阅与流式超时。 + +Add AI providers and models, choose defaults, and configure proxy, subscription, and streaming timeouts. + +## 完整功能清单 / Everything included + +- 添加、编辑和删除内置或自定义 AI 供应商 + - Add, edit, and remove built-in or custom AI providers +- 配置 API Key、Base URL、请求格式和模型列表 + - Configure API keys, base URLs, request formats, and model lists +- 登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户 + - Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts +- 选择主模型、快速模型以及图像理解、图像生成和语音识别模型 + - Choose primary, fast, image-understanding, image-generation, and speech-recognition models +- 为模型选择推理预设或自定义推理强度 + - Choose reasoning presets or a custom reasoning effort per model +- 配置 AI 请求使用的网络代理与绕过规则 + - Configure network proxies and bypass rules for AI requests +- 设置首 Token 等待和流式空闲超时 + - Set time-to-first-token and streaming idle timeouts +- 查看 models.dev 目录状态、手动刷新并定位本地缓存 + - Inspect models.dev catalog status, refresh it manually, and reveal its local cache +- 为供应商添加自定义 Header、请求体字段与 SSL 行为 + - Add custom headers, request-body fields, and SSL behavior per provider +- 保存前测试供应商或模型连接并刷新运行时客户端 + - Test provider or model connectivity before saving and refresh the runtime client + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“AI > 模型” + Go to AI > Models +3. 添加供应商并测试连接,再选择默认模型 + Add and test a provider, then choose defaults + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开模型设置” + - “Open model settings” +- “带我配置默认模型” + - “Take me to default-model setup” +- “我想检查代理设置” + - “I want to inspect proxy settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.application.appearance.md b/docs/interactive-capabilities/capabilities/setting.application.appearance.md new file mode 100644 index 0000000000..4d06b5812d --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.application.appearance.md @@ -0,0 +1,72 @@ + +--- +id: setting.application.appearance +kind: setting +category: application +title_zh: "外观与语言" +title_en: "Appearance & language" +--- + +# 外观与语言 / Appearance & language + +> 设置 / Setting + +切换主题与语言,调整字体和动效,并安装或导入外观包。 + +Switch themes and languages, tune typography and motion, and install or import appearance packs. + +## 完整功能清单 / Everything included + +- 选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观 + - Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances +- 切换简体中文、繁体中文、英文等受支持界面语言 + - Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages +- 分别调整整个界面与聊天区字号,并支持自定义像素值 + - Adjust global UI and chat font sizes independently, including custom pixel values +- 控制鼠标光效,并让动态背景尊重系统的减少动效偏好 + - Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference +- 导入、预览、应用、导出和删除本地外观包 + - Import, preview, apply, export, and delete local appearance packages +- 浏览、搜索、筛选并安装或更新 Skin 市场外观 + - Browse, search, filter, install, and update appearances from the Skin market +- 提交、查看和撤回自己的外观市场投稿 + - Submit, review, and withdraw your appearance-market submissions +- 在具备权限时查看并批准或拒绝外观投稿 + - When authorized, inspect and approve or reject appearance submissions + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“应用 > 外观” + Go to Application > Appearance +3. 选择主题、语言或外观效果 + Choose a theme, language, or visual effect + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 主题 / Theme | `system` / `bitfun-dark` / `bitfun-light` | 使用系统、BitFun 深色或 BitFun 浅色外观。 | Use the system, BitFun dark, or BitFun light appearance. | +| 界面语言 / Interface language | `en-US` / `zh-CN` / `zh-TW` | 设置 BitFun 的界面语言。 | Set the BitFun interface language. | + +## 可以直接对 Agent 说 / Try saying + +- “切换成深色主题” + - “Switch to the dark theme” +- “把界面语言改成英文” + - “Change the interface language to English” +- “打开外观设置” + - “Open Appearance settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.application.development.md b/docs/interactive-capabilities/capabilities/setting.application.development.md new file mode 100644 index 0000000000..a5b968e432 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.application.development.md @@ -0,0 +1,65 @@ + +--- +id: setting.application.development +kind: setting +category: application +title_zh: "终端与编辑器设置" +title_en: "Terminal & editor settings" +--- + +# 终端与编辑器设置 / Terminal & editor settings + +> 设置 / Setting + +选择默认 Shell,并调整代码编辑器的字体、缩进、换行、格式化与 Minimap。 + +Choose the default shell and tune editor font, indentation, wrapping, formatting, and minimap behavior. + +## 完整功能清单 / Everything included + +- 自动检测并选择默认终端 Shell + - Automatically detect and choose the default terminal shell +- 把终端面板放在右侧或底部 + - Place the terminal panel on the right or at the bottom +- 设置编辑器字体、字重、字号、行高与光标样式 + - Configure editor font, weight, size, line height, and cursor style +- 设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动 + - Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling +- 控制 Minimap、空白字符、当前行高亮和滚动边界 + - Control the minimap, whitespace rendering, current-line highlight, and scroll bounds +- 控制语义高亮、括号配色、保存/粘贴时格式化和空白清理 + - Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“应用 > 开发” + Go to Application > Development +3. 切换“终端”或“编辑器”视图 + Switch between Terminal and Editor + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 编辑器字号 / Editor font size | `integer` (10–32) | 设置代码编辑器的字体大小。 | Set the code editor font size. | + +## 可以直接对 Agent 说 / Try saying + +- “把编辑器字号改成 15” + - “Set the editor font size to 15” +- “打开终端设置” + - “Open terminal settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.application.general.md b/docs/interactive-capabilities/capabilities/setting.application.general.md new file mode 100644 index 0000000000..ebd961aa6c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.application.general.md @@ -0,0 +1,73 @@ + +--- +id: setting.application.general +kind: setting +category: application +title_zh: "常规设置" +title_en: "General settings" +--- + +# 常规设置 / General settings + +> 设置 / Setting + +管理启动、更新、关闭行为、通知与睡眠保持等应用级偏好。 + +Manage app-level preferences for startup, updates, close behavior, notifications, and sleep prevention. + +## 完整功能清单 / Everything included + +- 启用或停用自动检查更新 + - Enable or disable automatic update checks +- 手动检查、下载并安装可用更新,然后按需重启 + - Check for, download, and install an available update manually, then restart when needed +- 控制 BitFun 是否在登录系统后自动启动 + - Choose whether BitFun launches automatically after system sign-in +- 在长任务运行时阻止电脑自动睡眠 + - Prevent the computer from sleeping while long-running work is active +- 选择关闭主窗口时退出、最小化到托盘或每次询问 + - Choose whether closing the main window quits, minimizes to tray, or asks each time +- 分别控制任务完成、权限请求和启动提示通知 + - Control completion, permission-request, and startup-tip notifications independently +- 查看、标记已读、忽略或永久隐藏产品公告与提示 + - Review, mark seen, dismiss, or permanently hide product announcements and tips + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“应用 > 常规” + Go to Application > General +3. 修改开关;变更会自动保存 + Change a control; updates are saved automatically + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 自动检查更新 / Automatic updates | `boolean` | 启动后自动检查可用更新。 | Check for available updates automatically after startup. | +| 关闭按钮行为 / Close button behavior | `ask` / `minimize_to_tray` / `quit` | 选择退出应用或最小化到托盘。 | Choose whether closing quits the app or minimizes it to the tray. | +| 任务完成通知 / Completion notifications | `boolean` | 会话任务完成时发送系统通知。 | Send an OS notification when session work completes. | +| 权限请求通知 / Permission request notifications | `boolean` | Agent 等待权限确认时发送系统通知。 | Send an OS notification when an agent waits for permission. | +| 启动提示 / Startup tips | `boolean` | 启动后显示功能提示。 | Show product tips after startup. | + +## 可以直接对 Agent 说 / Try saying + +- “关闭自动更新” + - “Turn off automatic updates” +- “以后关闭窗口时最小化到托盘” + - “Minimize to tray when I close the window” +- “打开常规设置” + - “Open General settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.application.input.md b/docs/interactive-capabilities/capabilities/setting.application.input.md new file mode 100644 index 0000000000..87b2c7f222 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.application.input.md @@ -0,0 +1,69 @@ + +--- +id: setting.application.input +kind: setting +category: application +title_zh: "输入与快捷键" +title_en: "Input & shortcuts" +--- + +# 输入与快捷键 / Input & shortcuts + +> 设置 / Setting + +配置语音输入、麦克风、识别语言以及键盘快捷键。 + +Configure voice input, microphone, recognition language, and keyboard shortcuts. + +## 完整功能清单 / Everything included + +- 在聊天输入框启用或停用语音输入 + - Enable or disable voice input in the chat composer +- 选择自动检测或中文、粤语、英文、日文等识别语言 + - Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages +- 选择麦克风并执行语音识别测试 + - Choose a microphone and run a speech-recognition test +- 下载、选择、验证、修复或删除本地语音模型 + - Download, select, verify, repair, or delete local speech models +- 设置单次语音输入的最长录音时间 + - Set the maximum duration of one voice-input recording +- 搜索和查看全部应用、场景、编辑器与终端快捷键 + - Search and browse all app, scene, editor, and terminal shortcuts +- 录制新快捷键、检测冲突、恢复单项或重置全部自定义键位 + - Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“应用 > 输入” + Go to Application > Input +3. 切换“语音”或“快捷键”视图 + Switch between Voice and Shortcuts + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 启用语音输入 / Enable voice input | `boolean` | 在聊天输入框显示并启用录音入口。 | Show and enable recording in the chat composer. | +| 默认识别语言 / Default recognition language | `auto` / `zh` / `en` / `ja` / `yue` | 选择自动检测、中文、英文、日文或粤语。 | Choose automatic detection, Chinese, English, Japanese, or Cantonese. | +| 最长录音时间 / Maximum recording duration | `integer` (10–600) | 单次语音输入允许的最长秒数。 | Maximum seconds allowed for one voice input. | + +## 可以直接对 Agent 说 / Try saying + +- “打开快捷键设置” + - “Open keyboard-shortcut settings” +- “把语音输入的默认语言设为中文” + - “Set the voice-input language to Chinese” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.application.pet.md b/docs/interactive-capabilities/capabilities/setting.application.pet.md new file mode 100644 index 0000000000..a41766aad5 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.application.pet.md @@ -0,0 +1,66 @@ + +--- +id: setting.application.pet +kind: setting +category: application +title_zh: "桌面伙伴设置" +title_en: "Companion settings" +--- + +# 桌面伙伴设置 / Companion settings + +> 设置 / Setting + +启用 Agent 伙伴、选择显示位置,并管理当前角色。 + +Enable the agent companion, choose where it appears, and manage the active character. + +## 完整功能清单 / Everything included + +- 整体启用或停用 Agent 伙伴 + - Enable or disable the agent companion +- 控制伙伴是否显示在聊天输入框旁 + - Choose whether the companion appears beside the chat composer +- 控制伙伴是否显示为独立桌面窗口 + - Choose whether the companion appears as a standalone desktop window +- 从内置与已导入角色中选择当前伙伴 + - Choose the active companion from built-in and imported characters +- 导入本地 Petdex 角色包 + - Import a local Petdex character package +- 刷新角色列表并删除不再需要的导入包 + - Refresh the character list and delete imported packages you no longer need + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“应用 > 桌面伙伴” + Go to Application > Companion +3. 选择开关、位置和角色 + Choose its state, location, and character + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 启用桌面伙伴 / Enable companion | `boolean` | 显示或隐藏 Agent 伙伴。 | Show or hide the agent companion. | +| 显示位置 / Display location | `desktop` / `input` | 在桌面或聊天输入框中显示。 | Show on the desktop or in the chat composer. | + +## 可以直接对 Agent 说 / Try saying + +- “关闭桌面伙伴” + - “Turn off the desktop companion” +- “把 Agent 伙伴放到输入框里” + - “Put the agent companion in the composer” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.data.archived.md b/docs/interactive-capabilities/capabilities/setting.data.archived.md new file mode 100644 index 0000000000..27e82566a8 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.data.archived.md @@ -0,0 +1,63 @@ + +--- +id: setting.data.archived +kind: setting +category: data +title_zh: "已归档会话" +title_en: "Archived sessions" +--- + +# 已归档会话 / Archived sessions + +> 设置 / Setting + +查找、恢复或永久删除已归档的会话,管理长期会话历史。 + +Find, restore, or permanently delete archived sessions and manage long-term conversation history. + +## 完整功能清单 / Everything included + +- 按工作区浏览分页归档会话及其元数据 + - Browse paged archived sessions and metadata by workspace +- 按标题、内容和工作区搜索已归档会话 + - Search archived sessions by title, content, and workspace +- 恢复会话、轮次和原工作区视图并取消归档 + - Restore a session, its turns, and original workspace view, then unarchive it +- 明确确认后永久删除选中的归档会话 + - Permanently delete a selected archived session after explicit confirmation +- 明确确认后永久删除全部归档会话 + - Permanently delete all archived sessions after explicit confirmation + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“数据 > 已归档会话” + Go to Data > Archived Sessions +3. 选择会话后恢复或删除 + Choose a session to restore or delete + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开已归档会话” + - “Open archived sessions” +- “带我恢复一个旧会话” + - “Take me to restore an old session” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.data.diagnostics.md b/docs/interactive-capabilities/capabilities/setting.data.diagnostics.md new file mode 100644 index 0000000000..4d8e7319cc --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.data.diagnostics.md @@ -0,0 +1,70 @@ + +--- +id: setting.data.diagnostics +kind: setting +category: data +title_zh: "日志与诊断" +title_en: "Logs & diagnostics" +--- + +# 日志与诊断 / Logs & diagnostics + +> 设置 / Setting + +调整日志级别,查看运行日志路径,并导出用于排查问题的诊断包。 + +Adjust logging level, inspect runtime log locations, and export diagnostic bundles for troubleshooting. + +## 完整功能清单 / Everything included + +- 设置 Trace、Debug、Info、Warn、Error 或关闭后端日志 + - Set backend logging to Trace, Debug, Info, Warn, Error, or Off +- 选择诊断中是否允许包含敏感上下文,并在导出前明确提示 + - Choose whether diagnostics may include sensitive context, with an explicit warning before export +- 查看日志路径并打开日志文件夹 + - Inspect the log path and open the log folder +- 导出包含系统、配置健康和日志信息的诊断包 + - Export a diagnostics bundle containing system, configuration-health, and log information +- 查看上次崩溃、非正常退出、启动恢复和配置恢复信息 + - Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery +- 在开发构建中检查 DevTools 是否可用并打开或关闭 + - In development builds, check DevTools availability and open or close them +- 在开发构建中启用主窗口元素检查并回传选中的元素 + - In development builds, inspect main-window elements and report the selected element + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“数据 > 日志与诊断” + Go to Data > Logs & Diagnostics +3. 选择日志级别,或按需导出诊断包 + Choose a log level or export a bundle when needed + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 日志级别 / Log level | `error` / `warn` / `info` / `debug` / `trace` | 设置后端运行日志的详细程度。 | Set the verbosity of backend runtime logs. | +| 诊断包包含敏感信息 / Include sensitive diagnostics | `boolean` | 仅在明确需要并理解隐私风险时启用。 | Enable only when explicitly needed and after reviewing the privacy risk. | + +## 可以直接对 Agent 说 / Try saying + +- “把日志级别改成 debug” + - “Set the log level to debug” +- “打开诊断设置” + - “Open diagnostics settings” +- “带我导出诊断包” + - “Take me to export a diagnostic bundle” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.data.usage.md b/docs/interactive-capabilities/capabilities/setting.data.usage.md new file mode 100644 index 0000000000..08174ebc5d --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.data.usage.md @@ -0,0 +1,65 @@ + +--- +id: setting.data.usage +kind: setting +category: data +title_zh: "Token 用量" +title_en: "Token usage" +--- + +# Token 用量 / Token usage + +> 设置 / Setting + +查看请求、输入输出 Token、缓存命中和估算成本等使用统计。 + +Inspect request counts, input and output tokens, cache hits, and estimated cost statistics. + +## 完整功能清单 / Everything included + +- 按最近 24 小时、今天、本周、本月或全部时间查看用量 + - Review usage for the last 24 hours, today, this week, this month, or all time +- 按小时或天切换趋势粒度 + - Switch trend granularity between hourly and daily views +- 按供应商、模型或搜索关键词筛选用量 + - Filter usage by provider, model, or search text +- 查看请求数、总 Token、缓存 Token 与缓存命中率 + - View request count, total tokens, cached tokens, and cache-hit rate +- 按模型、供应商组和请求端点比较分布 + - Compare distributions by model, provider group, and request endpoint +- 分别查看输入、输出、缓存创建、缓存读取和命中率趋势 + - Track input, output, cache creation, cache read, and hit-rate trends separately + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“数据 > 用量” + Go to Data > Usage +3. 选择时间范围并查看统计 + Choose a time range and inspect statistics + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Token 用量” + - “Open Token usage” +- “带我查看使用统计” + - “Show me usage statistics” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.tools.acp.md b/docs/interactive-capabilities/capabilities/setting.tools.acp.md new file mode 100644 index 0000000000..0de43d3ee5 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.tools.acp.md @@ -0,0 +1,69 @@ + +--- +id: setting.tools.acp +kind: setting +category: automation +title_zh: "ACP 外部 Agents" +title_en: "ACP external agents" +--- + +# ACP 外部 Agents / ACP external agents + +> 设置 / Setting + +配置通过 Agent Client Protocol 接入的外部 Agent,并检查适配器、命令与会话选项。 + +Configure external agents connected through Agent Client Protocol and inspect adapters, commands, and session options. + +## 完整功能清单 / Everything included + +- 使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设 + - Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others +- 通过 JSON 查看、添加和保存 ACP Agent 配置 + - View, add, and save ACP agent configuration through JSON +- 探测 CLI、适配器、路径、版本、连接与权限要求 + - Probe CLI, adapter, path, version, connection, and permission requirements +- 安装外部 Agent CLI 并预下载 ACP 客户端适配器 + - Install external-agent CLIs and predownload ACP client adapters +- 在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因 + - Detect available external agents in SSH workspaces and show explicit unsupported reasons +- 为 ACP 会话选择模型并修改客户端声明的配置选项 + - Choose an ACP session model and edit client-declared configuration options +- 查看并执行外部 Agent 暴露的会话命令 + - Browse and run session commands exposed by an external agent +- 开始或取消 ACP 对话,并远程回答外部 Agent 权限请求 + - Start or cancel ACP turns and answer external-agent permission requests remotely + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工具 > ACP” + Go to Tools > ACP +3. 添加客户端并通过探测检查可用性 + Add a client and probe its availability + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 ACP 设置” + - “Open ACP settings” +- “带我配置外部 Agent” + - “Take me to external-agent setup” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.tools.automation.md b/docs/interactive-capabilities/capabilities/setting.tools.automation.md new file mode 100644 index 0000000000..66fe02e6a5 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.tools.automation.md @@ -0,0 +1,70 @@ + +--- +id: setting.tools.automation +kind: setting +category: automation +title_zh: "快捷操作与 Hooks" +title_en: "Quick actions & hooks" +--- + +# 快捷操作与 Hooks / Quick actions & hooks + +> 设置 / Setting + +自定义编码后的快捷操作,并配置在 Agent 生命周期事件上运行的 Hooks。 + +Customize post-coding quick actions and configure hooks that run on agent lifecycle events. + +## 完整功能清单 / Everything included + +- 启用和调整内置的提交与创建 Pull Request 快捷操作 + - Enable and tune the built-in Commit and Create Pull Request quick actions +- 添加、编辑和删除自定义编码后快捷操作及 Prompt + - Add, edit, and delete custom post-coding quick actions and prompts +- 整体启用或停用 Agent 生命周期 Hooks + - Enable or disable agent lifecycle hooks globally +- 对可信仓库单独启用项目级 .bitfun/config/hooks.json + - Enable project-level .bitfun/config/hooks.json separately for trusted repositories +- 定位用户级和项目级 Hooks 配置文件并在修改后即时生效 + - Locate user and project hook configuration files and apply edits without restarting +- 在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器 + - Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input +- 查看外部 AI 应用的只读 Hook 目录并选择导入项 + - Inspect read-only external-AI hook catalogs and choose entries to import +- 预览、修改和应用 Hook 导入计划,并保留冲突诊断 + - Preview, edit, and apply hook import plans while retaining conflict diagnostics + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工具 > 自动化” + Go to Tools > Automation +3. 在“快捷操作”或“Hooks”中配置 + Configure Quick Actions or Hooks + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 启用 Hooks / Enable hooks | `boolean` | 允许已配置的 Agent 生命周期 Hooks 运行。 | Allow configured agent lifecycle hooks to run. | +| 启用项目 Hooks / Enable project hooks | `boolean` | 允许当前项目中的 Hooks 配置生效。 | Allow hook configuration from the current project. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Hooks 设置” + - “Open Hooks settings” +- “带我编辑编码后的快捷操作” + - “Take me to post-coding quick actions” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.tools.execution.md b/docs/interactive-capabilities/capabilities/setting.tools.execution.md new file mode 100644 index 0000000000..7836e5d51c --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.tools.execution.md @@ -0,0 +1,84 @@ + +--- +id: setting.tools.execution +kind: setting +category: assistant +title_zh: "执行与权限控制" +title_en: "Execution & permissions" +--- + +# 执行与权限控制 / Execution & permissions + +> 设置 / Setting + +管理 Agent 工具权限、并行度、超时、延迟加载、Computer Use 与浏览器控制。 + +Manage agent tool permissions, concurrency, timeouts, deferred loading, Computer Use, and browser control. + +## 完整功能清单 / Everything included + +- 选择询问、自动批准或完全访问权限模式,并确认高风险警告 + - Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings +- 控制权限模式选择器是否显示在聊天输入框下方 + - Choose whether the permission-mode selector appears below the chat composer +- 创建、排序和保存全局或项目级 Allow、Ask、Deny 规则 + - Create, reorder, and save global or project-level Allow, Ask, and Deny rules +- 查看、撤销或清空项目中记住的权限授权与审计记录 + - Review, revoke, or clear remembered project permission grants and audit records +- 按需延迟加载大型工具定义以减少 Agent 初始上下文 + - Load large tool definitions on demand to reduce initial agent context +- 设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略 + - Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy +- 设置权限确认等待和单次工具执行超时 + - Set permission-confirmation and per-tool execution timeouts +- 设置 Deep Review 最大并行评审者和队列等待时间 + - Set the maximum parallel Deep Review workers and queue wait time +- 启用 Computer Use 并查看辅助功能与屏幕录制权限 + - Enable Computer Use and inspect accessibility and screen-recording permissions +- 选择浏览器、配置默认 CDP 并控制启动时自动连接 + - Choose a browser, configure default CDP, and control automatic connection at startup +- 控制是否在安全边界内修复模型生成的非法工具参数 JSON + - Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工具 > 执行与权限” + Go to Tools > Execution & Permissions +3. 先确认安全影响,再修改权限或执行参数 + Review the security impact before changing permissions or execution controls + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 延迟加载工具 / Deferred tool loading | `boolean` | 按需加载大型工具定义,减少 Agent 初始上下文。 | Load large tool definitions on demand to reduce initial agent context. | +| 子 Agent 批量执行策略 / Subagent batch policy | `safe_only` / `force_parallel` / `serial` | 选择仅安全任务并行、强制并行或串行执行。 | Choose safe-only parallelism, forced parallelism, or serial execution. | +| 子 Agent 最大并发 / Maximum subagent concurrency | `integer` (1–32) | 限制同时运行的子 Agent 数量。 | Limit the number of subagents that may run at once. | +| Swarm 最大并发 / Maximum swarm concurrency | `integer` (1–64) | 限制 Swarm 中同时执行的工作单元。 | Limit concurrent work units inside a swarm. | +| 工具执行超时 / Tool execution timeout | `integer` (1–86400) | 单次工具调用的超时秒数。 | Timeout in seconds for one tool call. | +| Computer Use 桌面控制 / Computer Use | `boolean` | 允许 Agent 使用已授权的桌面控制能力。 | Allow agents to use authorized desktop-control capabilities. | +| 启动时连接浏览器 / Connect browser on startup | `boolean` | BitFun 启动后自动尝试连接浏览器控制。 | Automatically try to connect browser control after BitFun starts. | +| 工具参数 JSON 修复 / Tool-argument JSON repair | `boolean` | 允许在安全边界内修复模型生成的轻微 JSON 格式错误。 | Allow minor model-generated JSON formatting errors to be repaired within the safety boundary. | + +## 可以直接对 Agent 说 / Try saying + +- “启用 Computer Use” + - “Enable Computer Use” +- “把子 Agent 最大并发改为 8” + - “Set maximum subagent concurrency to 8” +- “打开权限设置” + - “Open permission settings” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.tools.mcp.md b/docs/interactive-capabilities/capabilities/setting.tools.mcp.md new file mode 100644 index 0000000000..d4d7fb088a --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.tools.mcp.md @@ -0,0 +1,71 @@ + +--- +id: setting.tools.mcp +kind: setting +category: automation +title_zh: "MCP 服务器" +title_en: "MCP servers" +--- + +# MCP 服务器 / MCP servers + +> 设置 / Setting + +添加和管理 Model Context Protocol 服务器,查看工具、资源、提示词与远程授权状态。 + +Add and manage Model Context Protocol servers, including tools, resources, prompts, and remote authorization state. + +## 完整功能清单 / Everything included + +- 用表单或 JSON 查看和保存全部 MCP 服务器配置 + - View and save all MCP server configuration through forms or JSON +- 添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器 + - Add local-process, remote HTTP/SSE, or container MCP servers +- 启动、停止、重启和删除单个 MCP 服务器 + - Start, stop, restart, and delete individual MCP servers +- 查看初始化、连接、健康、重连、鉴权和失败状态 + - Inspect initialization, connection, health, reconnecting, authentication, and failure states +- 配置远程 Header/环境变量认证或清除已有凭据 + - Configure remote header/environment authentication or clear stored credentials +- 发起、轮询、取消或重新连接远程 MCP OAuth + - Start, poll, cancel, or reconnect remote MCP OAuth +- 查看 MCP 工具、Prompt 列表并读取指定 Prompt + - Browse MCP tools and prompts and load a selected prompt +- 列出、读取和打开 MCP Resources + - List, read, and open MCP resources +- 打开 MCP App/UI、双向发送消息并回答交互请求 + - Open MCP App/UI surfaces, exchange messages, and answer interaction requests + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工具 > MCP” + Go to Tools > MCP +3. 添加服务器并确认其权限与连接状态 + Add a server and review its permissions and connection state + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 MCP 设置” + - “Open MCP settings” +- “带我管理 MCP 服务器” + - “Take me to MCP server management” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.workspace.session.md b/docs/interactive-capabilities/capabilities/setting.workspace.session.md new file mode 100644 index 0000000000..13773c8df9 --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.workspace.session.md @@ -0,0 +1,64 @@ + +--- +id: setting.workspace.session +kind: setting +category: assistant +title_zh: "会话与工作区设置" +title_en: "Session & workspace settings" +--- + +# 会话与工作区设置 / Session & workspace settings + +> 设置 / Setting + +控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。 + +Control session-title generation, accelerated workspace search, and project-context behavior. + +## 完整功能清单 / Everything included + +- 启用或停用根据会话内容自动生成标题 + - Enable or disable automatic titles generated from session content +- 让标题模型继承主模型、快速模型或使用指定模型 + - Make title generation inherit the primary or fast model, or use a selected model +- 为本地工作区启用 Flashgrep 加速搜索 + - Enable Flashgrep-backed accelerated search for local workspaces +- 查看索引状态并在需要时重建工作区索引 + - Inspect index status and rebuild the workspace index when needed +- 远程工作区明确降级搜索实现,不把远程路径回退到本机 + - Use an explicit remote-workspace search path without silently falling back to local files + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工作区 > 会话与工作区” + Go to Workspace > Session & Workspace +3. 调整标题或搜索选项 + Tune title or search controls + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 自动生成会话标题 / Automatic session titles | `boolean` | 根据会话内容生成易识别的标题。 | Generate a recognizable title from session content. | +| 工作区加速搜索 / Accelerated workspace search | `boolean` | 为本地项目启用 Flashgrep 加速搜索。 | Enable Flashgrep-backed search for local projects. | + +## 可以直接对 Agent 说 / Try saying + +- “关闭自动生成会话标题” + - “Turn off automatic session titles” +- “启用工作区加速搜索” + - “Enable accelerated workspace search” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/capabilities/setting.workspace.worktrees.md b/docs/interactive-capabilities/capabilities/setting.workspace.worktrees.md new file mode 100644 index 0000000000..0374c51b6e --- /dev/null +++ b/docs/interactive-capabilities/capabilities/setting.workspace.worktrees.md @@ -0,0 +1,67 @@ + +--- +id: setting.workspace.worktrees +kind: setting +category: workspace +title_zh: "Worktree 设置" +title_en: "Worktree settings" +--- + +# Worktree 设置 / Worktree settings + +> 设置 / Setting + +配置 Git Worktree 的根目录、分支前缀和自动清理规则,并查看现有隔离工作区。 + +Configure the root, branch prefix, and cleanup rules for Git worktrees, and inspect existing isolated workspaces. + +## 完整功能清单 / Everything included + +- 控制新会话是否默认使用独立 Git Worktree + - Choose whether new sessions use isolated Git worktrees by default +- 设置受管 Worktree 的统一根目录 + - Set the common root directory for managed worktrees +- 设置自动创建分支使用的名称前缀 + - Set the branch-name prefix used for automatically created branches +- 创建隔离工作区时选择是否复制当前未提交改动 + - Choose whether current uncommitted changes are copied into a new isolated workspace +- 启用自动清理并设置最多保留的受管 Worktree 数量 + - Enable automatic cleanup and set the maximum number of managed worktrees to retain +- 查看 Worktree 生命周期、脏状态、未发布提交与关联会话 + - Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions +- 打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree + - Open or restore linked sessions and delete or force-delete a worktree after protection checks + +## 怎么用 / How to use it + +1. 打开设置 + Open Settings +2. 进入“工作区 > Worktrees” + Go to Workspace > Worktrees +3. 保存规则或管理现有 Worktree + Save policy or manage existing worktrees + +入口 / Entry: BitFun 设置 + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. | + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. | + +## 可以直接对 Agent 说 / Try saying + +- “打开 Worktree 设置” + - “Open Worktree settings” +- “带我管理并行工作区” + - “Take me to parallel-workspace management” + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. diff --git a/docs/interactive-capabilities/technical/tauri-command-map.json b/docs/interactive-capabilities/technical/tauri-command-map.json new file mode 100644 index 0000000000..37d294e5a9 --- /dev/null +++ b/docs/interactive-capabilities/technical/tauri-command-map.json @@ -0,0 +1,6928 @@ +{ + "schemaVersion": 1, + "generatedFrom": "src/shared/interactive-capabilities/catalog.json", + "catalogDigest": "3207e4dc899c9109f0be952b9497d2f6169f9e2bb3ba9a859dda7e6959903470", + "commandCount": 692, + "commands": [ + { + "id": "accept_file", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "accept_file", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn accept_file( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: AcceptFileRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "accept_operation", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "accept_operation", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn accept_operation( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: GetOperationSummaryRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "accept_session", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "accept_session", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn accept_session( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: AcceptSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "account_auto_sync", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_auto_sync", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_auto_sync( is_first_login: bool, workspace_path: String, config_json: String, sync_operation_id: u64, app_state: State<'_, crate::api::app_state::AppState>, path_manager: State<'_, Arc>, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_cancel_pending_login", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_cancel_pending_login", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_cancel_pending_login( request: PendingAccountLoginRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_connect_devices", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_connect_devices", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_connect_devices() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_delegate_to_paired", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_delegate_to_paired", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_delegate_to_paired(correlation_id: String) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_delete_device", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_delete_device", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_delete_device(targetDeviceId: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_delete_synced_session", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_delete_synced_session", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_delete_synced_session(session_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_device_rpc", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_device_rpc", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_device_rpc( target_device_id: String, command_json: String, timeout_ms: Option, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_execute_on_device", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_execute_on_device", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_execute_on_device( target_device_id: String, session_id: Option, content: String, agent_type: Option, workspace_path: Option, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_export_all_sessions", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_export_all_sessions", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_export_all_sessions( workspace_path: String, app_state: State<'_, crate::api::app_state::AppState>, path_manager: State<'_, Arc>, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_export_local_session", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_export_local_session", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_export_local_session( session_id: String, workspace_path: String, app_state: State<'_, crate::api::app_state::AppState>, path_manager: State<'_, Arc>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_fetch_session_turns", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_fetch_session_turns", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_fetch_session_turns( session_id: String, workspace_path: String, coordinator: State<'_, Arc>, app_state: State<'_, crate::api::app_state::AppState>, path_manager: State<'_, Arc>, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_fetch_settings", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_fetch_settings", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_fetch_settings() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_fetch_synced_sessions", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_fetch_synced_sessions", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_fetch_synced_sessions() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_finalize_login", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_finalize_login", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_finalize_login(request: PendingAccountLoginRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_get_credential_hint", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_get_credential_hint", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_get_credential_hint() -> Option", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_import_remote_sessions", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_import_remote_sessions", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_import_remote_sessions( workspace_path: String, coordinator: State<'_, Arc>, app_state: State<'_, crate::api::app_state::AppState>, path_manager: State<'_, Arc>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_list_devices", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_list_devices", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_list_devices() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_login", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_login", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_login(request: AccountAuthRequest) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_logout", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_logout", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_logout() -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_online_devices", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_online_devices", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_online_devices() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_send_session_to_device", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_send_session_to_device", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_send_session_to_device( target_device_id: String, session_id: String, session_json: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_status", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_status", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_status() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_sync_session", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_sync_session", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_sync_session(session_id: String, session_json: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_sync_settings", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_sync_settings", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_sync_settings(settings_json: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "account_token_expired", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::account_token_expired", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn account_token_expired() -> bool", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "acknowledge_external_ecosystems_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "acknowledge_external_ecosystems_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn acknowledge_external_ecosystems_command( request: AcknowledgeExternalEcosystemsRequest, ) -> ExternalSourceOperationResult<()>", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "activate_session_goal", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::activate_session_goal", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn activate_session_goal( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: ActivateSessionGoalRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "add_skill", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "add_skill", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn add_skill( _state: State<'_, AppState>, source_path: String, level: String, workspace_path: Option, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "appearance_market_browse", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_browse", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_browse( request: AppearanceMarketBrowseRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_download_release", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_download_release", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_download_release( request: AppearanceMarketDownloadRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "appearance_market_get_listing", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_get_listing", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_get_listing( request: AppearanceMarketSlugRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_get_review_submission", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_get_review_submission", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_get_review_submission( request: AppearanceMarketSubmissionIdRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_list_review_submissions", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_list_review_submissions", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_list_review_submissions( ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_list_submissions", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_list_submissions", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_list_submissions() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_review_submission", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_review_submission", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_review_submission( request: AppearanceMarketReviewRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "appearance_market_submit_package", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_submit_package", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_submit_package( request: AppearanceMarketSubmitPackageRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "appearance_market_withdraw_submission", + "moduleId": "appearance_market", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "api::appearance_market_api::appearance_market_withdraw_submission", + "sourceFile": "src/apps/desktop/src/api/appearance_market_api.rs", + "signature": "fn appearance_market_withdraw_submission( request: AppearanceMarketSubmissionIdRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "append_flow_chat_diagnostics", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "append_flow_chat_diagnostics", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn append_flow_chat_diagnostics( _state: State<'_, AppState>, request: AppendFlowChatDiagnosticsRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "apply_external_hook_import_command", + "moduleId": "external_hooks", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "apply_external_hook_import_command", + "sourceFile": "src/apps/desktop/src/api/external_hooks_api.rs", + "signature": "fn apply_external_hook_import_command( request: ApplyExternalHookImportRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "apply_external_mcp_import_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "apply_external_mcp_import_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn apply_external_mcp_import_command( request: ApplyExternalMcpImportRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "apply_external_source_control_action_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "apply_external_source_control_action_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn apply_external_source_control_action_command( request: ExternalSourceControlCommandRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "apply_patch", + "moduleId": "diff", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "apply_patch", + "sourceFile": "src/apps/desktop/src/api/diff_api.rs", + "signature": "fn apply_patch(request: ApplyPatchRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "archive_all_sessions", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "archive_all_sessions", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn archive_all_sessions( request: ArchiveAllSessionsRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "archive_session", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "archive_session", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn archive_session( request: ArchiveSessionRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "browser_control_enable_default_cdp", + "moduleId": "browser_control", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "api::browser_control_api::browser_control_enable_default_cdp", + "sourceFile": "src/apps/desktop/src/api/browser_control_api.rs", + "signature": "fn browser_control_enable_default_cdp( request: BrowserControlLaunchRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_control_get_status", + "moduleId": "browser_control", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "api::browser_control_api::browser_control_get_status", + "sourceFile": "src/apps/desktop/src/api/browser_control_api.rs", + "signature": "fn browser_control_get_status( request: BrowserControlStatusRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_control_launch", + "moduleId": "browser_control", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "api::browser_control_api::browser_control_launch", + "sourceFile": "src/apps/desktop/src/api/browser_control_api.rs", + "signature": "fn browser_control_launch( request: BrowserControlLaunchRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_control_list_browsers", + "moduleId": "browser_control", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "api::browser_control_api::browser_control_list_browsers", + "sourceFile": "src/apps/desktop/src/api/browser_control_api.rs", + "signature": "fn browser_control_list_browsers() -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_control_restart_with_cdp", + "moduleId": "browser_control", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "api::browser_control_api::browser_control_restart_with_cdp", + "sourceFile": "src/apps/desktop/src/api/browser_control_api.rs", + "signature": "fn browser_control_restart_with_cdp( request: BrowserControlLaunchRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_get_url", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_get_url", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_get_url( app: tauri::AppHandle, request: WebviewLabelRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_create", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_create", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_create( app: tauri::AppHandle, request: WebviewCreateRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_eval", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_eval", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_eval( app: tauri::AppHandle, request: WebviewEvalRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_navigate", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_navigate", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_navigate( app: tauri::AppHandle, request: WebviewNavigateRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_reload", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_reload", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_reload( app: tauri::AppHandle, request: WebviewLabelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_set_agent_target_state", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_set_agent_target_state", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_set_agent_target_state( request: BrowserAgentTargetStateRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "browser_webview_set_bounds", + "moduleId": "browser", + "capabilityId": "feature.browser", + "visibility": "implementation", + "rustPath": "api::browser_api::browser_webview_set_bounds", + "sourceFile": "src/apps/desktop/src/api/browser_api.rs", + "signature": "fn browser_webview_set_bounds( app: tauri::AppHandle, request: WebviewBoundsRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "btw_ask_stream", + "moduleId": "btw", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::btw_api::btw_ask_stream", + "sourceFile": "src/apps/desktop/src/api/btw_api.rs", + "signature": "fn btw_ask_stream( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: BtwAskStreamRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "btw_cancel", + "moduleId": "btw", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::btw_api::btw_cancel", + "sourceFile": "src/apps/desktop/src/api/btw_api.rs", + "signature": "fn btw_cancel( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: BtwCancelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "cancel_acp_dialog_turn", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "cancel_acp_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn cancel_acp_dialog_turn( state: State<'_, AppState>, request: CancelAcpDialogTurnRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_dialog_turn", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::cancel_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn cancel_dialog_turn( runtime: State<'_, DesktopRuntimeContext>, app_state: State<'_, AppState>, request: CancelDialogTurnRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_insights_generation", + "moduleId": "insights", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::insights_api::cancel_insights_generation", + "sourceFile": "src/apps/desktop/src/api/insights_api.rs", + "signature": "fn cancel_insights_generation() -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "cancel_mcp_remote_oauth", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::cancel_mcp_remote_oauth", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn cancel_mcp_remote_oauth( state: State<'_, AppState>, request: CancelMCPRemoteOAuthRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_search", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "cancel_search", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn cancel_search( state: State<'_, AppState>, request: CancelSearchRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::cancel_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn cancel_session( runtime: State<'_, DesktopRuntimeContext>, request: CancelSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_subscription_login", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "cancel_subscription_login", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn cancel_subscription_login(request: SubscriptionLoginRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "cancel_tool", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::cancel_tool", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn cancel_tool( coordinator: State<'_, Arc>, request: CancelToolRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cancel_transfer", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::cancel_transfer", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn cancel_transfer( state: State<'_, AppState>, transfer_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "canonicalize_agent_profile_configs", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::config_api::canonicalize_agent_profile_configs", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn canonicalize_agent_profile_configs( _state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "check_command_exists", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "check_command_exists", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn check_command_exists(command: String) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "check_commands_exist", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "check_commands_exist", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn check_commands_exist( commands: Vec, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "check_for_updates", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "check_for_updates", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn check_for_updates( app: AppHandle, request: CheckForUpdatesRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "check_git_isolation", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "check_git_isolation", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn check_git_isolation( request: SnapshotWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "check_path_exists", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "check_path_exists", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn check_path_exists( state: State<'_, AppState>, request: CheckPathExistsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "choose_external_mcp_conflict_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "choose_external_mcp_conflict_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn choose_external_mcp_conflict_command( request: ChooseExternalMcpConflictRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "choose_external_subagent_conflict_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "choose_external_subagent_conflict_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn choose_external_subagent_conflict_command( request: ChooseExternalSubagentConflictRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "cleanup_invalid_workspaces", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "cleanup_invalid_workspaces", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn cleanup_invalid_workspaces( state: State<'_, AppState>, app: tauri::AppHandle, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cleanup_storage", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "cleanup_storage", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn cleanup_storage(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "cleanup_storage_with_policy", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "cleanup_storage_with_policy", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn cleanup_storage_with_policy( state: State<'_, AppState>, policy: CleanupPolicy, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "clear_mcp_remote_auth", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "clear_mcp_remote_auth", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn clear_mcp_remote_auth( state: State<'_, AppState>, request: ClearMCPRemoteAuthRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "clear_project_permission_grants", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::clear_project_permission_grants", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn clear_project_permission_grants( state: State<'_, AppState>, runtime: State<'_, DesktopRuntimeContext>, request: PermissionProjectRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "clear_session_thread_goal", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::clear_session_thread_goal", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn clear_session_thread_goal( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: ClearSessionThreadGoalRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "close_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "close_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn close_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: CloseWorkspaceRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "compact_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::compact_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn compact_session( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: CompactSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "compress_path", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "compress_path", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn compress_path( state: State<'_, AppState>, request: CompressPathRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "compute_diff", + "moduleId": "diff", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "compute_diff", + "sourceFile": "src/apps/desktop/src/api/diff_api.rs", + "signature": "fn compute_diff(request: ComputeDiffRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "computer_use_get_status", + "moduleId": "computer_use", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "computer_use_get_status", + "sourceFile": "src/apps/desktop/src/api/computer_use_api.rs", + "signature": "fn computer_use_get_status( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "computer_use_open_system_settings", + "moduleId": "computer_use", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "computer_use_open_system_settings", + "sourceFile": "src/apps/desktop/src/api/computer_use_api.rs", + "signature": "fn computer_use_open_system_settings( request: ComputerUseOpenSettingsRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "computer_use_request_permissions", + "moduleId": "computer_use", + "capabilityId": "feature.computer-use", + "visibility": "implementation", + "rustPath": "computer_use_request_permissions", + "sourceFile": "src/apps/desktop/src/api/computer_use_api.rs", + "signature": "fn computer_use_request_permissions() -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "control_background_command", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::control_background_command", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn control_background_command( coordinator: State<'_, Arc>, request: ControlBackgroundCommandRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "control_deep_review_queue", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::control_deep_review_queue", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn control_deep_review_queue( request: ControlDeepReviewQueueRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_acp_flow_session", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "create_acp_flow_session", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn create_acp_flow_session( state: State<'_, AppState>, app_handle: AppHandle, request: CreateAcpFlowSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_assistant_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "create_assistant_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn create_assistant_workspace( state: State<'_, AppState>, app: tauri::AppHandle, _request: CreateAssistantWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_cron_job", + "moduleId": "cron", + "capabilityId": "feature.tasks-automation", + "visibility": "implementation", + "rustPath": "create_cron_job", + "sourceFile": "src/apps/desktop/src/api/cron_api.rs", + "signature": "fn create_cron_job(request: CreateCronJobRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_custom_agent", + "moduleId": "custom_agent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "create_custom_agent", + "sourceFile": "src/apps/desktop/src/api/custom_agent_api.rs", + "signature": "fn create_custom_agent( state: State<'_, AppState>, request: CreateCustomAgentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_directory", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "create_directory", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn create_directory( state: State<'_, AppState>, request: CreateDirectoryRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_file", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "create_file", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn create_file( state: State<'_, AppState>, request: CreateFileRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_miniapp", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::create_miniapp", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn create_miniapp( state: State<'_, AppState>, request: CreateMiniAppRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::create_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn create_session( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, runtime: State<'_, DesktopRuntimeContext>, mut request: CreateSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "create_subagent", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "create_subagent", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn create_subagent( state: State<'_, AppState>, request: CreateSubagentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "debug_close_devtools", + "moduleId": "debug", + "capabilityId": "setting.data.diagnostics", + "visibility": "implementation", + "rustPath": "api::debug_api::debug_close_devtools", + "sourceFile": "src/apps/desktop/src/api/debug_api.rs", + "signature": "fn debug_close_devtools(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "debug_devtools_available", + "moduleId": "debug", + "capabilityId": "setting.data.diagnostics", + "visibility": "implementation", + "rustPath": "api::debug_api::debug_devtools_available", + "sourceFile": "src/apps/desktop/src/api/debug_api.rs", + "signature": "fn debug_devtools_available() -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "debug_element_picked", + "moduleId": "debug", + "capabilityId": "setting.data.diagnostics", + "visibility": "implementation", + "rustPath": "api::debug_api::debug_element_picked", + "sourceFile": "src/apps/desktop/src/api/debug_api.rs", + "signature": "fn debug_element_picked(request: DebugElementPickedRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "debug_open_devtools", + "moduleId": "debug", + "capabilityId": "setting.data.diagnostics", + "visibility": "implementation", + "rustPath": "api::debug_api::debug_open_devtools", + "sourceFile": "src/apps/desktop/src/api/debug_api.rs", + "signature": "fn debug_open_devtools(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "decompress_path", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "decompress_path", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn decompress_path( state: State<'_, AppState>, request: DecompressPathRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "delete_agent_companion_pet_package", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "delete_agent_companion_pet_package", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn delete_agent_companion_pet_package( state: State<'_, AppState>, request: DeleteAgentCompanionPetPackageRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_all_archived_sessions", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "delete_all_archived_sessions", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn delete_all_archived_sessions( request: DeleteAllArchivedSessionsRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_assistant_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "delete_assistant_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn delete_assistant_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: DeleteAssistantWorkspaceRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_cron_job", + "moduleId": "cron", + "capabilityId": "feature.tasks-automation", + "visibility": "implementation", + "rustPath": "delete_cron_job", + "sourceFile": "src/apps/desktop/src/api/cron_api.rs", + "signature": "fn delete_cron_job(request: DeleteCronJobRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_custom_agent", + "moduleId": "custom_agent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "delete_custom_agent", + "sourceFile": "src/apps/desktop/src/api/custom_agent_api.rs", + "signature": "fn delete_custom_agent( state: State<'_, AppState>, request: DeleteCustomAgentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_directory", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "delete_directory", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn delete_directory( state: State<'_, AppState>, request: DeleteDirectoryRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_file", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "delete_file", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn delete_file( state: State<'_, AppState>, request: DeleteFileRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_mcp_server", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::delete_mcp_server", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn delete_mcp_server( state: State<'_, AppState>, request: DeleteMCPServerRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_miniapp", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::delete_miniapp", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn delete_miniapp(state: State<'_, AppState>, app_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_persisted_session", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "delete_persisted_session", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn delete_persisted_session( request: DeletePersistedSessionRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::delete_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn delete_session( runtime: State<'_, DesktopRuntimeContext>, request: DeleteSessionRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_skill", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "delete_skill", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn delete_skill( state: State<'_, AppState>, skill_key: String, workspace_path: Option, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "delete_subagent", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "delete_subagent", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn delete_subagent( state: State<'_, AppState>, request: DeleteSubagentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "dismiss_announcement", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::dismiss_announcement", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn dismiss_announcement( state: State<'_, AppState>, request: AnnouncementIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_answer", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_answer", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_answer( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchAnswerRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_append", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_append", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_append( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchAppendRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_cancel", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_cancel", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_cancel( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchJobRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_continue", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_continue", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_continue( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchContinueRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_install_cli_cancel", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_install_cli_cancel", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_install_cli_cancel( state: State<'_, AppState>, request: DispatchConnectionRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_install_cli_poll", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_install_cli_poll", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_install_cli_poll( state: State<'_, AppState>, request: DispatchInstallPollRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_install_cli_start", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_install_cli_start", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_install_cli_start( state: State<'_, AppState>, request: DispatchInstallStartRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_list_jobs", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_list_jobs", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_list_jobs( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchListJobsRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_list_targets", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_list_targets", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_list_targets( state: State<'_, AppState>, request: DispatchListTargetsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_load_transcript", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_load_transcript", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_load_transcript( path_manager: State<'_, Arc>, request: DispatchTranscriptRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_probe_target", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_probe_target", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_probe_target( state: State<'_, AppState>, request: DispatchProbeTargetRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_provision_target", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_provision_target", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_provision_target( state: State<'_, AppState>, request: DispatchConnectionRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_query", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_query", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_query( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchQueryJobRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_save_transcript", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_save_transcript", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_save_transcript( path_manager: State<'_, Arc>, request: DispatchSaveTranscriptRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_status", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_status", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_status( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchStatusRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_submit", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_submit", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_submit( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchSubmitRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_sync_model_config", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_sync_model_config", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_sync_model_config( state: State<'_, AppState>, request: DispatchConnectionRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "dispatch_sync_result", + "moduleId": "dispatch", + "capabilityId": "feature.detached-dispatch", + "visibility": "implementation", + "rustPath": "api::dispatch_api::dispatch_sync_result", + "sourceFile": "src/apps/desktop/src/api/dispatch_api.rs", + "signature": "fn dispatch_sync_result( state: State<'_, AppState>, path_manager: State<'_, Arc>, request: DispatchSyncResultRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "download_skill_market", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "download_skill_market", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn download_skill_market( _state: State<'_, AppState>, request: SkillMarketDownloadRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "editor_ai_cancel", + "moduleId": "editor_ai", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::editor_ai_api::editor_ai_cancel", + "sourceFile": "src/apps/desktop/src/api/editor_ai_api.rs", + "signature": "fn editor_ai_cancel( state: State<'_, AppState>, request: EditorAiCancelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "editor_ai_stream", + "moduleId": "editor_ai", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::editor_ai_api::editor_ai_stream", + "sourceFile": "src/apps/desktop/src/api/editor_ai_api.rs", + "signature": "fn editor_ai_stream( app: AppHandle, state: State<'_, AppState>, request: EditorAiStreamRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "ensure_assistant_bootstrap", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::ensure_assistant_bootstrap", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn ensure_assistant_bootstrap( coordinator: State<'_, Arc>, request: EnsureAssistantBootstrapRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "ensure_coordinator_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::ensure_coordinator_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn ensure_coordinator_session( runtime: State<'_, DesktopRuntimeContext>, request: EnsureCoordinatorSessionRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "execute_tool", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "execute_tool", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn execute_tool(request: ToolExecutionRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "expand_external_prompt_command_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "expand_external_prompt_command_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn expand_external_prompt_command_command( request: ExpandExternalPromptCommandRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "explorer_get_children", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "explorer_get_children", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn explorer_get_children( state: State<'_, AppState>, request: ExplorerGetChildrenRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "explorer_get_children_paginated", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "explorer_get_children_paginated", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn explorer_get_children_paginated( state: State<'_, AppState>, request: ExplorerGetChildrenPaginatedRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "explorer_get_file_tree", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "explorer_get_file_tree", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn explorer_get_file_tree( state: State<'_, AppState>, request: ExplorerGetFileTreeRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "export_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "export_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn export_config(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "export_diagnostics_bundle", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "export_diagnostics_bundle", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn export_diagnostics_bundle( _state: State<'_, AppState>, _request: ExportDiagnosticsBundleRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "export_local_file_to_path", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "export_local_file_to_path", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn export_local_file_to_path(request: ExportLocalFileRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "export_session_transcript", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "export_session_transcript", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn export_session_transcript( request: ExportSessionTranscriptRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "fetch_mcp_app_resource", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "fetch_mcp_app_resource", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn fetch_mcp_app_resource( state: State<'_, AppState>, request: FetchMCPAppResourceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "fork_session", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "fork_session", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn fork_session( request: ForkSessionRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "generate_commit_message", + "moduleId": "git_agent", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "generate_commit_message", + "sourceFile": "src/apps/desktop/src/api/git_agent_api.rs", + "signature": "fn generate_commit_message( app_state: State<'_, AppState>, request: GenerateCommitMessageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "generate_insights", + "moduleId": "insights", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::insights_api::generate_insights", + "sourceFile": "src/apps/desktop/src/api/insights_api.rs", + "signature": "fn generate_insights(request: GenerateInsightsRequest) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "generate_session_title", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::generate_session_title", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn generate_session_title( coordinator: State<'_, Arc>, request: GenerateSessionTitleRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_acp_clients", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "get_acp_clients", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn get_acp_clients(state: State<'_, AppState>) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_acp_session_commands", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "get_acp_session_commands", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn get_acp_session_commands( state: State<'_, AppState>, request: GetAcpSessionOptionsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_acp_session_options", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "get_acp_session_options", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn get_acp_session_options( state: State<'_, AppState>, request: GetAcpSessionOptionsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_agent_profile_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_agent_profile_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_agent_profile_config( _state: State<'_, AppState>, agent_id: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_agent_profile_configs", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_agent_profile_configs", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_agent_profile_configs(_state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_ai_model_catalog", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_ai_model_catalog", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_ai_model_catalog() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_all_modified_files", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_all_modified_files", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_all_modified_files( runtime: State<'_, DesktopRuntimeContext>, request: GetAllModifiedFilesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_all_tools_info", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "get_all_tools_info", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn get_all_tools_info() -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_announcement_tips", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::get_announcement_tips", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn get_announcement_tips( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_app_state", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_app_state", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_app_state(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_app_version", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_app_version", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn get_app_version( app: AppHandle, request: GetAppVersionRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_available_modes", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_available_modes", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_available_modes( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: Option, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_available_tools", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_available_tools", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_available_tools(state: State<'_, AppState>) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_baseline_snapshot_diff", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_baseline_snapshot_diff", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_baseline_snapshot_diff( request: GetBaselineSnapshotDiffRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_clipboard_files", + "moduleId": "clipboard_file", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_clipboard_files", + "sourceFile": "src/apps/desktop/src/api/clipboard_file_api.rs", + "signature": "fn get_clipboard_files() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_config( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: GetConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_configs", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_configs", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_configs( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: GetConfigsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_current_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_current_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_current_workspace( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_custom_agent_detail", + "moduleId": "custom_agent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "get_custom_agent_detail", + "sourceFile": "src/apps/desktop/src/api/custom_agent_api.rs", + "signature": "fn get_custom_agent_detail( state: State<'_, AppState>, request: GetCustomAgentDetailRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_default_review_team_definition", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_default_review_team_definition", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_default_review_team_definition() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_directory_children", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_directory_children", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_directory_children( state: State<'_, AppState>, request: GetDirectoryChildrenRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "get_directory_children_paginated", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_directory_children_paginated", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_directory_children_paginated( state: State<'_, AppState>, request: GetDirectoryChildrenPaginatedRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "get_external_ecosystem_awareness_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_external_ecosystem_awareness_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn get_external_ecosystem_awareness_command( request: ExternalEcosystemAwarenessRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_external_hook_catalog", + "moduleId": "external_hooks", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_external_hook_catalog", + "sourceFile": "src/apps/desktop/src/api/external_hooks_api.rs", + "signature": "fn get_external_hook_catalog( request: ExternalHookCatalogRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_external_hook_import_snapshot", + "moduleId": "external_hooks", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_external_hook_import_snapshot", + "sourceFile": "src/apps/desktop/src/api/external_hooks_api.rs", + "signature": "fn get_external_hook_import_snapshot( request: ExternalHookImportSnapshotRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_external_source_control_snapshot", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_external_source_control_snapshot", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn get_external_source_control_snapshot( request: ExternalSourceSnapshotRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_external_source_snapshot", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_external_source_snapshot", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn get_external_source_snapshot( request: ExternalSourceSnapshotRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_file_change_history", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_file_change_history", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_file_change_history( runtime: State<'_, DesktopRuntimeContext>, request: GetFileChangeHistoryRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_file_diff", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_file_diff", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_file_diff( runtime: State<'_, DesktopRuntimeContext>, request: GetFileDiffRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_file_editor_sync_hash", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_file_editor_sync_hash", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_file_editor_sync_hash( state: State<'_, AppState>, request: GetFileMetadataRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_file_metadata", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_file_metadata", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_file_metadata( state: State<'_, AppState>, request: GetFileMetadataRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_file_tree", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_file_tree", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_file_tree( state: State<'_, AppState>, request: GetFileTreeRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_global_config_health", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_global_config_health", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_global_config_health() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_global_config_status", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_global_config_status", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_global_config_status() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_global_skill_settings", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "get_global_skill_settings", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn get_global_skill_settings() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_health_status", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_health_status", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_health_status( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_latest_insights", + "moduleId": "insights", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::insights_api::get_latest_insights", + "sourceFile": "src/apps/desktop/src/api/insights_api.rs", + "signature": "fn get_latest_insights() -> Result, String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "get_mcp_prompt", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::get_mcp_prompt", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn get_mcp_prompt( state: State<'_, AppState>, request: GetMCPPromptRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_mcp_remote_oauth_session", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::get_mcp_remote_oauth_session", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn get_mcp_remote_oauth_session( state: State<'_, AppState>, request: GetMCPRemoteOAuthSessionRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_mcp_server_status", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "get_mcp_server_status", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn get_mcp_server_status( state: State<'_, AppState>, server_id: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_mcp_servers", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "get_mcp_servers", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn get_mcp_servers(state: State<'_, AppState>) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_mcp_tool_ui_uri", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "get_mcp_tool_ui_uri", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn get_mcp_tool_ui_uri( _state: State<'_, AppState>, tool_name: String, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_memory_paths", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_memory_paths", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_memory_paths(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_miniapp", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::get_miniapp", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn get_miniapp( state: State<'_, AppState>, request: GetMiniAppRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_miniapp_draft_storage", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::get_miniapp_draft_storage", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn get_miniapp_draft_storage( state: State<'_, AppState>, request: MiniAppDraftStorageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_miniapp_storage", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::get_miniapp_storage", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn get_miniapp_storage( state: State<'_, AppState>, app_id: String, key: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_miniapp_versions", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::get_miniapp_versions", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn get_miniapp_versions( state: State<'_, AppState>, app_id: String, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_mode_skill_configs", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "get_mode_skill_configs", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn get_mode_skill_configs( state: State<'_, AppState>, mode_id: String, force_refresh: Option, workspace_path: Option, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_model_configs", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_model_configs", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_model_configs( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_models_dev_catalog_status", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_models_dev_catalog_status", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_models_dev_catalog_status() -> bitfun_core_types::ModelsDevCatalogStatus", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "get_native_prompt_command_conflicts_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_native_prompt_command_conflicts_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn get_native_prompt_command_conflicts_command( request: NativePromptCommandConflictsRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "get_opened_workspaces", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_opened_workspaces", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_opened_workspaces( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_operation_diff", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_operation_diff", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_operation_diff( runtime: State<'_, DesktopRuntimeContext>, request: GetOperationDiffRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_operation_summary", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_operation_summary", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_operation_summary( runtime: State<'_, DesktopRuntimeContext>, request: GetOperationSummaryRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_pending_announcements", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::get_pending_announcements", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn get_pending_announcements( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_prevent_sleep_enabled", + "moduleId": "sleep_prevention", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "sleep_prevention::get_prevent_sleep_enabled", + "sourceFile": "src/apps/desktop/src/sleep_prevention.rs", + "signature": "fn get_prevent_sleep_enabled( app_state: State<'_, AppState>, sleep_prevention: State<'_, SleepPreventionState>, request: GetPreventSleepEnabledRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "get_primary_assistant_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_primary_assistant_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_primary_assistant_workspace( state: State<'_, AppState>, _request: GetPrimaryAssistantWorkspaceRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_project_permission_rules", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_project_permission_rules", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_project_permission_rules( state: State<'_, AppState>, request: PermissionProjectRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "get_project_storage_paths", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_project_storage_paths", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn get_project_storage_paths( state: State<'_, AppState>, workspace_path: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_readonly_tools_info", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "get_readonly_tools_info", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn get_readonly_tools_info() -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_recent_workspaces", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_recent_workspaces", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_recent_workspaces( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_runtime_capabilities", + "moduleId": "runtime", + "capabilityId": null, + "visibility": "internal", + "rustPath": "get_runtime_capabilities", + "sourceFile": "src/apps/desktop/src/api/runtime_api.rs", + "signature": "fn get_runtime_capabilities( _state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_runtime_logging_info", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_runtime_logging_info", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn get_runtime_logging_info( startup_trace: State<'_, DesktopStartupTrace>, _state: State<'_, AppState>, _request: GetRuntimeLoggingInfoRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_file_diff_stats", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_session_file_diff_stats", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_session_file_diff_stats( runtime: State<'_, DesktopRuntimeContext>, request: GetSessionFileDiffStatsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_files", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_session_files", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_session_files( runtime: State<'_, DesktopRuntimeContext>, request: GetSessionFilesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_lineage", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "get_session_lineage", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn get_session_lineage( request: GetSessionLineageRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "get_session_operations", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_session_operations", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_session_operations( runtime: State<'_, DesktopRuntimeContext>, request: GetSessionFilesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_permission_mode", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_session_permission_mode", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_session_permission_mode( runtime: State<'_, DesktopRuntimeContext>, coordinator: State<'_, Arc>, request: UpdateSessionPermissionModeRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "get_session_stats", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_session_stats", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_session_stats( runtime: State<'_, DesktopRuntimeContext>, request: GetSessionStatsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_thread_goal", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::get_session_thread_goal", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn get_session_thread_goal( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: GetSessionThreadGoalRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_turns", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_session_turns", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_session_turns( runtime: State<'_, DesktopRuntimeContext>, request: GetSessionTurnsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_session_usage_report", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "get_session_usage_report", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn get_session_usage_report( request: GetSessionUsageReportRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_skill_configs", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "get_skill_configs", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn get_skill_configs( state: State<'_, AppState>, force_refresh: Option, workspace_path: Option, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_snapshot_sessions", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_snapshot_sessions", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_snapshot_sessions( request: SnapshotWorkspaceRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_snapshot_system_stats", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_snapshot_system_stats", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_snapshot_system_stats( request: SnapshotWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_startup_native_trace", + "moduleId": "lib", + "capabilityId": null, + "visibility": "internal", + "rustPath": "get_startup_native_trace", + "sourceFile": "src/apps/desktop/src/lib.rs", + "signature": "fn get_startup_native_trace( state: tauri::State<'_, DesktopStartupTrace>, ) -> DesktopStartupTraceSnapshot", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_statistics", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_statistics", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_statistics( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_storage_paths", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_storage_paths", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn get_storage_paths(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_storage_statistics", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_storage_statistics", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn get_storage_statistics(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_subagent_detail", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "get_subagent_detail", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn get_subagent_detail( state: State<'_, AppState>, request: GetSubagentDetailRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_subscription_login_status", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_subscription_login_status", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_subscription_login_status( request: SubscriptionLoginRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "get_system_info", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "get_system_info", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn get_system_info() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_token_usage_statistics", + "moduleId": "token_usage", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::token_usage_api::get_token_usage_statistics", + "sourceFile": "src/apps/desktop/src/api/token_usage_api.rs", + "signature": "fn get_token_usage_statistics( request: TokenUsageStatisticsRequest, state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "get_tool_info", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "get_tool_info", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn get_tool_info(request: GetToolInfoRequest) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_turn_files", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "get_turn_files", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn get_turn_files( runtime: State<'_, DesktopRuntimeContext>, request: GetTurnFilesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_watched_paths", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "get_watched_paths", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn get_watched_paths() -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "get_workspace_reference_snapshot", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "get_workspace_reference_snapshot", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn get_workspace_reference_snapshot( state: State<'_, AppState>, request: WorkspaceReferenceSnapshotRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "git_add_files", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_add_files", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_add_files( state: State<'_, AppState>, request: GitAddFilesRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_add_worktree", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_add_worktree", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_add_worktree( state: State<'_, AppState>, request: GitAddWorktreeRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "git_checkout_branch", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_checkout_branch", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_checkout_branch( state: State<'_, AppState>, request: GitCheckoutBranchRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_cherry_pick", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_cherry_pick", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_cherry_pick( state: State<'_, AppState>, request: GitCherryPickRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_cherry_pick_abort", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_cherry_pick_abort", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_cherry_pick_abort( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_cherry_pick_continue", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_cherry_pick_continue", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_cherry_pick_continue( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_commit", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_commit", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_commit( state: State<'_, AppState>, request: GitCommitRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_create_branch", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_create_branch", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_create_branch( state: State<'_, AppState>, request: GitCreateBranchRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_delete_branch", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_delete_branch", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_delete_branch( state: State<'_, AppState>, request: GitDeleteBranchRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_branches", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_branches", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_branches( state: State<'_, AppState>, request: GitBranchesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_changed_files", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_changed_files", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_changed_files( state: State<'_, AppState>, request: GitChangedFilesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_commits", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_commits", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_commits( state: State<'_, AppState>, request: GitCommitsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_diff", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_diff", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_diff( state: State<'_, AppState>, request: GitDiffRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_enhanced_branches", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_enhanced_branches", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_enhanced_branches( state: State<'_, AppState>, request: GitBranchesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_file_content", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_file_content", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_file_content( state: State<'_, AppState>, request: GitGetFileContentRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_graph", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_graph", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_graph( _state: State<'_, AppState>, repository_path: String, max_count: Option, branch_name: Option, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "git_get_repository", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_repository", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_repository( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_repository_basic", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_repository_basic", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_repository_basic( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_repository_trust", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_repository_trust", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_repository_trust( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_get_status", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_get_status", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_get_status( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_is_repository", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_is_repository", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_is_repository( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_list_worktrees", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_list_worktrees", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_list_worktrees( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "git_pull", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_pull", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_pull( state: State<'_, AppState>, request: GitPullRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_push", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_push", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_push( state: State<'_, AppState>, request: GitPushRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_remove_worktree", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_remove_worktree", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_remove_worktree( state: State<'_, AppState>, request: GitRemoveWorktreeRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "git_reset_files", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_reset_files", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_reset_files( state: State<'_, AppState>, request: GitResetFilesRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_reset_to_commit", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_reset_to_commit", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_reset_to_commit( state: State<'_, AppState>, request: GitResetToCommitRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_resolve_revision", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_resolve_revision", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_resolve_revision( state: State<'_, AppState>, request: GitResolveRevisionRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "git_trust_repository", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "git_trust_repository", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn git_trust_repository( state: State<'_, AppState>, request: GitRepositoryRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "grant_miniapp_path", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::grant_miniapp_path", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn grant_miniapp_path( state: State<'_, AppState>, app_id: String, path: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "grant_miniapp_workspace", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::grant_miniapp_workspace", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn grant_miniapp_workspace( state: State<'_, AppState>, app_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "has_insights_data", + "moduleId": "insights", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::insights_api::has_insights_data", + "sourceFile": "src/apps/desktop/src/api/insights_api.rs", + "signature": "fn has_insights_data(request: GenerateInsightsRequest) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "hide_agent_companion_desktop_pet", + "moduleId": "appearance", + "capabilityId": "feature.desktop-pet", + "visibility": "implementation", + "rustPath": "appearance::hide_agent_companion_desktop_pet", + "sourceFile": "src/apps/desktop/src/appearance.rs", + "signature": "fn hide_agent_companion_desktop_pet(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "hide_main_window_after_close_request", + "moduleId": "lib", + "capabilityId": null, + "visibility": "internal", + "rustPath": "hide_main_window_after_close_request", + "sourceFile": "src/apps/desktop/src/lib.rs", + "signature": "fn hide_main_window_after_close_request(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "i18n_get_config", + "moduleId": "i18n", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "i18n_get_config", + "sourceFile": "src/apps/desktop/src/api/i18n_api.rs", + "signature": "fn i18n_get_config(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "i18n_get_current_language", + "moduleId": "i18n", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "i18n_get_current_language", + "sourceFile": "src/apps/desktop/src/api/i18n_api.rs", + "signature": "fn i18n_get_current_language(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "i18n_get_supported_languages", + "moduleId": "i18n", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "i18n_get_supported_languages", + "sourceFile": "src/apps/desktop/src/api/i18n_api.rs", + "signature": "fn i18n_get_supported_languages() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "i18n_set_config", + "moduleId": "i18n", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "i18n_set_config", + "sourceFile": "src/apps/desktop/src/api/i18n_api.rs", + "signature": "fn i18n_set_config(state: State<'_, AppState>, config: Value) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "i18n_set_language", + "moduleId": "i18n", + "capabilityId": "setting.application.appearance", + "visibility": "implementation", + "rustPath": "i18n_set_language", + "sourceFile": "src/apps/desktop/src/api/i18n_api.rs", + "signature": "fn i18n_set_language( state: State<'_, AppState>, _app: tauri::AppHandle, request: SetLanguageRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "import_agent_companion_pet_package", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "import_agent_companion_pet_package", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn import_agent_companion_pet_package( state: State<'_, AppState>, request: ImportAgentCompanionPetPackageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "import_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "import_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn import_config( state: State<'_, AppState>, request: ImportConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_acp_clients", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "initialize_acp_clients", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn initialize_acp_clients( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_ai", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "initialize_ai", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn initialize_ai(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_mcp_servers", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "initialize_mcp_servers", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn initialize_mcp_servers( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_mcp_servers_non_destructive", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::initialize_mcp_servers_non_destructive", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn initialize_mcp_servers_non_destructive( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_project_storage", + "moduleId": "storage_commands", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "initialize_project_storage", + "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", + "signature": "fn initialize_project_storage( state: State<'_, AppState>, workspace_path: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_snapshot", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "initialize_snapshot", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn initialize_snapshot( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: SnapshotInitRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "initialize_tray_after_startup", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::initialize_tray_after_startup", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn initialize_tray_after_startup( app: tauri::AppHandle, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "initialize_workspace_startup_state", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "initialize_workspace_startup_state", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn initialize_workspace_startup_state( state: State<'_, AppState>, app: tauri::AppHandle, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "install_acp_client_cli", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "install_acp_client_cli", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn install_acp_client_cli( state: State<'_, AppState>, request: AcpClientIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "install_update", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "install_update", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn install_update(app: AppHandle, request: InstallUpdateRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "interrupt_dialog_turn", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::interrupt_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn interrupt_dialog_turn( runtime: State<'_, DesktopRuntimeContext>, request: CancelDialogTurnRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "list_agent_companion_pets", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "list_agent_companion_pets", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn list_agent_companion_pets( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_agent_tool_names", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "list_agent_tool_names", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn list_agent_tool_names(state: State<'_, AppState>) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_ai_models_by_config", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "list_ai_models_by_config", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn list_ai_models_by_config( state: State<'_, AppState>, request: ListAIModelsByConfigRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_archived_sessions", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "list_archived_sessions", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn list_archived_sessions( request: ListPersistedSessionsRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_background_command_activities", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::list_background_command_activities", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn list_background_command_activities( request: ListBackgroundCommandActivitiesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_cron_jobs", + "moduleId": "cron", + "capabilityId": "feature.tasks-automation", + "visibility": "implementation", + "rustPath": "list_cron_jobs", + "sourceFile": "src/apps/desktop/src/api/cron_api.rs", + "signature": "fn list_cron_jobs(request: ListCronJobsRequest) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_directory_files", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "list_directory_files", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn list_directory_files( state: State<'_, AppState>, request: ListDirectoryFilesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_manageable_subagents", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "list_manageable_subagents", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn list_manageable_subagents( state: State<'_, AppState>, request: ListManageableSubagentsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "list_mcp_prompts", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::list_mcp_prompts", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn list_mcp_prompts( state: State<'_, AppState>, request: ListMCPPromptsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_mcp_resources", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::list_mcp_resources", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn list_mcp_resources( state: State<'_, AppState>, request: ListMCPResourcesRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_miniapps", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::list_miniapps", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn list_miniapps( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_pending_permission_requests", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::list_pending_permission_requests", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn list_pending_permission_requests( runtime: State<'_, DesktopRuntimeContext>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "list_persisted_sessions", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "list_persisted_sessions", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn list_persisted_sessions( request: ListPersistedSessionsRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_persisted_sessions_page", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "list_persisted_sessions_page", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn list_persisted_sessions_page( request: ListPersistedSessionsPageRequest, runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_project_permission_audit", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::list_project_permission_audit", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn list_project_permission_audit( state: State<'_, AppState>, runtime: State<'_, DesktopRuntimeContext>, request: PermissionAuditRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "list_project_permission_grants", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::list_project_permission_grants", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn list_project_permission_grants( state: State<'_, AppState>, runtime: State<'_, DesktopRuntimeContext>, request: PermissionProjectRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "list_sessions", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::list_sessions", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn list_sessions( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: ListSessionsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_skill_market", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "list_skill_market", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn list_skill_market( _state: State<'_, AppState>, request: SkillMarketListRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "list_subagents", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "list_subagents", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn list_subagents( state: State<'_, AppState>, request: ListSubagentsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "list_subscription_accounts", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "list_subscription_accounts", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn list_subscription_accounts( ) -> Result, String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "list_visible_subagents", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "list_visible_subagents", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn list_visible_subagents( state: State<'_, AppState>, request: ListVisibleSubagentsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "load_acp_json_config", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "load_acp_json_config", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn load_acp_json_config(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_canvas_artifact", + "moduleId": "canvas", + "capabilityId": "feature.canvas", + "visibility": "implementation", + "rustPath": "api::canvas_api::load_canvas_artifact", + "sourceFile": "src/apps/desktop/src/api/canvas_api.rs", + "signature": "fn load_canvas_artifact( state: State<'_, AppState>, request: CanvasStateRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_canvas_state", + "moduleId": "canvas", + "capabilityId": "feature.canvas", + "visibility": "implementation", + "rustPath": "api::canvas_api::load_canvas_state", + "sourceFile": "src/apps/desktop/src/api/canvas_api.rs", + "signature": "fn load_canvas_state( state: State<'_, AppState>, request: CanvasStateRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_git_repo_history", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "load_git_repo_history", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn load_git_repo_history( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_insights_report", + "moduleId": "insights", + "capabilityId": "feature.insights", + "visibility": "implementation", + "rustPath": "api::insights_api::load_insights_report", + "sourceFile": "src/apps/desktop/src/api/insights_api.rs", + "signature": "fn load_insights_report( request: LoadInsightsReportRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "load_mcp_json_config", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "load_mcp_json_config", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn load_mcp_json_config( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_persisted_session_metadata", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "load_persisted_session_metadata", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn load_persisted_session_metadata( request: LoadPersistedSessionMetadataRequest, runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "load_session_event_backfill", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::load_session_event_backfill", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn load_session_event_backfill( runtime: State<'_, DesktopRuntimeContext>, request: LoadSessionEventBackfillRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "load_session_turn_window", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::load_session_turn_window", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn load_session_turn_window( runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, request: LoadSessionTurnWindowRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "load_session_turns", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "load_session_turns", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn load_session_turns( request: LoadSessionTurnsRequest, runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "logout_subscription_account", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "logout_subscription_account", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn logout_subscription_account( request: SubscriptionProviderRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "lsp_change_document", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_change_document", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_change_document(request: ChangeDocumentRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_close_document", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_close_document", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_close_document(request: CloseDocumentRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_close_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_close_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_close_workspace(request: OpenWorkspaceRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_detect_project", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_detect_project", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_detect_project( request: DetectProjectRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_did_change", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_did_change", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_did_change(request: DidChangeRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_did_close", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_did_close", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_did_close(request: DidCloseRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_did_open", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_did_open", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_did_open(request: DidOpenRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_did_save", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_did_save", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_did_save(request: DidSaveRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_find_references", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_find_references", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_find_references( request: FindReferencesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_find_references_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_find_references_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_find_references_workspace( request: FindReferencesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_format_document", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_format_document", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_format_document( request: FormatDocumentRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_format_document_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_format_document_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_format_document_workspace( request: FormatDocumentRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_all_server_states", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_all_server_states", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_all_server_states( request: OpenWorkspaceRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_code_actions_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_code_actions_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_code_actions_workspace( request: GetCodeActionsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_completions", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_completions", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_get_completions( request: GetCompletionsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_completions_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_completions_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_completions_workspace( request: GetCompletionsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_document_highlight_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_document_highlight_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_document_highlight_workspace( request: GetDocumentHighlightRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_document_symbols_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_document_symbols_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_document_symbols_workspace( request: GetDocumentSymbolsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_hover", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_hover", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_get_hover(request: GetHoverRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_hover_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_hover_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_hover_workspace( request: GetHoverRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_inlay_hints_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_inlay_hints_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_inlay_hints_workspace( request: GetInlayHintsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_plugin", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_plugin", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_get_plugin(request: GetPluginRequest) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_semantic_tokens_range_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_semantic_tokens_range_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_semantic_tokens_range_workspace( request: GetSemanticTokensRangeRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_semantic_tokens_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_semantic_tokens_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_semantic_tokens_workspace( request: GetSemanticTokensRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_server_capabilities", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_server_capabilities", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_get_server_capabilities( request: GetServerCapabilitiesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_server_state", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_server_state", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_get_server_state(request: GetServerStateRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_get_supported_extensions", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_get_supported_extensions", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_get_supported_extensions() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_goto_definition", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_goto_definition", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_goto_definition( request: GotoDefinitionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_goto_definition_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_goto_definition_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_goto_definition_workspace( request: GotoDefinitionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_initialize", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_initialize", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_initialize() -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_install_plugin", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_install_plugin", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_install_plugin(request: InstallPluginRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_list_plugins", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_list_plugins", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_list_plugins() -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_list_workspaces", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_list_workspaces", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_list_workspaces() -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_open_document", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_open_document", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_open_document(request: OpenDocumentRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_open_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_open_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_open_workspace( request: OpenWorkspaceRequest, app_handle: tauri::AppHandle, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_prestart_server", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_prestart_server", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_prestart_server(request: PrestartServerRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_rename_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_rename_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_rename_workspace(request: RenameRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_save_document", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_save_document", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_save_document(request: SaveDocumentRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_start_server_for_file", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_start_server_for_file", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_start_server_for_file( request: StartServerForFileRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_stop_all_servers", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_stop_all_servers", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_stop_all_servers() -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_stop_server", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_stop_server", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_stop_server(request: StopServerRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_stop_server_workspace", + "moduleId": "lsp_workspace", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_stop_server_workspace", + "sourceFile": "src/apps/desktop/src/api/lsp_workspace_api.rs", + "signature": "fn lsp_stop_server_workspace(request: GetServerStateRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "lsp_uninstall_plugin", + "moduleId": "lsp", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "lsp_uninstall_plugin", + "sourceFile": "src/apps/desktop/src/api/lsp_api.rs", + "signature": "fn lsp_uninstall_plugin(request: UninstallPluginRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "mark_announcement_seen", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::mark_announcement_seen", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn mark_announcement_seen( state: State<'_, AppState>, request: AnnouncementIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "mark_bitfun_control_surface_ready", + "moduleId": "bitfun_control_host", + "capabilityId": null, + "visibility": "internal", + "rustPath": "bitfun_control_host::mark_bitfun_control_surface_ready", + "sourceFile": "src/apps/desktop/src/bitfun_control_host.rs", + "signature": "fn mark_bitfun_control_surface_ready()", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_agent_cancel", + "moduleId": "miniapp_agent", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_agent_api::miniapp_agent_cancel", + "sourceFile": "src/apps/desktop/src/api/miniapp_agent_api.rs", + "signature": "fn miniapp_agent_cancel( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: MiniAppAgentCancelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_agent_cancel_stale_runs", + "moduleId": "miniapp_agent", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_agent_api::miniapp_agent_cancel_stale_runs", + "sourceFile": "src/apps/desktop/src/api/miniapp_agent_api.rs", + "signature": "fn miniapp_agent_cancel_stale_runs( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: MiniAppAgentCancelStaleRunsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_agent_ensure_session", + "moduleId": "miniapp_agent", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_agent_api::miniapp_agent_ensure_session", + "sourceFile": "src/apps/desktop/src/api/miniapp_agent_api.rs", + "signature": "fn miniapp_agent_ensure_session( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: MiniAppAgentEnsureSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_agent_run", + "moduleId": "miniapp_agent", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_agent_api::miniapp_agent_run", + "sourceFile": "src/apps/desktop/src/api/miniapp_agent_api.rs", + "signature": "fn miniapp_agent_run( state: State<'_, AppState>, coordinator: State<'_, Arc>, scheduler: State<'_, Arc>, request: MiniAppAgentRunRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_agent_turn_text", + "moduleId": "miniapp_agent", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_agent_api::miniapp_agent_turn_text", + "sourceFile": "src/apps/desktop/src/api/miniapp_agent_api.rs", + "signature": "fn miniapp_agent_turn_text( state: State<'_, AppState>, coordinator: State<'_, Arc>, request: MiniAppAgentTurnTextRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_ai_cancel", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_ai_cancel", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_ai_cancel( _state: State<'_, AppState>, request: MiniAppAiCancelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_ai_chat", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_ai_chat", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_ai_chat( app: AppHandle, state: State<'_, AppState>, request: MiniAppAiChatRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_ai_complete", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_ai_complete", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_ai_complete( state: State<'_, AppState>, request: MiniAppAiCompleteRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_ai_list_models", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_ai_list_models", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_ai_list_models( state: State<'_, AppState>, request: MiniAppAiListModelsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_apply_draft", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_apply_draft", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_apply_draft( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_create_draft", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_create_draft", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_create_draft( state: State<'_, AppState>, request: MiniAppDraftCreateRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_decline_builtin_update", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_decline_builtin_update", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_decline_builtin_update( state: State<'_, AppState>, request: MiniAppDeclineBuiltinUpdateRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_dialog_message", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_dialog_message", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_dialog_message( _state: State<'_, AppState>, _app_id: String, _options: Value, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_discard_draft", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_discard_draft", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_discard_draft( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_draft_host_call", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_draft_host_call", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_draft_host_call( state: State<'_, AppState>, request: MiniAppDraftHostCallRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_draft_worker_call", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_draft_worker_call", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_draft_worker_call( state: State<'_, AppState>, request: MiniAppDraftWorkerCallRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_draft_worker_stop", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_draft_worker_stop", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_draft_worker_stop( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_get_customization_metadata", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_get_customization_metadata", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_get_customization_metadata( state: State<'_, AppState>, app_id: String, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_get_draft", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_get_draft", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_get_draft( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_host_call", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_host_call", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_host_call( state: State<'_, AppState>, request: MiniAppHostCallRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_import_from_path", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_import_from_path", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_import_from_path( state: State<'_, AppState>, request: MiniAppImportFromPathRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_install_deps", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_install_deps", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_install_deps( state: State<'_, AppState>, app_id: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_market_auth_poll", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_auth_poll", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_auth_poll( app: AppHandle, request: DesktopAuthPollViewRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_auth_start", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_auth_start", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_auth_start() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_browse", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_browse", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_browse( request: MarketBrowseRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_capture_window", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_capture_window", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_capture_window( app: AppHandle, window: WebviewWindow, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_get_listing", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_get_listing", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_get_listing( request: MarketSlugRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_import_package", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_import_package", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_import_package( state: State<'_, AppState>, request: MarketImportPackageRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_inspect_package", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_inspect_package", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_inspect_package( request: MarketPackagePathRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_install", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_install", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_install( state: State<'_, AppState>, request: MarketInstallRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_installed_origins", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_installed_origins", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_installed_origins( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_installed_status", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_installed_status", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_installed_status( state: State<'_, AppState>, request: MarketListingIdRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_list_submissions", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_list_submissions", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_list_submissions() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_logout", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_logout", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_logout(app: AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_me", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_me", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_me() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_set_favorite", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_set_favorite", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_set_favorite( request: MarketSetFavoriteRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_set_rating", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_set_rating", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_set_rating( request: MarketSetRatingRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_market_submit_installed", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_submit_installed", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_submit_installed( app: AppHandle, state: State<'_, AppState>, request: MarketSubmitInstalledRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "miniapp_market_withdraw_submission", + "moduleId": "miniapp_market", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_market_api::miniapp_market_withdraw_submission", + "sourceFile": "src/apps/desktop/src/api/miniapp_market_api.rs", + "signature": "fn miniapp_market_withdraw_submission( request: MarketSubmissionIdRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "miniapp_permission_diff_for_draft", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_permission_diff_for_draft", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_permission_diff_for_draft( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_recompile", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_recompile", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_recompile( state: State<'_, AppState>, request: MiniAppRecompileRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_render_slide_page", + "moduleId": "miniapp_export", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_export_api::miniapp_render_slide_page", + "sourceFile": "src/apps/desktop/src/api/miniapp_export_api.rs", + "signature": "fn miniapp_render_slide_page( app: AppHandle, request: MiniAppRenderSlidePageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_runtime_status", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_runtime_status", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_runtime_status(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_set_draft_permissions", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_set_draft_permissions", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_set_draft_permissions( state: State<'_, AppState>, request: MiniAppDraftPermissionsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_sync_draft_from_fs", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_sync_draft_from_fs", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_sync_draft_from_fs( state: State<'_, AppState>, request: MiniAppDraftRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_sync_from_fs", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_sync_from_fs", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_sync_from_fs( state: State<'_, AppState>, request: MiniAppSyncFromFsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_worker_call", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_worker_call", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_worker_call( state: State<'_, AppState>, request: MiniAppWorkerCallRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_worker_list_running", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_worker_list_running", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_worker_list_running( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "miniapp_worker_stop", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::miniapp_worker_stop", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn miniapp_worker_stop(state: State<'_, AppState>, app_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "minimize_to_tray", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::minimize_to_tray", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn minimize_to_tray( app: tauri::AppHandle, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "mutate_external_hook_import_command", + "moduleId": "external_hooks", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "mutate_external_hook_import_command", + "sourceFile": "src/apps/desktop/src/api/external_hooks_api.rs", + "signature": "fn mutate_external_hook_import_command( request: MutateExternalHookImportRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "never_show_announcement", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::never_show_announcement", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn never_show_announcement( state: State<'_, AppState>, request: AnnouncementIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "notify_cron_host_ready", + "moduleId": "cron", + "capabilityId": "feature.tasks-automation", + "visibility": "implementation", + "rustPath": "notify_cron_host_ready", + "sourceFile": "src/apps/desktop/src/api/cron_api.rs", + "signature": "fn notify_cron_host_ready() -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "open_html_file_in_browser", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::open_html_file_in_browser", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn open_html_file_in_browser( app: AppHandle, request: OpenHtmlFileInBrowserRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "open_remote_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "open_remote_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn open_remote_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: OpenRemoteWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "open_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "open_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn open_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: OpenWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "page_create_open_link", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_create_open_link", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_create_open_link(request: PageOpenRequest) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_delete", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_delete", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_delete(request: PageSlugRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_delete_version", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_delete_version", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_delete_version(request: PageDeleteVersionRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_deploy", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_deploy", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_deploy(request: PageDeployRequest) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_list", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_list", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_list() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_list_versions", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_list_versions", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_list_versions(request: PageSlugRequest) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_publish", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_publish", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_publish(request: PagePublishRequest) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "page_save_version", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_save_version", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_save_version( request: PagePublishRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "page_unpublish", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_unpublish", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_unpublish(request: PageSlugRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "page_update", + "moduleId": "pages", + "capabilityId": "feature.pages", + "visibility": "implementation", + "rustPath": "api::pages_api::page_update", + "sourceFile": "src/apps/desktop/src/api/pages_api.rs", + "signature": "fn page_update(request: PageUpdateRequest) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "paste_files", + "moduleId": "clipboard_file", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "paste_files", + "sourceFile": "src/apps/desktop/src/api/clipboard_file_api.rs", + "signature": "fn paste_files(request: PasteFilesRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "peer_control_attach", + "moduleId": "peer_host_invoke", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::peer_host_invoke::peer_control_attach", + "sourceFile": "src/apps/desktop/src/api/peer_host_invoke.rs", + "signature": "fn peer_control_attach(controller_device_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "peer_control_detach", + "moduleId": "peer_host_invoke", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::peer_host_invoke::peer_control_detach", + "sourceFile": "src/apps/desktop/src/api/peer_host_invoke.rs", + "signature": "fn peer_control_detach(controller_device_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "peer_controller_set_active", + "moduleId": "peer_host_invoke", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::peer_host_invoke::peer_controller_set_active", + "sourceFile": "src/apps/desktop/src/api/peer_host_invoke.rs", + "signature": "fn peer_controller_set_active(active: bool) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "peer_host_invoke_complete", + "moduleId": "peer_host_invoke", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::peer_host_invoke::peer_host_invoke_complete", + "sourceFile": "src/apps/desktop/src/api/peer_host_invoke.rs", + "signature": "fn peer_host_invoke_complete( id: String, ok: bool, value: Option, error: Option, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "peer_mode_ping", + "moduleId": "peer_host_invoke", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::peer_host_invoke::peer_mode_ping", + "sourceFile": "src/apps/desktop/src/api/peer_host_invoke.rs", + "signature": "fn peer_mode_ping() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "plan_external_hook_import_command", + "moduleId": "external_hooks", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "plan_external_hook_import_command", + "sourceFile": "src/apps/desktop/src/api/external_hooks_api.rs", + "signature": "fn plan_external_hook_import_command( request: PlanExternalHookImportRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "plan_external_mcp_import_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "plan_external_mcp_import_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn plan_external_mcp_import_command( request: PlanExternalMcpImportRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "predownload_acp_client_adapter", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "predownload_acp_client_adapter", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn predownload_acp_client_adapter( state: State<'_, AppState>, request: AcpClientIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "preview_commit_message", + "moduleId": "git_agent", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "preview_commit_message", + "sourceFile": "src/apps/desktop/src/api/git_agent_api.rs", + "signature": "fn preview_commit_message( app_state: State<'_, AppState>, request: PreviewCommitMessageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "probe_acp_client_requirements", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "probe_acp_client_requirements", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn probe_acp_client_requirements( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: ProbeAcpClientRequirementsRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "project_ai_model_reasoning_catalog", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "project_ai_model_reasoning_catalog", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn project_ai_model_reasoning_catalog( request: bitfun_core_types::ReasoningCatalogProjectionRequest, ) -> bitfun_core_types::ReasoningCatalogProjection", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "quick_commit_message", + "moduleId": "git_agent", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "quick_commit_message", + "sourceFile": "src/apps/desktop/src/api/git_agent_api.rs", + "signature": "fn quick_commit_message( app_state: State<'_, AppState>, request: QuickCommitMessageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "quit_app", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::quit_app", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn quit_app(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "read_background_command_output", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::read_background_command_output", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn read_background_command_output( request: ReadBackgroundCommandOutputRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "read_file_content", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "read_file_content", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn read_file_content( state: State<'_, AppState>, request: ReadFileContentRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "read_mcp_resource", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::read_mcp_resource", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn read_mcp_resource( state: State<'_, AppState>, request: ReadMCPResourceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "record_file_change", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "record_file_change", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn record_file_change( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: RecordFileChangeRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "recover_interrupted_dialog_turn", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::recover_interrupted_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn recover_interrupted_dialog_turn( runtime: State<'_, DesktopRuntimeContext>, request: RecoverInterruptedDialogTurnRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "refresh_model_client", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "refresh_model_client", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn refresh_model_client( state: State<'_, AppState>, model_id: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "refresh_models_dev_catalog_now", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "refresh_models_dev_catalog_now", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn refresh_models_dev_catalog_now( ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "refresh_subscription_account", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "refresh_subscription_account", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn refresh_subscription_account( state: State<'_, AppState>, request: SubscriptionProviderRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "reject_file", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "reject_file", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn reject_file( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: AcceptFileRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reject_operation", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "reject_operation", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn reject_operation( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: GetOperationSummaryRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "relay_deploy_cancel", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_cancel", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_cancel( state: State<'_, AppState>, connection_id: String, task: RelayDeployTask, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_install_docker", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_install_docker", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_install_docker( state: State<'_, AppState>, connection_id: String, mirror_mode: Option, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_poll", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_poll", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_poll( state: State<'_, AppState>, connection_id: String, task: RelayDeployTask, cursor: u64, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_preflight", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_preflight", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_preflight( state: State<'_, AppState>, connection_id: String, port: Option, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_register", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_register", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_register( state: State<'_, AppState>, connection_id: String, username: String, password: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_start", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_start", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_start( state: State<'_, AppState>, connection_id: String, port: Option, mirror_mode: Option, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "relay_deploy_verify", + "moduleId": "relay_deploy", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::relay_deploy_api::relay_deploy_verify", + "sourceFile": "src/apps/desktop/src/api/relay_deploy_api.rs", + "signature": "fn relay_deploy_verify(relay_url: String) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "reload_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "reload_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn reload_config(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reload_custom_agents", + "moduleId": "custom_agent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "reload_custom_agents", + "sourceFile": "src/apps/desktop/src/api/custom_agent_api.rs", + "signature": "fn reload_custom_agents( state: State<'_, AppState>, request: ReloadCustomAgentsRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reload_global_config", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reload_global_config", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reload_global_config() -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reload_session_context", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::reload_session_context", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn reload_session_context( runtime: State<'_, DesktopRuntimeContext>, request: bitfun_runtime_ports::AgentContextReloadRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "reload_subagents", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "reload_subagents", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn reload_subagents( state: State<'_, AppState>, request: ReloadSubagentsRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "remote_close_workspace", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_close_workspace", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_close_workspace(state: State<'_, AppState>) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_connect_configure_bot", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_configure_bot", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_configure_bot(request: ConfigureBotRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_configure_custom_server", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_configure_custom_server", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_configure_custom_server(url: String) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_bot_verbose_mode", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_bot_verbose_mode", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_bot_verbose_mode() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_device_info", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_device_info", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_device_info() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_form_state", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_form_state", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_form_state() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_lan_ip", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_lan_ip", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_lan_ip() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_lan_network_info", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_lan_network_info", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_lan_network_info() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_get_methods", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_get_methods", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_get_methods() -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_set_bot_verbose_mode", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_set_bot_verbose_mode", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_set_bot_verbose_mode(verbose: bool) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_set_form_state", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_set_form_state", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_set_form_state( request: bot::RemoteConnectFormState, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_start", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_start", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_start( request: StartRemoteConnectRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_status", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_status", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_status() -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_stop", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_stop", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_stop() -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_stop_bot", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_stop_bot", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_stop_bot() -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_weixin_qr_poll", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_weixin_qr_poll", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_weixin_qr_poll( request: WeixinQrPollRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_connect_weixin_qr_start", + "moduleId": "remote_connect", + "capabilityId": "feature.remote-connect", + "visibility": "implementation", + "rustPath": "api::remote_connect_api::remote_connect_weixin_qr_start", + "sourceFile": "src/apps/desktop/src/api/remote_connect_api.rs", + "signature": "fn remote_connect_weixin_qr_start( request: WeixinQrStartRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remote_create_dir", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_create_dir", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_create_dir( state: State<'_, AppState>, connection_id: String, path: String, recursive: bool, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_download_to_local_path", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_download_to_local_path", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_download_to_local_path( app_handle: tauri::AppHandle, state: State<'_, AppState>, connection_id: String, remote_path: String, local_path: String, transfer_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_execute", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_execute", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_execute( state: State<'_, AppState>, connection_id: String, command: String, ) -> Result<(String, String, i32), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_exists", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_exists", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_exists( state: State<'_, AppState>, connection_id: String, path: String, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_get_tree", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_get_tree", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_get_tree( state: State<'_, AppState>, connection_id: String, path: String, depth: Option, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_get_workspace_info", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_get_workspace_info", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_get_workspace_info( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_open_workspace", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_open_workspace", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_open_workspace( state: State<'_, AppState>, connection_id: String, remote_path: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_read_dir", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_read_dir", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_read_dir( state: State<'_, AppState>, connection_id: String, path: String, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_read_file", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_read_file", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_read_file( state: State<'_, AppState>, connection_id: String, path: String, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_remove", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_remove", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_remove( state: State<'_, AppState>, connection_id: String, path: String, recursive: bool, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_remove_workspace", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_remove_workspace", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_remove_workspace( state: State<'_, AppState>, connection_id: String, remote_path: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_rename", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_rename", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_rename( state: State<'_, AppState>, connection_id: String, old_path: String, new_path: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_upload_from_local_path", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_upload_from_local_path", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_upload_from_local_path( app_handle: tauri::AppHandle, state: State<'_, AppState>, connection_id: String, local_path: String, remote_path: String, transfer_id: String, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remote_write_file", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::remote_write_file", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn remote_write_file( state: State<'_, AppState>, connection_id: String, path: String, content: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "remove_project_permission_grant", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::remove_project_permission_grant", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn remove_project_permission_grant( state: State<'_, AppState>, runtime: State<'_, DesktopRuntimeContext>, request: RemovePermissionGrantRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "remove_recent_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "remove_recent_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn remove_recent_workspace( state: State<'_, AppState>, request: RemoveRecentWorkspaceRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "rename_file", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "rename_file", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn rename_file( state: State<'_, AppState>, request: RenameFileRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reorder_opened_workspaces", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reorder_opened_workspaces", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reorder_opened_workspaces( state: State<'_, AppState>, request: ReorderOpenedWorkspacesRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "replace_mode_skill_selection", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "replace_mode_skill_selection", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn replace_mode_skill_selection( state: State<'_, AppState>, request: ReplaceModeSkillSelectionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "report_bitfun_control_result", + "moduleId": "bitfun_control_host", + "capabilityId": null, + "visibility": "internal", + "rustPath": "bitfun_control_host::report_bitfun_control_result", + "sourceFile": "src/apps/desktop/src/bitfun_control_host.rs", + "signature": "fn report_bitfun_control_result( request: ReportBitFunControlResultRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "report_canvas_runtime_error", + "moduleId": "canvas", + "capabilityId": "feature.canvas", + "visibility": "implementation", + "rustPath": "api::canvas_api::report_canvas_runtime_error", + "sourceFile": "src/apps/desktop/src/api/canvas_api.rs", + "signature": "fn report_canvas_runtime_error( state: State<'_, AppState>, request: ReportCanvasRuntimeErrorRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "report_ide_control_result", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "report_ide_control_result", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn report_ide_control_result(request: IdeControlResultRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_agent_profile_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "reset_agent_profile_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn reset_agent_profile_config( _state: State<'_, AppState>, agent_id: String, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_assistant_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reset_assistant_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reset_assistant_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: ResetAssistantWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "reset_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn reset_config( state: State<'_, AppState>, request: ResetConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_memory", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::reset_memory", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn reset_memory(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_mode_skill_selection", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "reset_mode_skill_selection", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn reset_mode_skill_selection( state: State<'_, AppState>, request: ResetModeSkillSelectionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reset_workspace_persona_files", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reset_workspace_persona_files", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reset_workspace_persona_files( state: State<'_, AppState>, request: ResetWorkspacePersonaFilesRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "resize_agent_companion_desktop_pet", + "moduleId": "appearance", + "capabilityId": "feature.desktop-pet", + "visibility": "implementation", + "rustPath": "appearance::resize_agent_companion_desktop_pet", + "sourceFile": "src/apps/desktop/src/appearance.rs", + "signature": "fn resize_agent_companion_desktop_pet( app: tauri::AppHandle, width: f64, height: f64, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "respond_permission", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::respond_permission", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn respond_permission( runtime: State<'_, DesktopRuntimeContext>, request: PermissionResponseRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "respond_permission_batch", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::respond_permission_batch", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn respond_permission_batch( runtime: State<'_, DesktopRuntimeContext>, request: PermissionResponseRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "restart_app", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "restart_app", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn restart_app(app: AppHandle, request: RestartAppRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "restart_mcp_server", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "restart_mcp_server", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn restart_mcp_server( state: State<'_, AppState>, server_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "restore_session", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::restore_session", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn restore_session( runtime: State<'_, DesktopRuntimeContext>, request: RestoreSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "restore_session_view", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::restore_session_view", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn restore_session_view( runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, request: RestoreSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "restore_session_with_turns", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::restore_session_with_turns", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn restore_session_with_turns( runtime: State<'_, DesktopRuntimeContext>, request: RestoreSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "reveal_external_source_location", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "reveal_external_source_location", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn reveal_external_source_location( request: RevealExternalSourceLocationRequest, ) -> ExternalSourceOperationResult<()>", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "reveal_in_explorer", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reveal_in_explorer", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reveal_in_explorer( state: State<'_, AppState>, request: RevealInExplorerRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "reveal_models_dev_cache_directory", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "reveal_models_dev_cache_directory", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn reveal_models_dev_cache_directory() -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "review_platform_clear_auth_token", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_clear_auth_token", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_clear_auth_token( _state: State<'_, AppState>, request: ReviewPlatformClearAuthTokenRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "review_platform_get_issue", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_issue", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_issue( _state: State<'_, AppState>, request: ReviewPlatformIssueRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_pull_request_ci_log", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_pull_request_ci_log", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_pull_request_ci_log( _state: State<'_, AppState>, request: ReviewPlatformPullRequestCiLogRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_pull_request_detail", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_pull_request_detail", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_pull_request_detail( _state: State<'_, AppState>, request: ReviewPlatformPullRequestDetailRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_pull_request_detail_page", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_pull_request_detail_page", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_pull_request_detail_page( _state: State<'_, AppState>, request: ReviewPlatformPullRequestDetailPageRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_pull_request_review_target", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_pull_request_review_target", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_pull_request_review_target( _state: State<'_, AppState>, request: ReviewPlatformPullRequestDetailRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_pull_request_review_target_by_identity", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_pull_request_review_target_by_identity", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_pull_request_review_target_by_identity( _state: State<'_, AppState>, request: ReviewPlatformPullRequestIdentityRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_workspace_context", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_workspace_context", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_workspace_context( _state: State<'_, AppState>, request: ReviewPlatformWorkspaceContextRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_get_workspace_snapshot", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_get_workspace_snapshot", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_get_workspace_snapshot( _state: State<'_, AppState>, request: ReviewPlatformWorkspaceSnapshotRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "review_platform_update_auth_token", + "moduleId": "review_platform", + "capabilityId": "feature.code-review", + "visibility": "implementation", + "rustPath": "review_platform_update_auth_token", + "sourceFile": "src/apps/desktop/src/api/review_platform_api.rs", + "signature": "fn review_platform_update_auth_token( _state: State<'_, AppState>, request: ReviewPlatformUpdateAuthTokenRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "rollback_miniapp", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::rollback_miniapp", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn rollback_miniapp( state: State<'_, AppState>, app_id: String, version: u32, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "rollback_session", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "rollback_session", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn rollback_session( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: RollbackSessionRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "rollback_session_to_turn", + "moduleId": "snapshot_service", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "rollback_session_to_turn", + "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", + "signature": "fn rollback_session_to_turn( runtime: State<'_, DesktopRuntimeContext>, request: bitfun_runtime_ports::AgentSessionRollbackToTurnRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "run_init_agents_md", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::run_init_agents_md", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn run_init_agents_md( coordinator: State<'_, Arc>, scheduler: State<'_, Arc>, app_state: State<'_, AppState>, request: RunInitAgentsMdRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "run_system_command", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "run_system_command", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn run_system_command( request: RunCommandRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_acp_json_config", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "save_acp_json_config", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn save_acp_json_config( state: State<'_, AppState>, json_config: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_canvas_state", + "moduleId": "canvas", + "capabilityId": "feature.canvas", + "visibility": "implementation", + "rustPath": "api::canvas_api::save_canvas_state", + "sourceFile": "src/apps/desktop/src/api/canvas_api.rs", + "signature": "fn save_canvas_state( state: State<'_, AppState>, request: SaveCanvasStateRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_cloud_speech_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "save_cloud_speech_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn save_cloud_speech_config( state: State<'_, AppState>, request: SaveCloudSpeechConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "save_git_repo_history", + "moduleId": "git", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "save_git_repo_history", + "sourceFile": "src/apps/desktop/src/api/git_api.rs", + "signature": "fn save_git_repo_history( state: State<'_, AppState>, request: SaveGitRepoHistoryRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_mcp_json_config", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "save_mcp_json_config", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn save_mcp_json_config( state: State<'_, AppState>, json_config: String, expected_fingerprint: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_merged_diff_content", + "moduleId": "diff", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "save_merged_diff_content", + "sourceFile": "src/apps/desktop/src/api/diff_api.rs", + "signature": "fn save_merged_diff_content(request: SaveMergedContentRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_project_permission_rules", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::save_project_permission_rules", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn save_project_permission_rules( state: State<'_, AppState>, request: SaveProjectPermissionRulesRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "save_session_metadata", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "save_session_metadata", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn save_session_metadata( request: SaveSessionMetadataRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "save_session_turn", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "save_session_turn", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn save_session_turn( request: SaveSessionTurnRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "scan_workspace_info", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "scan_workspace_info", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn scan_workspace_info( state: State<'_, AppState>, request: ScanWorkspaceInfoRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "search_build_index", + "moduleId": "search", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "search_build_index", + "sourceFile": "src/apps/desktop/src/api/search_api.rs", + "signature": "fn search_build_index( state: State<'_, AppState>, request: SearchRepoIndexRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "search_file_contents", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "search_file_contents", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn search_file_contents( state: State<'_, AppState>, request: SearchFileContentsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "search_filenames", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "search_filenames", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn search_filenames( state: State<'_, AppState>, request: SearchFilenamesRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "search_files", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "search_files", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn search_files( state: State<'_, AppState>, request: SearchFilesRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "search_get_repo_status", + "moduleId": "search", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "search_get_repo_status", + "sourceFile": "src/apps/desktop/src/api/search_api.rs", + "signature": "fn search_get_repo_status( state: State<'_, AppState>, request: SearchRepoIndexRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "search_rebuild_index", + "moduleId": "search", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "search_rebuild_index", + "sourceFile": "src/apps/desktop/src/api/search_api.rs", + "signature": "fn search_rebuild_index( state: State<'_, AppState>, request: SearchRepoIndexRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "search_referenceable_sessions", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "search_referenceable_sessions", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn search_referenceable_sessions( request: SearchReferenceableSessionsRequest, runtime: State<'_, DesktopRuntimeContext>, app_state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "search_session_content", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "search_session_content", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn search_session_content( request: SessionContentSearchRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "search_skill_market", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "search_skill_market", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn search_skill_market( _state: State<'_, AppState>, request: SkillMarketSearchRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "send_background_command_input", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::send_background_command_input", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn send_background_command_input( coordinator: State<'_, Arc>, request: SendBackgroundCommandInputRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "send_mcp_app_message", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "send_mcp_app_message", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn send_mcp_app_message( state: State<'_, AppState>, request: SendMCPAppMessageRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "send_system_notification", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "send_system_notification", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn send_system_notification( app: tauri::AppHandle, request: SendNotificationRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "set_acp_session_config_option", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "set_acp_session_config_option", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn set_acp_session_config_option( state: State<'_, AppState>, request: SetAcpSessionConfigOptionRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "set_acp_session_model", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "set_acp_session_model", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn set_acp_session_model( state: State<'_, AppState>, request: SetAcpSessionModelRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_active_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "set_active_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn set_active_workspace( state: State<'_, AppState>, app: tauri::AppHandle, request: SetActiveWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_agent_profile_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "set_agent_profile_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn set_agent_profile_config( state: State<'_, AppState>, agent_id: String, config: Value, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "set_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn set_config( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, request: SetConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_external_mcp_server_decision_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_mcp_server_decision_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_mcp_server_decision_command( request: SetExternalMcpServerDecisionRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_mcp_servers_enabled_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_mcp_servers_enabled_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_mcp_servers_enabled_command( request: SetExternalMcpServersEnabledRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_source_conflict_choice_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_source_conflict_choice_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_source_conflict_choice_command( request: SetExternalSourceConflictChoiceRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_source_enabled_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_source_enabled_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_source_enabled_command( request: SetExternalSourceEnabledRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_subagent_activation_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_subagent_activation_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_subagent_activation_command( request: SetExternalSubagentActivationRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_subagent_model_binding_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_subagent_model_binding_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_subagent_model_binding_command( request: SetExternalSubagentModelBindingRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_subagents_enabled_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_subagents_enabled_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_subagents_enabled_command( request: SetExternalSubagentsEnabledRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_tool_conflict_choice_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_tool_conflict_choice_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_tool_conflict_choice_command( request: SetExternalToolConflictChoiceRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_tool_target_decision_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_tool_target_decision_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_tool_target_decision_command( request: SetExternalToolTargetDecisionRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_external_tool_targets_enabled_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_external_tool_targets_enabled_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_external_tool_targets_enabled_command( request: SetExternalToolTargetsEnabledRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_global_skill_disabled", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "set_global_skill_disabled", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn set_global_skill_disabled( request: SetGlobalSkillDisabledRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "set_macos_edit_menu_mode", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "set_macos_edit_menu_mode", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn set_macos_edit_menu_mode( state: State<'_, AppState>, app: tauri::AppHandle, request: SetMacosEditMenuModeRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "set_main_window_transient_geometry", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::set_main_window_transient_geometry", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn set_main_window_transient_geometry( app: tauri::AppHandle, request: SetMainWindowTransientGeometryRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "set_miniapp_draft_storage", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::set_miniapp_draft_storage", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn set_miniapp_draft_storage( state: State<'_, AppState>, request: MiniAppDraftStorageSetRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_miniapp_storage", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::set_miniapp_storage", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn set_miniapp_storage( state: State<'_, AppState>, app_id: String, key: String, value: Value, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_mode_skill_disabled", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "set_mode_skill_disabled", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn set_mode_skill_disabled( state: State<'_, AppState>, mode_id: String, skill_key: String, disabled: bool, workspace_path: Option, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_native_prompt_command_conflict_choice_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "set_native_prompt_command_conflict_choice_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn set_native_prompt_command_conflict_choice_command( request: SetNativePromptCommandConflictChoiceRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "set_prevent_sleep_enabled", + "moduleId": "sleep_prevention", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "sleep_prevention::set_prevent_sleep_enabled", + "sourceFile": "src/apps/desktop/src/sleep_prevention.rs", + "signature": "fn set_prevent_sleep_enabled( app_state: State<'_, AppState>, sleep_prevention: State<'_, SleepPreventionState>, request: SetPreventSleepEnabledRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "set_primary_assistant_workspace", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "set_primary_assistant_workspace", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn set_primary_assistant_workspace( state: State<'_, AppState>, request: SetPrimaryAssistantWorkspaceRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "set_session_memory_mode", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::set_session_memory_mode", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn set_session_memory_mode( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: SetSessionMemoryModeRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_session_thread_goal_status", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::set_session_thread_goal_status", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn set_session_thread_goal_status( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: SetSessionThreadGoalStatusRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "set_subagent_timeout", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::set_subagent_timeout", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn set_subagent_timeout( coordinator: State<'_, Arc>, request: SetSubagentTimeoutRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "show_agent_companion_desktop_pet", + "moduleId": "appearance", + "capabilityId": "feature.desktop-pet", + "visibility": "implementation", + "rustPath": "appearance::show_agent_companion_desktop_pet", + "sourceFile": "src/apps/desktop/src/appearance.rs", + "signature": "fn show_agent_companion_desktop_pet(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "show_main_window", + "moduleId": "appearance", + "capabilityId": "feature.desktop-pet", + "visibility": "implementation", + "rustPath": "appearance::show_main_window", + "sourceFile": "src/apps/desktop/src/appearance.rs", + "signature": "fn show_main_window(app: tauri::AppHandle) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_append_audio_chunk", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_append_audio_chunk", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_append_audio_chunk( state: State<'_, AppState>, request: SpeechAppendAudioChunkRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_cancel_input_session", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_cancel_input_session", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_cancel_input_session( state: State<'_, AppState>, request: SpeechCancelInputSessionRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_cancel_model_download", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_cancel_model_download", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_cancel_model_download( state: State<'_, AppState>, app: AppHandle, request: SpeechCancelModelDownloadRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_delete_model", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_delete_model", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_delete_model( state: State<'_, AppState>, app: AppHandle, request: SpeechDeleteModelRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_download_model", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_download_model", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_download_model( state: State<'_, AppState>, app: AppHandle, request: SpeechDownloadModelRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_finish_input_session", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_finish_input_session", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_finish_input_session( state: State<'_, AppState>, request: SpeechFinishInputSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_list_models", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_list_models", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_list_models( state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_start_input_session", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_start_input_session", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_start_input_session( state: State<'_, AppState>, request: SpeechStartInputSessionRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "speech_verify_model", + "moduleId": "speech", + "capabilityId": "feature.voice-input", + "visibility": "implementation", + "rustPath": "speech_verify_model", + "sourceFile": "src/apps/desktop/src/api/speech_api.rs", + "signature": "fn speech_verify_model( state: State<'_, AppState>, app: AppHandle, request: SpeechVerifyModelRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "ssh_connect", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_connect", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_connect( state: State<'_, AppState>, mut config: SSHConnectionConfig, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_delete_connection", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_delete_connection", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_delete_connection( state: State<'_, AppState>, connection_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_disconnect", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_disconnect", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_disconnect( state: State<'_, AppState>, connection_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_disconnect_all", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_disconnect_all", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_disconnect_all(state: State<'_, AppState>) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_get_config", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_get_config", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_get_config( state: State<'_, AppState>, host: String, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_get_server_info", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_get_server_info", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_get_server_info( state: State<'_, AppState>, connection_id: String, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_has_stored_password", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_has_stored_password", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_has_stored_password( state: State<'_, AppState>, connection_id: String, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_is_connected", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_is_connected", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_is_connected( state: State<'_, AppState>, connection_id: String, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_list_config_hosts", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_list_config_hosts", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_list_config_hosts( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_list_docker_containers", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_list_docker_containers", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_list_docker_containers( state: State<'_, AppState>, mut config: SSHConnectionConfig, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_list_port_forwards", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_list_port_forwards", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_list_port_forwards( state: State<'_, AppState>, connection_id: Option, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_list_remote_listening_ports", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_list_remote_listening_ports", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_list_remote_listening_ports( state: State<'_, AppState>, connection_id: String, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_list_saved_connections", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_list_saved_connections", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_list_saved_connections( state: State<'_, AppState>, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_save_connection", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_save_connection", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_save_connection( state: State<'_, AppState>, config: SSHConnectionConfig, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_start_port_forward", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_start_port_forward", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_start_port_forward( state: State<'_, AppState>, request: PortForwardRequest, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_stop_port_forward", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_stop_port_forward", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_stop_port_forward( state: State<'_, AppState>, forward_id: String, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "ssh_test_connection", + "moduleId": "ssh", + "capabilityId": "feature.remote-workspaces", + "visibility": "implementation", + "rustPath": "api::ssh_api::ssh_test_connection", + "sourceFile": "src/apps/desktop/src/api/ssh_api.rs", + "signature": "fn ssh_test_connection( state: State<'_, AppState>, mut config: SSHConnectionConfig, ) -> Result", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "start_acp_dialog_turn", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "start_acp_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn start_acp_dialog_turn( state: State<'_, AppState>, app_handle: AppHandle, request: StartAcpDialogTurnRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_dialog_turn", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::start_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn start_dialog_turn( _app: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: StartDialogTurnRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_file_watch", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "start_file_watch", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn start_file_watch(path: String, recursive: Option) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_mcp_remote_oauth", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "api::mcp_api::start_mcp_remote_oauth", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn start_mcp_remote_oauth( state: State<'_, AppState>, request: StartMCPRemoteOAuthRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_mcp_server", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "start_mcp_server", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn start_mcp_server(state: State<'_, AppState>, server_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_search_file_contents_stream", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "start_search_file_contents_stream", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn start_search_file_contents_stream( app_handle: AppHandle, state: State<'_, AppState>, request: SearchFileContentsRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "start_search_filenames_stream", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "start_search_filenames_stream", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn start_search_filenames_stream( app_handle: AppHandle, state: State<'_, AppState>, request: SearchFilenamesRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "start_subscription_login", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "start_subscription_login", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn start_subscription_login( state: State<'_, AppState>, request: SubscriptionLoginRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "startup_window_control", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::startup_window_control", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn startup_window_control( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, app: tauri::AppHandle, request: StartupWindowControlRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "steer_dialog_turn", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::steer_dialog_turn", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn steer_dialog_turn( runtime: State<'_, DesktopRuntimeContext>, request: SteerDialogTurnRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "stop_acp_client", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "stop_acp_client", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn stop_acp_client( state: State<'_, AppState>, request: AcpClientIdRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "stop_file_watch", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "stop_file_watch", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn stop_file_watch(path: String) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "stop_mcp_server", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "stop_mcp_server", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn stop_mcp_server(state: State<'_, AppState>, server_id: String) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "submit_acp_permission_response", + "moduleId": "acp_client", + "capabilityId": "setting.tools.acp", + "visibility": "implementation", + "rustPath": "submit_acp_permission_response", + "sourceFile": "src/apps/desktop/src/api/acp_client_api.rs", + "signature": "fn submit_acp_permission_response( state: State<'_, AppState>, request: SubmitAcpPermissionResponseRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "submit_mcp_interaction_response", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "submit_mcp_interaction_response", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn submit_mcp_interaction_response( state: State<'_, AppState>, request: SubmitMCPInteractionResponseRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "submit_user_answers", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "submit_user_answers", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn submit_user_answers( runtime: State<'_, DesktopRuntimeContext>, tool_id: String, answers: serde_json::Value, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "subscribe_config_updates", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "subscribe_config_updates", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn subscribe_config_updates() -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "subscribe_permission_requests", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::subscribe_permission_requests", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn subscribe_permission_requests( app: AppHandle, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "sync_config_to_global", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "sync_config_to_global", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn sync_config_to_global(_state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "terminal_ack", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_ack", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_ack( request: AcknowledgeRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_close", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_close", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_close( request: CloseSessionRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_create", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_create", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_create( _app: AppHandle, request: CreateSessionRequest, state: State<'_, TerminalState>, app_state: State<'_, AppState>, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_execute", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_execute", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_execute( request: ExecuteCommandRequest, state: State<'_, TerminalState>, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_get", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_get", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_get( session_id: String, state: State<'_, TerminalState>, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "terminal_get_history", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_get_history", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_get_history( session_id: String, state: State<'_, TerminalState>, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_get_shells", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_get_shells", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_get_shells( state: State<'_, TerminalState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "terminal_has_shell_integration", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_has_shell_integration", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_has_shell_integration( session_id: String, state: State<'_, TerminalState>, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_list", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_list", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_list( state: State<'_, TerminalState>, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "terminal_resize", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_resize", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_resize( request: ResizeRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_send_command", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_send_command", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_send_command( request: SendCommandRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_shutdown_all", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_shutdown_all", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_shutdown_all(state: State<'_, TerminalState>) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "terminal_signal", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_signal", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_signal( request: SignalRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "terminal_write", + "moduleId": "terminal", + "capabilityId": "feature.terminal", + "visibility": "implementation", + "rustPath": "api::terminal_api::terminal_write", + "sourceFile": "src/apps/desktop/src/api/terminal_api.rs", + "signature": "fn terminal_write( request: WriteRequest, state: State<'_, TerminalState>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "test_ai_config_connection", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "test_ai_config_connection", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn test_ai_config_connection( state: State<'_, AppState>, request: TestAIConfigConnectionRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "test_ai_connection", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "test_ai_connection", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn test_ai_connection(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "toggle_main_window_fullscreen", + "moduleId": "system", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::system_api::toggle_main_window_fullscreen", + "sourceFile": "src/apps/desktop/src/api/system_api.rs", + "signature": "fn toggle_main_window_fullscreen( app: tauri::AppHandle, request: ToggleMainWindowFullscreenRequest, ) -> Result", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "touch_session_activity", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "touch_session_activity", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn touch_session_activity( request: TouchSessionActivityRequest, runtime: State<'_, DesktopRuntimeContext>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "trigger_announcement", + "moduleId": "announcement", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "api::announcement_api::trigger_announcement", + "sourceFile": "src/apps/desktop/src/api/announcement_api.rs", + "signature": "fn trigger_announcement( state: State<'_, AppState>, request: AnnouncementIdRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "unarchive_session", + "moduleId": "session", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "unarchive_session", + "sourceFile": "src/apps/desktop/src/api/session_api.rs", + "signature": "fn unarchive_session( request: UnarchiveSessionRequest, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_active_turn_permission_mode", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_active_turn_permission_mode", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_active_turn_permission_mode( runtime: State<'_, DesktopRuntimeContext>, coordinator: State<'_, Arc>, request: UpdateActiveTurnPermissionModeRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "update_app_status", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "update_app_status", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn update_app_status( _state: State<'_, AppState>, _request: UpdateAppStatusRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "WorkspaceAgnostic" + }, + { + "id": "update_cron_job", + "moduleId": "cron", + "capabilityId": "feature.tasks-automation", + "visibility": "implementation", + "rustPath": "update_cron_job", + "sourceFile": "src/apps/desktop/src/api/cron_api.rs", + "signature": "fn update_cron_job(request: UpdateCronJobCommandRequest) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_custom_agent", + "moduleId": "custom_agent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "update_custom_agent", + "sourceFile": "src/apps/desktop/src/api/custom_agent_api.rs", + "signature": "fn update_custom_agent( state: State<'_, AppState>, request: UpdateCustomAgentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_external_integration_policy_command", + "moduleId": "external_sources", + "capabilityId": "feature.ecosystem-compatibility", + "visibility": "implementation", + "rustPath": "update_external_integration_policy_command", + "sourceFile": "src/apps/desktop/src/api/external_sources_api.rs", + "signature": "fn update_external_integration_policy_command( request: UpdateExternalIntegrationPolicyRequest, ) -> ExternalSourceOperationResult", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "update_mcp_remote_auth", + "moduleId": "mcp", + "capabilityId": "setting.tools.mcp", + "visibility": "implementation", + "rustPath": "update_mcp_remote_auth", + "sourceFile": "src/apps/desktop/src/api/mcp_api.rs", + "signature": "fn update_mcp_remote_auth( state: State<'_, AppState>, request: UpdateMCPRemoteAuthRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_miniapp", + "moduleId": "miniapp", + "capabilityId": "feature.miniapps", + "visibility": "implementation", + "rustPath": "api::miniapp_api::update_miniapp", + "sourceFile": "src/apps/desktop/src/api/miniapp_api.rs", + "signature": "fn update_miniapp( state: State<'_, AppState>, app_id: String, request: UpdateMiniAppRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_session_mode", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_session_mode", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_session_mode( runtime: State<'_, DesktopRuntimeContext>, request: UpdateSessionModeRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "update_session_model", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_session_model", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_session_model( runtime: State<'_, DesktopRuntimeContext>, request: UpdateSessionModelRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_session_permission_mode", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_session_permission_mode", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_session_permission_mode( runtime: State<'_, DesktopRuntimeContext>, coordinator: State<'_, Arc>, request: UpdateSessionPermissionModeRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteRouted" + }, + { + "id": "update_session_thread_goal_objective", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_session_thread_goal_objective", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_session_thread_goal_objective( coordinator: State<'_, Arc>, app_state: State<'_, AppState>, request: UpdateSessionThreadGoalObjectiveRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_session_title", + "moduleId": "agentic", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "api::agentic_api::update_session_title", + "sourceFile": "src/apps/desktop/src/api/agentic_api.rs", + "signature": "fn update_session_title( runtime: State<'_, DesktopRuntimeContext>, request: UpdateSessionTitleRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_subagent", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "update_subagent", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn update_subagent( state: State<'_, AppState>, request: UpdateSubagentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_subagent_config", + "moduleId": "subagent", + "capabilityId": "feature.agents", + "visibility": "implementation", + "rustPath": "update_subagent_config", + "sourceFile": "src/apps/desktop/src/api/subagent_api.rs", + "signature": "fn update_subagent_config( state: State<'_, AppState>, request: UpdateSubagentConfigRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "update_workspace_info", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "update_workspace_info", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn update_workspace_info( state: State<'_, AppState>, app: tauri::AppHandle, request: UpdateWorkspaceInfoRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "upload_image_contexts", + "moduleId": "context_upload", + "capabilityId": "feature.files-editor", + "visibility": "implementation", + "rustPath": "api::context_upload_api::upload_image_contexts", + "sourceFile": "src/apps/desktop/src/api/context_upload_api.rs", + "signature": "fn upload_image_contexts( request: UploadImageContextRequest, ) -> Result, String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "validate_config", + "moduleId": "config", + "capabilityId": "setting.application.general", + "visibility": "implementation", + "rustPath": "validate_config", + "sourceFile": "src/apps/desktop/src/api/config_api.rs", + "signature": "fn validate_config(state: State<'_, AppState>) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "validate_skill_path", + "moduleId": "skill", + "capabilityId": "feature.skills", + "visibility": "implementation", + "rustPath": "validate_skill_path", + "sourceFile": "src/apps/desktop/src/api/skill_api.rs", + "signature": "fn validate_skill_path(path: String) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "validate_tool_input", + "moduleId": "tool", + "capabilityId": "feature.ai-assistant", + "visibility": "implementation", + "rustPath": "validate_tool_input", + "sourceFile": "src/apps/desktop/src/api/tool_api.rs", + "signature": "fn validate_tool_input( request: ToolValidationRequest, ) -> Result", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "webdriver_bridge_result", + "moduleId": "lib", + "capabilityId": null, + "visibility": "internal", + "rustPath": "webdriver_bridge_result", + "sourceFile": "src/apps/desktop/src/lib.rs", + "signature": "fn webdriver_bridge_result(request: WebdriverBridgeResultRequest) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + }, + { + "id": "worktree_bind_session", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_bind_session", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_bind_session( request: WorktreeSessionBindingRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_create", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_create", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_create( request: WorktreeCreateRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_create_branch", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_create_branch", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_create_branch( request: WorktreeCreateBranchRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_list", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_list", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_list( request: WorktreeListRequest, ) -> Result, WorktreeError>", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_list_projects", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_list_projects", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_list_projects( request: WorktreeProjectListRequest, ) -> Result, WorktreeError>", + "remoteWorkspacePolicy": "LocalOnly" + }, + { + "id": "worktree_promote", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_promote", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_promote( request: WorktreePromoteRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_recreate", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_recreate", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_recreate( request: WorktreeRecreateRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "worktree_remove", + "moduleId": "worktree", + "capabilityId": "feature.git", + "visibility": "implementation", + "rustPath": "api::worktree_api::worktree_remove", + "sourceFile": "src/apps/desktop/src/api/worktree_api.rs", + "signature": "fn worktree_remove( request: WorktreeRemoveRequest, ) -> Result", + "remoteWorkspacePolicy": "RemoteUnsupported" + }, + { + "id": "write_file_content", + "moduleId": "commands", + "capabilityId": "feature.projects", + "visibility": "implementation", + "rustPath": "write_file_content", + "sourceFile": "src/apps/desktop/src/api/commands.rs", + "signature": "fn write_file_content( state: State<'_, AppState>, request: WriteFileContentRequest, ) -> Result<(), String>", + "remoteWorkspacePolicy": "LegacyUnaudited" + } + ] +} diff --git a/docs/interactive-capabilities/technical/ui-interaction-inventory.json b/docs/interactive-capabilities/technical/ui-interaction-inventory.json new file mode 100644 index 0000000000..7b4f7ce5ba --- /dev/null +++ b/docs/interactive-capabilities/technical/ui-interaction-inventory.json @@ -0,0 +1,1863 @@ +{ + "schemaVersion": 1, + "generatedFrom": "src/shared/interactive-capabilities/catalog.json", + "catalogDigest": "3207e4dc899c9109f0be952b9497d2f6169f9e2bb3ba9a859dda7e6959903470", + "roots": [ + "src/web-ui/src" + ], + "digest": "644f35d8f903d81ae15754aca9ac5c0ff23d26b6da878cbc1c5cfd2c480d90d0", + "fileCount": 370, + "interactionCount": 4441, + "files": [ + { + "sourceFile": "src/web-ui/src/app/components/AboutDialog/AboutDialog.tsx", + "interactionCount": 10, + "digest": "72e44da48b02f264c9b9c24633e7b9f07659afba9a0bbf0837b98c586a906580" + }, + { + "sourceFile": "src/web-ui/src/app/components/AgentCompanionDesktopPet/AgentCompanionDesktopPet.tsx", + "interactionCount": 23, + "digest": "4502d9c0a6f4d40061bc2f15143517a90ae4e6b43d4754d4892ec63847a1b22b" + }, + { + "sourceFile": "src/web-ui/src/app/components/AppErrorBoundary.tsx", + "interactionCount": 2, + "digest": "442bf5d5a960b17305bd93834d5edc964d6d16d2e112267122f10b1f93c2384b" + }, + { + "sourceFile": "src/web-ui/src/app/components/MCPInteractionDialog/MCPInteractionDialog.tsx", + "interactionCount": 6, + "digest": "09b446f41af395a3da8a6ff4113c546a79f4ddc6868bbb333d590f717f40e1f9" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavBar/NavBar.tsx", + "interactionCount": 15, + "digest": "c2cd6077dc9e25278baaca5e4441c0b374afe0b3342f4f3d76f1991b46e9c8f8" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/MainNav.tsx", + "interactionCount": 48, + "digest": "d2ff4fb20c6a66fe9ccd3846e68fd5ecf813a958b1bc5b189f0446945b65261f" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/AssistantSessionCreateMenu.tsx", + "interactionCount": 10, + "digest": "eff139fd7506b1efbc14cdefedf30a73cfdd47f5bb7952d5a9e29ec507042e9f" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/BranchQuickSwitch.tsx", + "interactionCount": 4, + "digest": "16c548a61bb3b12c0ae8831a1fc5bac11d0f127aab474f7a012103bbd611fe58" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/DeviceStatusControl.tsx", + "interactionCount": 12, + "digest": "4d0f4055d7093d6ff4e43ef6f337176396fc9922dcc2f1aa3bc0e993cb3b7752" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/GithubStarButton.tsx", + "interactionCount": 3, + "digest": "6bb72922c080b1a032599c08bf37caebdc6c8efc85685db2abc7c9bbd434d1a4" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/MiniAppEntry.tsx", + "interactionCount": 6, + "digest": "7f5a6d4e705e3b6b38e1604626e7fb436714f8c819f06e152715e47fb43ec3b0" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/NavItem.tsx", + "interactionCount": 9, + "digest": "4aca0cceb147da5fc85b4218e6b89bf0731d06004195791d014b21c50de9b7c9" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx", + "interactionCount": 20, + "digest": "bed067a15547d0fe95e2e5d97d40fd439a10044856ca3e228c2d2d2503eecec3" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/SectionHeader.tsx", + "interactionCount": 4, + "digest": "ba92bc3bb063b448e8b2185ef0025ee88d8f569a0673c4251fb416268c954002" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/WorkspaceSessionFilterMenu.tsx", + "interactionCount": 22, + "digest": "850490a752c37a17f4ccffb303ead3dba4768180fcb56b0787131ffa0aaf0742" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/components/WorkspaceSessionGroupingToggle.tsx", + "interactionCount": 3, + "digest": "b4e85e98e6afdeca2b29e47b894c18994e147e56ee1249a94c46130db7adb7cc" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx", + "interactionCount": 51, + "digest": "5e3b44c6b62a2bdbc9b367812980cc66189488190237febd2122f18bb716baf2" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx", + "interactionCount": 97, + "digest": "e4543876666b7171e9da5021e158ea1ba388661a51439af4c6189459f17026d5" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceListSection.tsx", + "interactionCount": 2, + "digest": "45d5bea921a5990680ae65972a158fc59630638ddba100a05613b9e2b0f0603a" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceProjectPermissionsDialog.tsx", + "interactionCount": 26, + "digest": "a0dc155d5850422abcec799ddbbcdef7034a50ca45a9b94149594d21254da758" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceRelatedPathsDialog.tsx", + "interactionCount": 20, + "digest": "36b8676b324d3823aba40c97f9c306fe959cb02aa702ae92a2d736bd12adba62" + }, + { + "sourceFile": "src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.tsx", + "interactionCount": 15, + "digest": "dd7903a23495d51d9cecb7f8e9809d2c3cd4cfc7d54d1f89dcf58d9b8c170b3a" + }, + { + "sourceFile": "src/web-ui/src/app/components/NewProjectDialog/NewProjectDialog.tsx", + "interactionCount": 12, + "digest": "6323300ed80ab7423e4e17ad7810305dbd6fe0a2d1a4c40e3a7ac55fa3342081" + }, + { + "sourceFile": "src/web-ui/src/app/components/RemoteConnectDialog/AccountPanel.tsx", + "interactionCount": 35, + "digest": "256fede5b7ef94cf1d4c95e6b2866e94de5b9e2e1826a0696afbbe30860e1b56" + }, + { + "sourceFile": "src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDialog.tsx", + "interactionCount": 85, + "digest": "c7bb68d0dfbff4dad1bd505e33f613b47fe5b3281ae874bbfae31947c9a54ad5" + }, + { + "sourceFile": "src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDisclaimer.tsx", + "interactionCount": 6, + "digest": "5fb2452d947b95f7a2da23d91770e8146270bc1864534b9998170d29d415b270" + }, + { + "sourceFile": "src/web-ui/src/app/components/SceneBar/SceneBar.tsx", + "interactionCount": 2, + "digest": "9ee30a73f2ad51c5d60b8ecf98c31a508e255097c0762eb160ad5aa5f7c50cf9" + }, + { + "sourceFile": "src/web-ui/src/app/components/SceneBar/SceneTab.tsx", + "interactionCount": 8, + "digest": "e828b26cb3cc2137160225d9a89f629cd1df7660b1277e40e30a99020185aa53" + }, + { + "sourceFile": "src/web-ui/src/app/components/TitleBar/NotificationButton.tsx", + "interactionCount": 7, + "digest": "800bf7039a8ac6f3bd2570109e2562db41066e9494b0b5bacb834a0c2cef01e2" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/BranchSelectModal.tsx", + "interactionCount": 15, + "digest": "aa52b015092112afe46d0f23cc1f49990cc4ec102665fbe52008a332f79f7081" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/DiffFullscreenViewer.tsx", + "interactionCount": 7, + "digest": "0a06427596059af7b545b5e6240e44414c83108ac16865bc25d01b603f21f8da" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/FilesPanel.tsx", + "interactionCount": 24, + "digest": "c5e6ae8fd39b89e1f51abaed1674cb16e74f425d636a404fbad0356887ef55fc" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/TerminalEditModal.tsx", + "interactionCount": 11, + "digest": "2203bb38233ef96178a45d432f6f7ec0d8df40bce50e1c19a612c2ef0f976369" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/base/FlexiblePanel.tsx", + "interactionCount": 6, + "digest": "c31a0f742347cce42224fb5b532130213d0fb1279f238a49af2536c3ff6d8d1e" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/anchor-zone/AnchorZone.tsx", + "interactionCount": 7, + "digest": "93508e96928a9993e3c5a01ee1f91d0ef43fe209eb407ac690228951da34b6b2" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/editor-area/DropZone.tsx", + "interactionCount": 1, + "digest": "ceaa1bd839d7bd2dab929b0572b789fb4cf2f71bcc0dbd8e0356ffb89f557fb1" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/editor-area/EditorArea.tsx", + "interactionCount": 2, + "digest": "1d0b3d2c64be24fce4f8d564e64289eb77e41de272f449ec7765fc50de94b729" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/editor-area/EditorGroup.tsx", + "interactionCount": 3, + "digest": "bde48fc8a6f4408467e3c7a42871b14329e6c6664448200c3e627eb837653cf0" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/editor-area/SplitHandle.tsx", + "interactionCount": 2, + "digest": "49dc52031c0544284b6859aae310872aa3e6f20f280201cf128f94fbb45742f2" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/empty-state/EmptyState.tsx", + "interactionCount": 2, + "digest": "800c24c7082600bd8240deb5c3579a8211d051f2cdc5c1e731e16a80c80384ff" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/mission-control/MissionControl.tsx", + "interactionCount": 10, + "digest": "3f881b99976da45e1d397f22df2e160814cbb9adc57f95a7470a73fbe62937c6" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/mission-control/SearchFilter.tsx", + "interactionCount": 1, + "digest": "f8ed27d6c0c020bcd8194b28b88a293a205ed9b4cbabd66c8f2fe99d93c0bac4" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/mission-control/ThumbnailCard.tsx", + "interactionCount": 7, + "digest": "075cd17c7cbd174c6c7a6f1d84bc1861640f787f02e4ba3d6d276973603c8aa4" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/quick-look/QuickLook.tsx", + "interactionCount": 5, + "digest": "8ffa60464c82c5c3b1a9d9778db233b4abbc99a2a6f3cd1d34e2f1bba1cc13c3" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/tab-bar/Tab.tsx", + "interactionCount": 6, + "digest": "80f6ac0064563fd5ca1446b0ae521d3f6755598e6c9c23d2469fb4b15faae08b" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/tab-bar/TabBar.tsx", + "interactionCount": 7, + "digest": "f507af744f2f75354f70256cf38e5a5562d6657d1cbe39f16674f13116cfd269" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/content-canvas/tab-bar/TabOverflowMenu.tsx", + "interactionCount": 6, + "digest": "9084a8cfcfa844aa242bfa389071a5791ee21343bf88ef0b64bc7b0440f7b84f" + }, + { + "sourceFile": "src/web-ui/src/app/components/panels/review-platform/ReviewPlatformPanel.tsx", + "interactionCount": 76, + "digest": "b97d73bf33a952b576411d18e77baf917ba26e6136ccc08b8a602d5d8f888208" + }, + { + "sourceFile": "src/web-ui/src/app/components/scheduled-jobs/DateTimePickerPopover.tsx", + "interactionCount": 11, + "digest": "876bcdc3917aee329a026a416ff3d159820b3d7e7ebb31a2a4cc71fb8c25615d" + }, + { + "sourceFile": "src/web-ui/src/app/components/scheduled-jobs/LocalizedDateTimeField.tsx", + "interactionCount": 8, + "digest": "55bcf41107c36e62643ffb43d3c2b915f485ecbd93fb571fae8b1153fe59b9db" + }, + { + "sourceFile": "src/web-ui/src/app/components/scheduled-jobs/ScheduledJobsView.tsx", + "interactionCount": 39, + "digest": "53a3456b5e5fb254fc033f3f95660b295d948962ffe4e8422f2ec872fafd40e1" + }, + { + "sourceFile": "src/web-ui/src/app/global-search/GlobalSearchRoot.tsx", + "interactionCount": 19, + "digest": "2aeaca8d728a5fa487c2843b356604d6928c8b28f5fce98392449befd4020471" + }, + { + "sourceFile": "src/web-ui/src/app/global-search/interactiveCapabilityCatalog.ts", + "interactionCount": 4, + "digest": "b020950e8f55205c58a5de472b337d624d6b04282e91313c2bd725b0998c2ace" + }, + { + "sourceFile": "src/web-ui/src/app/global-search/productActionActivator.ts", + "interactionCount": 1, + "digest": "b6f62675f12f9b898ddd44dccff53023def7821ba563d7b16e003366603984f1" + }, + { + "sourceFile": "src/web-ui/src/app/global-search/providers/actionSearchProvider.ts", + "interactionCount": 1, + "digest": "5c8a37b7985292a7aced10564a39859683d1c4375c587a256dbd615f79e74b77" + }, + { + "sourceFile": "src/web-ui/src/app/global-search/types.ts", + "interactionCount": 1, + "digest": "99d1095c99b7c119d7e2d5a7a28bb05fb24d98e77cc7c926d975a70c1c64b413" + }, + { + "sourceFile": "src/web-ui/src/app/hooks/useGallerySceneAutoRefresh.ts", + "interactionCount": 1, + "digest": "712656790d2bbcedceb16494b1ccc2d5fde039451c150e5166fdfe772f03413a" + }, + { + "sourceFile": "src/web-ui/src/app/layout/FloatingMiniChat.tsx", + "interactionCount": 6, + "digest": "5059c1180efc08d341b6daaff0843abbcfaeaad07f98b8659de3ffc1567ade4e" + }, + { + "sourceFile": "src/web-ui/src/app/layout/MiniAppBubbleWelcome.tsx", + "interactionCount": 3, + "digest": "a853cbbc90fea7b9b977c8ddf250f0d924583d65af10c68e9189636f27ad532c" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/SceneViewport.tsx", + "interactionCount": 3, + "digest": "ddf8a26b0485f28f1675e445e54e3a4bd946a1fcd9a1f1622ac0d6a23d119770" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/AgentsScene.tsx", + "interactionCount": 37, + "digest": "00e237e1b5bb46d0b2a1d5808a53e21c839bfaef823a9f5951fb1796459fd856" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/components/AgentCard.tsx", + "interactionCount": 3, + "digest": "719cd7ddc210207bdecc923095729e452f783cd337136bd1f19de0cff766a361" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/components/CoreAgentCard.tsx", + "interactionCount": 3, + "digest": "719cd7ddc210207bdecc923095729e452f783cd337136bd1f19de0cff766a361" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/components/CreateAgentPage.tsx", + "interactionCount": 39, + "digest": "69d923ae22f2551ae91f13ecdb14bc653d317c88a1c2f3f98ba3f2a91a10ef74" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/components/SkillGroupPicker.tsx", + "interactionCount": 29, + "digest": "b413f483a2eeb1a196a985fa9027f355d13a54cc29bd6a8a6105ee6fd394a61f" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/agents/components/ToolGroupPicker.tsx", + "interactionCount": 29, + "digest": "cf8174689b86225ec7b6a39bdb8452c33812ab7dc94ee44ff3f0626e60eaa452" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/browser/BrowserPanel.tsx", + "interactionCount": 17, + "digest": "438445a73e738ad7ede86dc54427b0c65581287ebed56e5e95465a7d60166a8c" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/browser/BrowserScene.tsx", + "interactionCount": 12, + "digest": "b26b5a550dcf630b2b424ab6076dd667a240ad4d07387be4ea860a9dd49157b3" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/ecosystem-compatibility/EcosystemCompatibilityScene.tsx", + "interactionCount": 28, + "digest": "b43da9979def9cd2b3a98244425002f511e885e62e8287bde0af9d97c0ec2bba" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/file-viewer/FileViewerNav.tsx", + "interactionCount": 8, + "digest": "d964511fea7dc39a6b6541c39ffdf805ff974464290eab084624eca078ca7b19" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/git/GitNav.tsx", + "interactionCount": 4, + "digest": "2b7d115bc658087afcabe87546363d2d178e6311b620d8deea358d65eaaeb8c9" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/git/GitScene.tsx", + "interactionCount": 3, + "digest": "db71de0865bec4d8fa770b04e2b6530881da9d032ba231beffe5100763c0ff8d" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/git/views/BranchesView.tsx", + "interactionCount": 14, + "digest": "3e139a4d1953eb5163a542a27520c9f805f1933ade0ff4d85d42603729bb7bcd" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/git/views/WorkingCopyView.tsx", + "interactionCount": 32, + "digest": "a2c2342fa9ae21f2a037f76551905ba9284ffd97c7d00d170f7e4d0cce1fd09c" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/MiniAppGalleryScene.tsx", + "interactionCount": 2, + "digest": "581e87fefd80f06c835a2d939a980b9379a563434c07ced3ca43e1bcc3ac90af" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/MiniAppScene.tsx", + "interactionCount": 5, + "digest": "5066f0ac612f46405d8a55f6bcf07cef12baeee3162b0b487c3a46fc679ef484" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/components/MiniAppCard.tsx", + "interactionCount": 10, + "digest": "68f7e131bb93b6e87fe2310ecc773f15c9f90302bff41475a2fb3bef0728a416" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/components/MiniAppDetailModal.tsx", + "interactionCount": 6, + "digest": "d05c249013a70050a77a89986a5f7286ac56b7635ab7f2d23607b765271d9273" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/customization/MiniAppCustomizeEntry.tsx", + "interactionCount": 2, + "digest": "fd6ddfc32f6dcace1a847606a2f8901367e0a02ae42b1e834e98582d61774dcc" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/customization/MiniAppCustomizePanel.tsx", + "interactionCount": 17, + "digest": "786e87aa14be39785b525f9f09daaec1b9668eb22287ea9be4200ce9fa04dfcb" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/customization/MiniAppPermissionDiffDialog.tsx", + "interactionCount": 2, + "digest": "ab2d7fbab5224c4b95d74a5900b003bbbfbc7b9bdafdc4d7dd06c3d8e6e4f4de" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/miniAppActivity.ts", + "interactionCount": 2, + "digest": "e0bb67f750366f712621113e5620313556ee64d827e77de3b4e9d59bb17a3eca" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/views/MiniAppGalleryView.tsx", + "interactionCount": 19, + "digest": "4967764e43f6674286d7351d144c45b6f9e5f6a306f709288e48fde6c4dba5cc" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/views/MiniAppMarketView.tsx", + "interactionCount": 23, + "digest": "3747b29e7f3cc26c32147264da178541b4beb39b7617abd6c08022cc9556ad10" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.tsx", + "interactionCount": 41, + "digest": "fe57e0acd70a7998ee1336c1c1e7abcb59a2d38d9652adb14747f6ee191310a7" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/my-agent/InsightsScene.tsx", + "interactionCount": 16, + "digest": "8340ed769d01c59681b5b878264434982a5ab9ffd62001a26041b45f32bf3589" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/nav-registry.ts", + "interactionCount": 2, + "digest": "7dcb6ce4e62577083e6a9abe45b23839fb8d82c1148466c72d48129b53060672" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/pages/PagesScene.tsx", + "interactionCount": 34, + "digest": "6a15c79d533d3ace991d9860368d76735945d78735ec6e1bf57acc01ca45b0d8" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/AssistantAvatarPicker.tsx", + "interactionCount": 16, + "digest": "d06077a41aec2eb7ee782a191fe5e2f879091c23f09737dfb06707c0b8b9ddf6" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/AssistantCard.tsx", + "interactionCount": 15, + "digest": "09f9205d3e6da251a6efb0ddacfc0b0916565d8b908a8e8e3cd75945888b8ab1" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx", + "interactionCount": 41, + "digest": "ed71a621f323d9cfabdfade37850d6ba2bcdbcb4224785e3f0e319f08b8ba43b" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx", + "interactionCount": 41, + "digest": "9e1e4d0ffa3be745251cd3fba74eb8c1791439142b415f3ffe82997465eee1ee" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.tsx", + "interactionCount": 6, + "digest": "5e8f1b2e43224dfda11f01874fae6fde28c2c43f03498b42a854416f2aa2c7e5" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/NurseryGallery.tsx", + "interactionCount": 10, + "digest": "a5b19980672c5dc0561d8f3ce3ac046ae2d539cdfdaeb7f83a82f46d3dc9dada" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/profile/views/PersonaRadar.tsx", + "interactionCount": 3, + "digest": "e81bb5c0479a90450e41dd3325b97ac293be653ca9b8e58699b28f65dfd61441" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/session/SessionScene.tsx", + "interactionCount": 2, + "digest": "acfb49d3d22bf5690accee5fa1bb0b1d9d7b5798bf6575354e79f832dd14463c" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/settings/SettingsNav.tsx", + "interactionCount": 10, + "digest": "cdb14a2e4c64e66daa0077086f5a9af1a65e804c37ad9f622c58204ee71abfcd" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/settings/components/ArchivedSessionsConfig.tsx", + "interactionCount": 11, + "digest": "711291c1a1d8c0e0511f2d6a0f177ba7b669677fac686360bb8f675af994f143" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/settings/components/KeyboardShortcutsTab.tsx", + "interactionCount": 23, + "digest": "1be232ca02b417e007e83b1a1193ed209ed4391164cf94632cfe00b09bb91195" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/settings/components/SettingsViewPage.tsx", + "interactionCount": 2, + "digest": "a0dca5a4044950973b7e917696bb15593f7ff8dfa5e739a1cf93c5b932abca48" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/settings/settingsRegistry.ts", + "interactionCount": 17, + "digest": "3bd894e5312019468f8a94e489334cbb1d60784d2a90f7d31632a6a648b20be0" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/shell/ShellNav.tsx", + "interactionCount": 14, + "digest": "feda8254c4e00152c105f9ec34f7336c9657bc3894068cb88a9409883f0c49cc" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/shell/components/ShellNavEntryItem.tsx", + "interactionCount": 7, + "digest": "ba38ae79f585609b3f2b91147a9f2fad5747899dbbf6f350eb9e485b38eca181" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/shell/components/ShellNavWorkspaceSwitcher.tsx", + "interactionCount": 6, + "digest": "98fe03224eb823b520c453bb5d2105529d4c441fe7364a7a4874d330c4d5af54" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/skills/SkillsScene.tsx", + "interactionCount": 62, + "digest": "564597ef8a29e696dce830a5bb7f8f1cfcc536bc5559485aa063598ad6f921f5" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/skills/components/SkillCard.tsx", + "interactionCount": 8, + "digest": "2ba5365bad213027bd4704c5dc213cb9722e5892e6dee69800a83cd270ba5bdf" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/skills/components/SkillsSuiteView.tsx", + "interactionCount": 18, + "digest": "5a0e313c53a07c79fa750e3dfea2f2d79177e54838523b34650546f4ed4355ad" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/todos/TodosScene.tsx", + "interactionCount": 12, + "digest": "471bf0d6ce8569f4b1de9cf8e9809b1bef0fecfbfc2e05ee11aba12a1b353b7e" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/todos/components/TodoCalendar.tsx", + "interactionCount": 3, + "digest": "6937633b8dd02dd9065a58f05e7bd2b4f2f59554db7ec1c5d74881890364b0fe" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/todos/components/TodoEditor.tsx", + "interactionCount": 30, + "digest": "98507ad206a4e67bb973c3e2f2bc832349691c5c8d309892b315a6369f408fc9" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/todos/components/TodoItemRow.tsx", + "interactionCount": 11, + "digest": "f8edb85ff21e005753441a11b1b24932eccd4523ddf3b9cb488c7dd37a4ed94d" + }, + { + "sourceFile": "src/web-ui/src/app/scenes/welcome/WelcomeScene.tsx", + "interactionCount": 10, + "digest": "69a3737dc237c1a33c0ecddfa8c433d16be18a1ce6bee50b49110e599e60eee8" + }, + { + "sourceFile": "src/web-ui/src/app/stores/sceneStore.ts", + "interactionCount": 3, + "digest": "58298bea669690eb5524f43038cacc0c08ae621bcf9fb97df8392539f2f4d530" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Alert/Alert.tsx", + "interactionCount": 2, + "digest": "800c24c7082600bd8240deb5c3579a8211d051f2cdc5c1e731e16a80c80384ff" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Button/Button.tsx", + "interactionCount": 1, + "digest": "596a703135d03aefdc877c8db21f35e8f46d043d078e73e45df3e65b7bffd8f0" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Checkbox/Checkbox.tsx", + "interactionCount": 2, + "digest": "dcce382aa2d381ebe9b6e66f08d1282649b8e023bc93f32e541513c650ae4adb" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/CodeEditor/CodeEditor.tsx", + "interactionCount": 2, + "digest": "0819b25af57a97c0ca230c96e29e4e974f7a0d99a15c58b8c1317484bcaa23fb" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/ConfigPage/ConfigPageRefreshButton.tsx", + "interactionCount": 2, + "digest": "6799cf30edc8746a5a315525533e14b3c72ffda5c476987659d5c38f7050973e" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/ConfirmDialog/ConfirmDialog.tsx", + "interactionCount": 6, + "digest": "69b63bb8c7b2d92db44843e1aadf1c2ff1f2f128d0eecf78f31bf10928feca38" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FilterPill/FilterPill.tsx", + "interactionCount": 3, + "digest": "2ee8b0c8a4304a06842c8bfb846c977a9faedf49f2bd4f13df92b6a59b4811ee" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FlowChatCards/BaseToolCard/BaseToolCard.tsx", + "interactionCount": 6, + "digest": "cace0b2bf846ce4c94ce596f0ebaa9ce1a6a02836cd23d96416aa2927903bab6" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FlowChatCards/SearchCard/SearchCard.tsx", + "interactionCount": 2, + "digest": "a1cf84b1285db4c6c65d2bdc8a3d065e12b78bddc9d32e1ad595248a6a9d6862" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FlowChatCards/SnapshotCard/SnapshotCard.tsx", + "interactionCount": 14, + "digest": "ee993168da4eb9f22f7368bd59e9eedfc142a8395b190eea42f74550891f5916" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FlowChatCards/TaskCard/TaskCard.tsx", + "interactionCount": 2, + "digest": "a1cf84b1285db4c6c65d2bdc8a3d065e12b78bddc9d32e1ad595248a6a9d6862" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/FlowChatCards/WebSearchCard/WebSearchCard.tsx", + "interactionCount": 3, + "digest": "f74c002789c2c805fdacbdc2b81a6cf51678e8da0dd7ea1244f8ab391d68d25c" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/IconButton/IconButton.tsx", + "interactionCount": 1, + "digest": "596a703135d03aefdc877c8db21f35e8f46d043d078e73e45df3e65b7bffd8f0" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Input/Input.tsx", + "interactionCount": 1, + "digest": "37c2810a30e7352a856980ebc8ec6e1c2ee396fcaccb0d89e7b6da1f3b215742" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/InputDialog/InputDialog.tsx", + "interactionCount": 7, + "digest": "bb81143bae203a2bd6d517c9ecacf1a8ed631ba2a1a71ac80d4c18c19da0d183" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Markdown/Markdown.tsx", + "interactionCount": 15, + "digest": "d3d81ec92c282151b74e21b5e206496c84646666285d4f4c80ba522c2104decc" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Markdown/MermaidBlock.tsx", + "interactionCount": 6, + "digest": "ea060e14ea967a8f3d7614d37a30e40745f47f2def1318e842dd858ae653e0be" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Modal/Modal.tsx", + "interactionCount": 3, + "digest": "b8051f3ce05c2bc03a14d7c5661ee67c5467e161116d223f9633885ea6d89977" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/NumberInput/NumberInput.tsx", + "interactionCount": 16, + "digest": "ecf0961cd95d9b89f6764fb44bd1e40b4742b71183ae6454fd4baf7f30b2b623" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/PopupCloseButton/PopupCloseButton.tsx", + "interactionCount": 2, + "digest": "721537e698f0017dd22367f7fc6b4fb3e3e2584e373105f854d31d3c5b103fa4" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Search/Search.tsx", + "interactionCount": 10, + "digest": "74546f8760083a67b57e03a86c8e4e39f24ac4677d387bb376831ed5cdfb2c72" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Select/Select.tsx", + "interactionCount": 19, + "digest": "59929103e1e8ee3f9db42c06250e695d37e1ea29d2e86b0532bf41aa1e6878f7" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Switch/Switch.tsx", + "interactionCount": 2, + "digest": "dcce382aa2d381ebe9b6e66f08d1282649b8e023bc93f32e541513c650ae4adb" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Tabs/Tabs.tsx", + "interactionCount": 8, + "digest": "1c200ebcd62529c34392698c288320de0a8efda8e91ef90759c9f9e821d0d66d" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Tag/Tag.tsx", + "interactionCount": 3, + "digest": "24eb873ecd3ee7efa78c3ea38dd8620ce794fc478705ae294c0a87e9bba3b717" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/Textarea/Textarea.tsx", + "interactionCount": 2, + "digest": "a6babb495854c3d0e7344818b3121bd142e382e828bc0b518f001aca74ffe6a8" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/WindowControls/WindowControls.tsx", + "interactionCount": 9, + "digest": "42cc6e8308233191f2be58b9830d6c798a6f43bc6d58ff72b58d52e389703fb6" + }, + { + "sourceFile": "src/web-ui/src/component-library/components/registry.tsx", + "interactionCount": 83, + "digest": "d44260be8de787f2032f053a6b9cfd0f3079482dc330d200d1a4dd362ced4902" + }, + { + "sourceFile": "src/web-ui/src/component-library/preview/MarkdownPreview.tsx", + "interactionCount": 16, + "digest": "779e26b3f1785f51933fd7def6b300df8e0e4c42e33cf2e9be5096560f9cb213" + }, + { + "sourceFile": "src/web-ui/src/component-library/preview/PreviewApp.tsx", + "interactionCount": 7, + "digest": "c57f4e01c7fce20b7e4315c32d8e2a8975edfdc33d8986273064c28bf82b86c3" + }, + { + "sourceFile": "src/web-ui/src/component-library/preview/layouts/ColumnLayout.tsx", + "interactionCount": 2, + "digest": "11443e85c1eec613496667ab8370ddd507852ccedfa1cc7c180f12d89afd06a5" + }, + { + "sourceFile": "src/web-ui/src/component-library/preview/layouts/FullPageLayout.tsx", + "interactionCount": 2, + "digest": "62f592fdbe80e9e753762e8b300f0d640d85c11ab7e44667e4e92ecd83061531" + }, + { + "sourceFile": "src/web-ui/src/component-library/preview/layouts/LargeCardLayout.tsx", + "interactionCount": 2, + "digest": "b331468136e2a16473642002a365e790452eafb167373979e5498c01df70054e" + }, + { + "sourceFile": "src/web-ui/src/features/dispatch/DispatchInstallDialog.tsx", + "interactionCount": 17, + "digest": "328bd653959a664b2d1b0276c354cc504d1f77c5c17e0c0667b9ad6b0932b1ce" + }, + { + "sourceFile": "src/web-ui/src/features/dispatch/DispatchJobObserver.ts", + "interactionCount": 2, + "digest": "90d3ae5aaeb99bd543e07983e7d5d357f58ccae8a88ae275e5bd0fcdfeae78f3" + }, + { + "sourceFile": "src/web-ui/src/features/dispatch/DispatchResultDialog.tsx", + "interactionCount": 3, + "digest": "a843d51e9de9c1bb85f4aedfc4a316807c07474660ec83884334a19f46fbcf0c" + }, + { + "sourceFile": "src/web-ui/src/features/dispatch/DispatchTargetPicker.tsx", + "interactionCount": 24, + "digest": "cd452d25efced5cff703b2796e7a2df566e5391582422cabd6653777b1d3b440" + }, + { + "sourceFile": "src/web-ui/src/features/market-account/MarketAccountControls.tsx", + "interactionCount": 12, + "digest": "5f3462acbd4f7ebb652624e6ffe9bef20c00fc143429b4a28b665782001b9d0d" + }, + { + "sourceFile": "src/web-ui/src/features/relay-deploy/RelayDeployWizard.tsx", + "interactionCount": 63, + "digest": "47225dd360eea7224b51eaf010255ba4237f4149fbf41f3ce65d3934756146f1" + }, + { + "sourceFile": "src/web-ui/src/features/ssh-remote/ConfirmDialog.tsx", + "interactionCount": 3, + "digest": "9a2fc2713cfba555bec0c4c6a7294c56a12c27ac501e910a4a32642f1d5d342b" + }, + { + "sourceFile": "src/web-ui/src/features/ssh-remote/PortForwardDialog.tsx", + "interactionCount": 28, + "digest": "7bec680f2f5cf637517d807a00fa950daca33ccf3c535213eb6fb200879275c0" + }, + { + "sourceFile": "src/web-ui/src/features/ssh-remote/RemoteFileBrowser.tsx", + "interactionCount": 43, + "digest": "078cfe9221f9960346945d8c552f35945efb1254bc2b1b1c9ecb9a035ac20b2f" + }, + { + "sourceFile": "src/web-ui/src/features/ssh-remote/SSHAuthPromptDialog.tsx", + "interactionCount": 26, + "digest": "5cbe2a8f80e3059f1db1a0ddb721a11021cef9fbc4d5c28693f929cb0f3c0af1" + }, + { + "sourceFile": "src/web-ui/src/features/ssh-remote/SSHConnectionDialog.tsx", + "interactionCount": 88, + "digest": "965b441cf23ffe36a08b9a57334b826ed59e60c7cd481bfcf7ec08e8cfc57d47" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ChatInput.tsx", + "interactionCount": 72, + "digest": "3bc3014007ebb954f0b4118133c0d5eb466e57589e77ddffc407f09d05b0952c" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ChatInputApprovalBand.tsx", + "interactionCount": 16, + "digest": "cc1904f2af94cc64544f97e88876a0cddbc3c538f8213539c932c48b6b460305" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ChatInputWorkspaceStrip.tsx", + "interactionCount": 37, + "digest": "143f49a23623cfc9203a0aa86ef3a002f8df05f45dbe7081b5d56ab7642f6c50" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/CodePreview.tsx", + "interactionCount": 1, + "digest": "3f30a635ba469e752dab3152c95dbd9672021a6fa0fb631e8b186880d8360d4c" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/CopyOutputButton.tsx", + "interactionCount": 4, + "digest": "23d321c7fb61ae064401ec41e4cc420ca6d41895df3e0a378a9faf0cb00fc932" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/CopyableTextPreview.tsx", + "interactionCount": 2, + "digest": "3365bf0837a71832cdb189d033e1db265b4c1c1b7df44dbd92f70219863e63de" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/CoworkExampleCards.tsx", + "interactionCount": 9, + "digest": "0b33e2f6bfab61f0b1535b7bef152beae635202c6716d799d4a6183c02edee2a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/CurrentSessionTitle.tsx", + "interactionCount": 2, + "digest": "7be80ca3d88067fd7b14b160f723a79c15020d48a347d4193b1aa84d6d561322" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/DeepReviewConsentDialog.tsx", + "interactionCount": 5, + "digest": "42b9845b7b6713f08eaaef0eee7f17734cd099fc4ed16e6729b4c35c021606d7" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/FileMentionPicker.tsx", + "interactionCount": 3, + "digest": "a9678c221f5f91f150d7f32b28234ce3a4828b340b799b9506429893af649c54" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/FlowToolCardErrorBoundary.tsx", + "interactionCount": 3, + "digest": "7a197aaa471a1c3d4e579bd59ce2301774e7835076e414ce77ecf1718c71d331" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/HarnessProfileSelector.tsx", + "interactionCount": 6, + "digest": "46f5e5d7ea81bfc842800d0828091753e4e50a2958cd498e6491bb05e4f70f62" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ImageAnalysisCard.tsx", + "interactionCount": 3, + "digest": "72c71c8b75354f4d869144a796feb46e71992e11903a6be98667d94638146c4b" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/InlineDiffPreview.tsx", + "interactionCount": 1, + "digest": "62b4e22a320c57cafc40cd098d6acc2dbff485acafc7b44632967eaec31fa5ed" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ModelSelector.tsx", + "interactionCount": 41, + "digest": "9b4e294e5e4cb4f76dba9102b202b2cdfb9fb0a1413d19c7defe7b89f4d58427" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/PendingQueuePanel.tsx", + "interactionCount": 17, + "digest": "1c6a9eb29ec14fd58be0a3c7c8249ea5f17ca8160ed2549ff12361e6aade61eb" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ReasoningPresetSelector.tsx", + "interactionCount": 11, + "digest": "feb9a2225f6112a8bc853cafee27967b44384291dcf09991ef93e165bdf402e8" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/RichTextInput.tsx", + "interactionCount": 2, + "digest": "f24910b9e8354d3c394fdc5035bb66e6e64d018918b90db7efa9629785e91114" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ScrollToBottomButton.tsx", + "interactionCount": 2, + "digest": "826f89cbe7e1b6478a33fb7134b4bf910064df64da42d3c690a0efedb509c2f4" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ScrollToLatestBar.tsx", + "interactionCount": 4, + "digest": "63d0507b079412f4fda2f44bf23cd90e95d69476c429e00ba98a077d291f7a8b" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/ScrollToTurnHeaderButton.tsx", + "interactionCount": 2, + "digest": "b641196d646a0bd1a5f5abf77ee3d3fd5859f4b12d1a0473c5f15cec1c7c3ee0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/TaskDetailPanel/TaskDetailPanel.tsx", + "interactionCount": 2, + "digest": "01dfa8acbf611baaeed5fce484d1569aca6f1386dde2759c92a1baa39e9e22f2" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/WelcomePanel.tsx", + "interactionCount": 18, + "digest": "7707f5defa1a80b93cff01b9fee3287c62bcfdba5c45fd5ead522f9878edfe80" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/background-command/BackgroundCommandInputDialog.tsx", + "interactionCount": 11, + "digest": "740905c53bc4f8ded4f43597129c72cc142061bf2dde0a7f2d74e18969f5bb21" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/background-command/BackgroundCommandOutputPanel.tsx", + "interactionCount": 19, + "digest": "8a026d1e6306329d098fe8b825f35583bee48dd62408d357b3e9dc83b02f8b74" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/btw/BtwSessionPanel.tsx", + "interactionCount": 11, + "digest": "728781e6f319761696c70d66829d05e7e964376f6cc50142412a17a167a30647" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/ExploreGroupRenderer.tsx", + "interactionCount": 1, + "digest": "46424042c7dd88a7e38ce26a4a5bef28861de9b841553fba674ea10ee415db47" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/ExportImageButton.tsx", + "interactionCount": 5, + "digest": "5e859ef0ce860d25cf281eeee04733663932fbdee89a8ad856a5249b4fea8f62" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/FlowChatHeader.tsx", + "interactionCount": 49, + "digest": "1a2907522c75ea3b8faeb75ca1a0db41d2578473cc02e25353b1e92e7f4db6bf" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/FlowChatTurnRail.tsx", + "interactionCount": 4, + "digest": "5fb3b45bcac51fa05bf76334599f8a760c7d8b203c1c79e6b6ac9bc138ea945d" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/ForkSessionButton.tsx", + "interactionCount": 2, + "digest": "bb83c3a72352b6f210ab81246c79e4ea34b8584229cf148c9fea1e296269467f" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/HistorySessionPlaceholder.tsx", + "interactionCount": 3, + "digest": "19479a97c3793ba8bfaab7c3d9e30253fa8bd947ac7e87e152d41b13063e3d16" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/ModelRoundItem.tsx", + "interactionCount": 25, + "digest": "d866878512276fe5dd60e2565f1a313ad44000e4a20a287ac75b3cb31a8ada35" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/SessionFileModificationsBar.tsx", + "interactionCount": 3, + "digest": "c855039aafcb5243552367fef76f9e89210c08b88564a4a9b21a77a39a9fae42" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/SessionFilesBadge.tsx", + "interactionCount": 16, + "digest": "3aaef095190aaa169159c74205e9365b44799a9e1dee7e152c8e8b467a98b430" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/SessionTreePopover.tsx", + "interactionCount": 16, + "digest": "b8adeee39b3a2c08d6802e8757b0e9e8379c39e2bb840ba5a8937ae102bb2a58" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/TurnFailureNoticeItem.tsx", + "interactionCount": 6, + "digest": "53aaa0bd4fcaa5dfed0ad893b32446c4420738b851172aa3ca59a64609b9cb94" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/UserMessageEditComposer.tsx", + "interactionCount": 20, + "digest": "549b6219395d1db73da5d4ce36161b2c8d398627546e42c8f7087780cc118721" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/UserMessageItem.tsx", + "interactionCount": 17, + "digest": "cfc8d1aa30ab67d7a166bbad1a205792cd909e5f2cf356310ec3ce7ef8ddd483" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/modern/VirtualMessageList.tsx", + "interactionCount": 2, + "digest": "5c9b6c5f733b4228591a24937166d511089960e281ac71826daaa8fe047c12d4" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/session-menu/SessionMenu.tsx", + "interactionCount": 8, + "digest": "c1e7a5399f931af0f03c95c56bb482c37361a59f35dfb090f025ee11b625ac52" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/smart-recommendations/SmartRecommendations.tsx", + "interactionCount": 4, + "digest": "7972f5d0bc2d74d5876c136eda12451b674959eb39f8329cff779855540f6977" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/subagent/SubagentProjectionView.tsx", + "interactionCount": 3, + "digest": "a5023e05d0fc4d3ec1c7442cd53bb692691c6523345d9713e34ab62677f0448e" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/thread-goal/ThreadGoalDialogs.tsx", + "interactionCount": 18, + "digest": "61d4eb7622aaaacd046ccc0cc430cbdecc72549ff1ceee1253f0aa095a6b95f5" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/toolbar-mode/ToolbarMode.tsx", + "interactionCount": 21, + "digest": "80e4cb2cd0d095173df1b2850cd34ddac4370fd894c4a09a9ca122eec03066f8" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/usage/SessionRuntimeStatusEntry.tsx", + "interactionCount": 3, + "digest": "f1b220a6d690806dcbf34c367ccbac59cc61b5624b861031cbd185cea84cdb91" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/usage/SessionUsagePanel.tsx", + "interactionCount": 29, + "digest": "69a6a7f0616cf4b9094664301b27234cd28600239ab7ce69c74d44158d335b34" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/usage/SessionUsageReportCard.tsx", + "interactionCount": 21, + "digest": "27eeee24f33ba9a06cc740252c9094a7c5d8e363aa687a08df97c610bcab1c5e" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/components/voice/ComposerVoiceInputButton.tsx", + "interactionCount": 12, + "digest": "912f007cb9fac9c349176ebb6360f18fb7e81de17340a5f300484dfc1fc7bf92" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/CapacityQueueNotice.tsx", + "interactionCount": 10, + "digest": "def22706a88bc8f6c14d6e694f1821e15c4bb26a23f2d44ca999d5304351929a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/DecisionExecutionGate.tsx", + "interactionCount": 9, + "digest": "779e06ab0d4cc00305257163603004ac192cd95b3ef5328a2484ec9244f44cca" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/DeepReviewActionBar.tsx", + "interactionCount": 8, + "digest": "fe39ec4f8e9303e69c811dd71a7b6d2231dbf7b77fbe9b50bf2073599f8de30a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/PartialResultsPanel.tsx", + "interactionCount": 3, + "digest": "4b107fe62097b73f0e0d027eef01130ad2dc7ce1b5ca7f9f79b44eba1ae1a102" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/RemediationSelectionPanel.tsx", + "interactionCount": 16, + "digest": "d84d2e44562993eb396b21ef35536050873dba59960d72097d50cb215031167f" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/ReviewActionControls.tsx", + "interactionCount": 24, + "digest": "310f78972e8461acc45db4af9b2e7bbda4ab100dcc2d14992970ae667ba9ac5d" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/deep-review/action-bar/ReviewActionHeader.tsx", + "interactionCount": 3, + "digest": "44984b125c1c24f3b7770077ee150633930a50e7687ba55894ad48c13313aeae" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/services/AgenticEventListener.ts", + "interactionCount": 1, + "digest": "7f8e6aeea2c70ee8c127464d6670b432cd88d2e21db9b00ac6a9ba2155a62ffe" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts", + "interactionCount": 2, + "digest": "5f7bc8e43b6cd842a9cac3617e2f6391d321f5540dfaf61d055de1c0d5c07a98" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/session-stream/SessionStream.ts", + "interactionCount": 3, + "digest": "7ad83a19901b2cb043e00d7d392173f231ba326a6a59db204c6631972d312ff6" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/session-stream/turnOwnership.ts", + "interactionCount": 3, + "digest": "82af9709dc32ecf55c105e748a21efdb93be6114efeb695aac6975bc0d5c0df3" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/AcpPermissionActions.tsx", + "interactionCount": 5, + "digest": "63b1a4021843d657ff5861199a947fc776bfcfcff1253c726eeaac9e94f334f4" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/AskUserQuestionCard.tsx", + "interactionCount": 23, + "digest": "51d4a6e5c3c649963ab4b6c13624c135ffebfcd4db2db2a4a91c47530987e9f9" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/BaseToolCard.tsx", + "interactionCount": 1, + "digest": "80de0b878be5b0025e41687ad72c26cca20d2b90db996fb23b1cc9452e07b2c0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/CanvasToolCard.tsx", + "interactionCount": 1, + "digest": "e90fc0f453b1983f6b7436caa506b4115019979c7b4dfcf5f2a89cb6532c4348" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/CodeReviewReportExportActions.tsx", + "interactionCount": 14, + "digest": "a92fe110f3e7a04f7e652f5b7d0721e6acf7e1983fc5768801158f274b0ee064" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/CodeReviewToolCard.tsx", + "interactionCount": 9, + "digest": "bdb74b0158ad1de6a0c2f79419165ab8bfacb5a060dad95118b9f91d7bbef8c8" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/CompactToolCard.tsx", + "interactionCount": 2, + "digest": "3339877a57ed4bd416aee74cf7a69e6b7248332c3539513d390274f3575aff3a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ComputerUseToolCard.tsx", + "interactionCount": 4, + "digest": "cc74419def0013e9c698ee7869e1f2ab90510a131e578ec1e65a5775bf05feeb" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/CreatePlanDisplay.tsx", + "interactionCount": 15, + "digest": "75d184756c8b11b85bbca7d69d775356bd8721c670aab497e3cb3b5a3212bb01" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/DefaultToolCard.tsx", + "interactionCount": 1, + "digest": "a9dfb311157a83d145d67325ca94bdeb6184cfac1f2483a357979538dd593423" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ExecProcessToolCardView.tsx", + "interactionCount": 1, + "digest": "80de0b878be5b0025e41687ad72c26cca20d2b90db996fb23b1cc9452e07b2c0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/FileOperationToolCard.tsx", + "interactionCount": 7, + "digest": "bf50630ac42b691eb646cfaff9732c55a063a2627955c8d25cf2c135d326f4c6" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/GenerativeWidgetToolCard.tsx", + "interactionCount": 4, + "digest": "d52f97df234cb09ef79c566d4e2bba6a6799096d575b2bf85df53ae44f9bccb0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/GetFileDiffDisplay.tsx", + "interactionCount": 1, + "digest": "80de0b878be5b0025e41687ad72c26cca20d2b90db996fb23b1cc9452e07b2c0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/GitToolDisplay.tsx", + "interactionCount": 1, + "digest": "80de0b878be5b0025e41687ad72c26cca20d2b90db996fb23b1cc9452e07b2c0" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/GlobSearchDisplay.tsx", + "interactionCount": 1, + "digest": "26187ac580124d6512ada8e352984e5a71fd5f0d8cd06f8e3524bcb0f6ec410b" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/GrepSearchDisplay.tsx", + "interactionCount": 1, + "digest": "26187ac580124d6512ada8e352984e5a71fd5f0d8cd06f8e3524bcb0f6ec410b" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/LSDisplay.tsx", + "interactionCount": 1, + "digest": "26187ac580124d6512ada8e352984e5a71fd5f0d8cd06f8e3524bcb0f6ec410b" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/MCPToolDisplay.tsx", + "interactionCount": 3, + "digest": "e4f2b1310972a9daa5f529012f37e282a635e7aa1f60bad94fba46a9ba13207e" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/MiniAppToolDisplay.tsx", + "interactionCount": 4, + "digest": "332aec436e34d04b0dee932ec792b02ecb992f1368bd0e1c5691e3a23dbba97d" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ModelThinkingDisplay.tsx", + "interactionCount": 2, + "digest": "5c6dc46d0d1933de857f3c966368b1369b21010aa7fb66d7aad5add841bcef93" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/PageDeployToolDisplay.tsx", + "interactionCount": 4, + "digest": "cbea2b453c161d4ae7df7e70f800d5d7264f45d4116936305915e6a798dd9817" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/PagePublishToolDisplay.tsx", + "interactionCount": 7, + "digest": "0a39d59f714161b10b52f249341688120e84079fc224fe017c5451b971d502b4" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ReadFileDisplay.tsx", + "interactionCount": 1, + "digest": "d1b438960d0d9809abdf035e070581273810871bc637f6f29b0020d4471a5201" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ReviewSessionSummaryCard.tsx", + "interactionCount": 5, + "digest": "79574e65638dd8f7bfdc50b23aff228485a6e5593051fba12ef82a073be4d1a9" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/RunCodeToolCard.tsx", + "interactionCount": 1, + "digest": "a9dfb311157a83d145d67325ca94bdeb6184cfac1f2483a357979538dd593423" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/SessionControlToolCard.tsx", + "interactionCount": 1, + "digest": "56e4d6577600cdcf762fe725cdd628ec0073e7952ae62247d547a0800c368e9c" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/SessionMessageToolCard.tsx", + "interactionCount": 1, + "digest": "56e4d6577600cdcf762fe725cdd628ec0073e7952ae62247d547a0800c368e9c" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/SnapshotFullscreenDiffViewer.tsx", + "interactionCount": 17, + "digest": "12369bf685d3a2d640e5034cd1492d34e1143a99a47691a80538d2314de9a026" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/TaskToolDisplay.tsx", + "interactionCount": 7, + "digest": "22e4abf3ce92bdf4bc06bb5c96f89667387ceb48bf2a6524019b1db5054c975e" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/TerminalToolCard.tsx", + "interactionCount": 5, + "digest": "2554256c2909aceb8a3f45dab8e245ff1d89e7c9bf8b7bbbf5de279feec2d001" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/TodoWriteDisplay.tsx", + "interactionCount": 1, + "digest": "a0373f791fe21572e6bfeb652a02dd432574ed16e350476ee23d62534a3a11a4" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ToolCardHeaderActions.tsx", + "interactionCount": 3, + "digest": "967db492728fe80c3773e0d12c4c45282eea13edd771b1469d66f23da1b0762d" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ToolCardIconSlot.tsx", + "interactionCount": 3, + "digest": "336e58316520dbe407edbf86a7bfe0ac6c96415c29881cedb9c5ea92c3820a1a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ToolTimeoutIndicator.tsx", + "interactionCount": 15, + "digest": "dda88b1c48b78668ae918141f69a3c0f774465f0cdec1fa4d0150acc4e1b8633" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/ViewImageToolCard.tsx", + "interactionCount": 4, + "digest": "e0eddeea9c114cdadbf5a72bbf990aaf6487c2e94e7c0c2f1ce6c368a12da184" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/WebFetchCard.tsx", + "interactionCount": 2, + "digest": "3ac7421cebac716f6102aaae2c5e591eebcf87c259abc598b6b78bdc43a07a14" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/tool-cards/WebSearchCard.tsx", + "interactionCount": 2, + "digest": "3e656cfb5cbfc90e5a5fc498a800e873918c8455837cc265cd8f5c349f0d78e2" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/utils/captureElementToDownloadsPng.tsx", + "interactionCount": 3, + "digest": "336e58316520dbe407edbf86a7bfe0ac6c96415c29881cedb9c5ea92c3820a1a" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/utils/chatInputMode.ts", + "interactionCount": 2, + "digest": "29ab9a456e810a6ddf439bf2cfeab366ff8cfb744a8b0031af53a14ab704a010" + }, + { + "sourceFile": "src/web-ui/src/flow_chat/utils/slashActionSelection.ts", + "interactionCount": 1, + "digest": "b5331eaa8fefaab28fc3477fc218c2e930f9e29f1cfdc1d4480d9fa303226bb7" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/api/service-api/AgentAPI.ts", + "interactionCount": 1, + "digest": "7b8411ac6473bc5bae2bfee0b113b4dc11f33c68a922b4fe080deb874aeb6ec9" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/AcpAgentsConfig.tsx", + "interactionCount": 50, + "digest": "85c9019dcd019026bfc5c3556d2182667111ba9b5af0244236804d08ddffe1b8" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/AppearanceMarketDialog.tsx", + "interactionCount": 25, + "digest": "df7513e26d2c633380d27546c3263af139d9cb2a4c91b97aa8f2b81b24eb1124" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/AppearanceMarketWorkflows.tsx", + "interactionCount": 36, + "digest": "c6aaa9cd48b97389765e0ca2dc9a0d332dece4ed6cccca3c30eea06fcf5c6500" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/AppearancePackageConfigSection.tsx", + "interactionCount": 15, + "digest": "2d5ef58f587a800f4531e75cea6269c578ed8afec691803f230d41c8a3210af8" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/AppearanceSettingsPage.tsx", + "interactionCount": 6, + "digest": "25031f404d44559835a0f5be95862a1261e8c44ed0faa80fef4263f91a70dfc0" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ApplicationSettingsPages.tsx", + "interactionCount": 28, + "digest": "a8450df3e5b2e2dd8d2cd88d3bd7fc3d1c1fb3a5bc85e57c4181c8840ab8d01c" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/DefaultModelConfig.tsx", + "interactionCount": 8, + "digest": "a4bd861b41cd2d363d95544836c88e06d0df6ad79f3b0848289e69f597a59862" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/EditorConfig.tsx", + "interactionCount": 43, + "digest": "3017f3c917babdc71d6c5605fa4b0580214fc3e803e56c21053b314a59b4bb27" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ExternalMcpOverview.tsx", + "interactionCount": 10, + "digest": "6528b24dc28ce3d18f5d1e871d6a629ddd45325e549d59df78f494f7682401e7" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ExternalSourcesConfig.tsx", + "interactionCount": 97, + "digest": "9c8722ecf069d8421640858fa61e4b09bc227a07cfcc9530b598fdbbb9b5c979" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/GlobalPermissionRulesDialog.tsx", + "interactionCount": 23, + "digest": "346a4b4bbd486716f40111c0d4297a642870011d1a8932b96296a905e610bdd6" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/HooksConfig.tsx", + "interactionCount": 21, + "digest": "e253a2b2db557e534e7c69f2e6108aedc9a4bb54bde002de77f21d90e5782a06" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/LocalVoiceModelsConfig.tsx", + "interactionCount": 10, + "digest": "c973526c84c73d048e5759050ac5c0b0b63e9fb26f6d6909bc5d09717da52191" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/LspConfig.tsx", + "interactionCount": 10, + "digest": "23120608db3c46d70af9b5d693cc14de002ab72d693741cc38c0756c02734d35" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/MCPResourceBrowser.tsx", + "interactionCount": 7, + "digest": "309d08c5c7fa5c7879a75817b2535ef091d4b5cd23598fc780fe0dcdd075049f" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/McpToolsConfig.tsx", + "interactionCount": 30, + "digest": "c6ff3769f4cbeb67f8429bd598eb2d4ddc5d8c305e03a09f656a98fb01aa5a94" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/MemorySettingsPage.tsx", + "interactionCount": 26, + "digest": "b2e66d55d31b5ccf6714a150f1570126bc8257305d509cee0e113b6ddad66188" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ModelSelectionRadio.tsx", + "interactionCount": 11, + "digest": "376f4390a69eb471cdd2b6c7168e47b0b9f10f4d0059e15af1d31a1c4a2641d2" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ModelSettingsPage.tsx", + "interactionCount": 148, + "digest": "19e5543a9d29e85888dd15ed1ef89972d7c6f5870c0df02618525044e0e89f18" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/QuickActionsConfig.tsx", + "interactionCount": 21, + "digest": "ddeedc033984f20229d762d2f66a054c47716503eb2d9817a923cf588a5d49d8" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ReasoningConfigPanel.tsx", + "interactionCount": 4, + "digest": "ae273486dc30b0ffdaa154e52bff34482a3dfe5077c7d914fde2dd5f9f86d6f6" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ReasoningPresetEditor.tsx", + "interactionCount": 47, + "digest": "16e28ca81dd36dd03825ba9fa98c9e3a3b7f9609b10eef8c48756b35a3662c98" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ReviewCapacitySection.tsx", + "interactionCount": 3, + "digest": "7ed57719f518829216b02649cbe308a546a5ddc0e744c2afe96c867aadef97be" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/RuntimeSettingsPages.tsx", + "interactionCount": 61, + "digest": "a8fe0d61eebca6089d202105121e094cd3dcc1b686f40e12b83955e56576fa84" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/SessionTitleConfig.tsx", + "interactionCount": 4, + "digest": "e767d412d7c167e989d3f1ba13de93759ce52dd7a27767603806b6f026c724d0" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/SkillsConfig.tsx", + "interactionCount": 26, + "digest": "bc89b1feb9ea9742bbee8baf6a94594327a87abf3cae2c8d0edcfe40514c2f52" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/ToolJsonRepairSection.tsx", + "interactionCount": 2, + "digest": "87c228bc172e9c94a8da629424861c4be4be624ed470bfc28e84d273c0f7ede0" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/UsageStatisticsConfig.tsx", + "interactionCount": 12, + "digest": "8dbdabc85f9522b362facf6cf76a4423e255dc32cf714247ce6e0343014b1914" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/VoiceInputConfig.tsx", + "interactionCount": 11, + "digest": "3d78ff50acf0dc20a11d3602d06452db0feed896633eb9b07c6a8a2f54b6de4b" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/VoiceInputDiagnostics.tsx", + "interactionCount": 6, + "digest": "d880418ff8493e5088f0019901b805b787d0ead8eeef9537b9cc5035136e4d88" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/WorktreeSettingsPage.tsx", + "interactionCount": 21, + "digest": "fed0041824dfb62b015ffd94003b5ee92a038ddc32ba1e3dfe8007afe7fc6086" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/common/ConfigCollectionItem.tsx", + "interactionCount": 3, + "digest": "910d0f28c50e3445c714bffa8c3d51a77410673feb4ee088acce0f3ab216dc7a" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/external-sources/ExternalAppsOverview.tsx", + "interactionCount": 7, + "digest": "8d0a6a8129a6b8bfd74db95374d62831f593a9175602acd18d0849657d5cf0ef" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/external-sources/ExternalCommandConflicts.tsx", + "interactionCount": 2, + "digest": "b57cc16f5f9834355e246c6e447e84b968a8e495ce07f229095feafb6097ef17" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigActions.tsx", + "interactionCount": 6, + "digest": "e6091de1a092f094b0b50cd7ecbced67083be38bb2b4eff37656a1c335d9a333" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigCheckbox.tsx", + "interactionCount": 1, + "digest": "dfbe8ba18f96bfe2f3b74d093dede0c35b41da1e58f4374b9cb74e604392d9ed" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigForm.tsx", + "interactionCount": 1, + "digest": "a2c996449184bac4d0fa8fef84195b9429307b2b8738e8bf0f5815ff45b254c5" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigInput.tsx", + "interactionCount": 1, + "digest": "e3b20b2c575ae8beb150b67967227c9027f71cba31d09a098a202a0860b780e3" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigSection.tsx", + "interactionCount": 3, + "digest": "8e6b42ca7ddd7d62e7717856fbb1d2edf6a0fe283586241272ca9fbcd8e2250b" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigSelect.tsx", + "interactionCount": 2, + "digest": "30c1652c930288599f00a923456322a17e56c8ae21510f61a81a9e94ab3d709f" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigStatus.tsx", + "interactionCount": 2, + "digest": "2c9b70c5a389779f6a41ab0f2439fbd2feca590229c5cca960fd2ef180d360e4" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/config/components/form-controls/ConfigTextarea.tsx", + "interactionCount": 2, + "digest": "afcab9d0f51389fddd83dce562be344f06845f341e180a3b8bc356df86c0a4fa" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.tsx", + "interactionCount": 21, + "digest": "78505138644521f6c4222856343360abf5d8fe7f59c4eb1eda24ccf7521ddfe7" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/i18n/components/LanguageSelector.tsx", + "interactionCount": 7, + "digest": "eb90e3c1b746399a5717f94640993d5f9016a523d8a329c9aefc50014529f323" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/peer-device/DeviceSurfaceSwitcher.tsx", + "interactionCount": 11, + "digest": "5619cfff8371c84bf77615c8a587bfd1fbd21296642dd3af429cfc7358beb3e4" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/peer-device/PeerDirectoryBrowser.tsx", + "interactionCount": 25, + "digest": "ba7ba8343e2259c0ee54439a13c147cb1534bba4e1f007f5cbdfa4abb171ee34" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/peer-device/PeerDirectoryPickerHost.tsx", + "interactionCount": 1, + "digest": "a16ae4098ce174439657f44f94c246fd6a29da2c57f8fb09d12461375730da42" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/peer-device/runtimeSessionEventGate.ts", + "interactionCount": 1, + "digest": "1ad4712c0508ac87f02e99984ddc8edc1de21825c592c4811e4557c772bed4f3" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/providers/CoreProvider.tsx", + "interactionCount": 2, + "digest": "8ea0dae2a8416c7d073f3ef574ae1af40d5e093ac503f889509c3e71c77dc972" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/update/UpdateAvailableDialog.tsx", + "interactionCount": 5, + "digest": "8040f108b897b87b8a544a54c322d61cba13320f3f0eb7c15049c386703300d4" + }, + { + "sourceFile": "src/web-ui/src/infrastructure/update/UpdateInstallProgressModal.tsx", + "interactionCount": 2, + "digest": "5dfdfb847ee8c285f1ef0aab7df64324c79970aad2060c81defe1f9ffb7e8ff9" + }, + { + "sourceFile": "src/web-ui/src/shared/ai-errors/aiErrorActions.ts", + "interactionCount": 1, + "digest": "5d927f55b447532af8f138334a36ef4a6421ac89e843c1fd4d7ca983dabca311" + }, + { + "sourceFile": "src/web-ui/src/shared/announcement-system/components/AnnouncementToastItem.tsx", + "interactionCount": 6, + "digest": "f6cd8c778d1ebc36eef53e7497262686b11a45b2babff93fe33d32aa949f46d5" + }, + { + "sourceFile": "src/web-ui/src/shared/announcement-system/components/FeatureModal.tsx", + "interactionCount": 17, + "digest": "64873cd0d52d6695a1bc0f9714616e7c1810014db2875c105c1a315661d3a7e1" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/components/ui/ContextMenu.tsx", + "interactionCount": 5, + "digest": "ca35c570fe3512c337cd1ba28fc1bd215c7c7fccbe4b6ca9cf85a12e013d3f0a" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/core/ContextMenuRegistry.ts", + "interactionCount": 2, + "digest": "88a6d9edd325c04e184c4837c9070f678830a535819b3b43a181ce058456042f" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/core/MenuBuilder.ts", + "interactionCount": 1, + "digest": "36563ca975b14d289f5ff05d5360a257aaa7f47589373f952da4aa13947a7cd2" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/EditorMenuProvider.ts", + "interactionCount": 2, + "digest": "6af7643a21c2bc21b0f4dc3e0a96016ee42b9c5a7b8dd641929093060c8f41b0" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/FileExplorerMenuProvider.ts", + "interactionCount": 1, + "digest": "962dc043ea72e800e2ec60c347a76de82a55acfec3487d1b08152df90f207f49" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/FlowChatMenuProvider.ts", + "interactionCount": 1, + "digest": "962dc043ea72e800e2ec60c347a76de82a55acfec3487d1b08152df90f207f49" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/GlobalMenuProvider.ts", + "interactionCount": 1, + "digest": "dc017ceff0389ea583fcb8cc0f978ade68b4fb443270516f68aa3ac6f5aa8f18" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/SelectionMenuProvider.ts", + "interactionCount": 1, + "digest": "962dc043ea72e800e2ec60c347a76de82a55acfec3487d1b08152df90f207f49" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/providers/TerminalMenuProvider.ts", + "interactionCount": 1, + "digest": "962dc043ea72e800e2ec60c347a76de82a55acfec3487d1b08152df90f207f49" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/types/provider.types.ts", + "interactionCount": 2, + "digest": "ae5e5766511afcc484ffb0b9803b4ff3bfed474dda2c993088ca73f41a8d499a" + }, + { + "sourceFile": "src/web-ui/src/shared/context-menu-system/utils/menuBuilder.ts", + "interactionCount": 4, + "digest": "5cdeedf488700cb1244947f7053abd49caaae0cd2054f612a03a2d906a4a577a" + }, + { + "sourceFile": "src/web-ui/src/shared/context-system/components/ContextCard/ContextCard.tsx", + "interactionCount": 2, + "digest": "6ed1e248afe87ec694da824710c65234088cb76c66fb5a96471fb578a7a1b344" + }, + { + "sourceFile": "src/web-ui/src/shared/context-system/components/ContextList/ContextList.tsx", + "interactionCount": 3, + "digest": "8dbeb63ae835bfc050bac7b8061ce9897b47b1abe8b6ea6c2b62119977e9cc64" + }, + { + "sourceFile": "src/web-ui/src/shared/context-system/core/types/CodeSnippetContextImpl.tsx", + "interactionCount": 1, + "digest": "596a703135d03aefdc877c8db21f35e8f46d043d078e73e45df3e65b7bffd8f0" + }, + { + "sourceFile": "src/web-ui/src/shared/context-system/core/types/ImageContextImpl.tsx", + "interactionCount": 3, + "digest": "4cef10b2eefb34695fa47c5dfcc93e59e364b0d4e7ff5e9ed6c88d13d280a4c3" + }, + { + "sourceFile": "src/web-ui/src/shared/context-system/drag-drop/ContextDropZone.tsx", + "interactionCount": 1, + "digest": "fd67f9bcd3959414dc973a3f44b062e3fc342c477a7492b59c0e98ee82343cb9" + }, + { + "sourceFile": "src/web-ui/src/shared/notification-system/components/LoadingNotification.tsx", + "interactionCount": 2, + "digest": "1786afbe5ae70fbb7aad1ccb96981e45c119ab7357d18071e20edcc1ccf6ae9e" + }, + { + "sourceFile": "src/web-ui/src/shared/notification-system/components/NotificationCenter.tsx", + "interactionCount": 22, + "digest": "8429f28fe0db130eb26bfd3285d873a8185ed55e5e255636e6fc03a62b31b6d5" + }, + { + "sourceFile": "src/web-ui/src/shared/notification-system/components/NotificationItem.tsx", + "interactionCount": 4, + "digest": "96f8ff7986424877d2562ded3fbe5384c2bdfb9ecd29119bc25df19e0624103d" + }, + { + "sourceFile": "src/web-ui/src/shared/notification-system/components/ProgressNotification.tsx", + "interactionCount": 2, + "digest": "1786afbe5ae70fbb7aad1ccb96981e45c119ab7357d18071e20edcc1ccf6ae9e" + }, + { + "sourceFile": "src/web-ui/src/shared/services/ide-control/api.ts", + "interactionCount": 2, + "digest": "05ce070fd91faaec839b8195d8e73bd40fa1e915cc0add0f30d29499756296e4" + }, + { + "sourceFile": "src/web-ui/src/shared/utils/chatContext.ts", + "interactionCount": 1, + "digest": "6a00a0b4ebf9e19811a69446b8011285a1df0664e747ba6d10e66b3aed6b0048" + }, + { + "sourceFile": "src/web-ui/src/shared/utils/tabUtils.ts", + "interactionCount": 1, + "digest": "5d927f55b447532af8f138334a36ef4a6421ac89e843c1fd4d7ca983dabca311" + }, + { + "sourceFile": "src/web-ui/src/tools/bitfun-canvas/BitfunCanvasPanel.tsx", + "interactionCount": 9, + "digest": "4ec861730c1f859e3335a04ae5d88ab71a875435a53beafdf991f55cc1fbf32c" + }, + { + "sourceFile": "src/web-ui/src/tools/bitfun-canvas/runtime/sdk/controls.tsx", + "interactionCount": 6, + "digest": "2e5af0e50153df5b3f323b526171b1e60bc08be46fbc1af383005bcae32dfd90" + }, + { + "sourceFile": "src/web-ui/src/tools/bitfun-canvas/runtime/sdk/data-display.tsx", + "interactionCount": 9, + "digest": "c26a957db3e52f2463b1a8875364942dd3b0493f1000b8c8bc0a3fe8aac1a8eb" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/CodeEditor.tsx", + "interactionCount": 4, + "digest": "f5649543b779a51fbafcc155ec4914bd7895fdd61cc51b03438f5e46c0587a8a" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/DiffEditor.tsx", + "interactionCount": 6, + "digest": "b414fc41173a9cf8821c09e4f3f4c13b6cf7075b7b20505fbd153c75cebab499" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/EditorBreadcrumb.tsx", + "interactionCount": 5, + "digest": "ea0c793a4c1f393a242252c2bae93cd0843988a8478580d601a1b0861ef72dd8" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/EditorStatusBar.tsx", + "interactionCount": 4, + "digest": "1c1fa501fec12c21def54f40ea0ac3104456122bb86ee62364634c1edfc749ad" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/ImageViewer.tsx", + "interactionCount": 12, + "digest": "d1015fe3aa37291756a244c64da569c56fa79a39c3225d7a30c35b60e02e2126" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/MarkdownEditor.tsx", + "interactionCount": 21, + "digest": "d42b30d8e5afd1e440ee2e17430ea955d03b879f796eba878c7cc5f0fe3dd5d9" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/PlanViewer.tsx", + "interactionCount": 30, + "digest": "6db25c91d12f6914d1c1c7a54e27880b6ae6546991563a5a374899ec3df57cf9" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/ReadOnlyCodeBlock/ReadOnlyCodeBlock.tsx", + "interactionCount": 1, + "digest": "84ae9fbe9daed0037da02c57d0a8d182934bef56023b6d4b9ca5a5d81fde2d46" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/components/StatusBarPopovers/StatusBarPopovers.tsx", + "interactionCount": 17, + "digest": "650e6c96d639f5d1d404211a2ecb00a934836154171da4cc8c89ec6875c948e8" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/meditor/components/EditArea.tsx", + "interactionCount": 4, + "digest": "3c7d2039e97d629678f32622c7f36bc67d004ea071a31a070200f8134e2c9e5b" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/meditor/components/InlineAiPreviewBlock.tsx", + "interactionCount": 9, + "digest": "7682578cdecd1fa125e09b6b4eb905a2dd50d3307a4610b810faa9d4ba087af3" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/meditor/components/MEditor.tsx", + "interactionCount": 11, + "digest": "e3e0792e48e2ae6464bc8b4ecdbf3a1bc82c16bb79a4722702d3e25191a85f7b" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/meditor/components/TiptapEditor.tsx", + "interactionCount": 18, + "digest": "14371ce420ec4dfe14fa3ad1878679a9576be5fd0997a05cdc57a00f838ee31d" + }, + { + "sourceFile": "src/web-ui/src/tools/editor/services/ActiveEditTargetService.ts", + "interactionCount": 7, + "digest": "28df7133a9ff262e3fbe16c8a3603155cff295e14c9827a3f914b26bf943fdd3" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/FileExplorer.tsx", + "interactionCount": 9, + "digest": "364c3516ec5ee27d38bb7e90352348ba4b1a4870a9187c48f99990e34917b78a" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/FileSearchResults.tsx", + "interactionCount": 10, + "digest": "38d40c7962e6d77dbf8a625cb2323464eae82ab61bc087802f26fd5a3f194533" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/FileTree.tsx", + "interactionCount": 1, + "digest": "9242a66e148486660e68f09171641f6aafa0c5987bddb8644e5812f18ce3c2ce" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/FileTreeItem.tsx", + "interactionCount": 9, + "digest": "e61e8191c41535432fd27b54e7d806ab45a6e1c163ee9a564a54fd42815bd0db" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/FileTreeNode.tsx", + "interactionCount": 2, + "digest": "a91a917033bfff27a66b9a15f395b53a2b25e1c13aaa05d8a7e02eb9972a084c" + }, + { + "sourceFile": "src/web-ui/src/tools/file-system/components/VirtualFileTree.tsx", + "interactionCount": 2, + "digest": "46330b4db8334c2d5453337abe446e82cc507a4c1844cccd5de9867ba22c28a5" + }, + { + "sourceFile": "src/web-ui/src/tools/generative-widget/GenerativeWidgetPanel.tsx", + "interactionCount": 8, + "digest": "dc26d9a28d6272c6a0c0c62324fda9807da67a9f3fabddcb9d4bef3c556e2157" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.tsx", + "interactionCount": 7, + "digest": "4c6c84b4f71230d14a2d986c2f90323dca9a239b2a51802300683c01e6834786" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/GitBranchHistoryView/GitBranchHistoryView.tsx", + "interactionCount": 13, + "digest": "c07b23dea843bec1b456da9b627738a78bb057f939daae6a73f77d0e4cb3b891" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.tsx", + "interactionCount": 11, + "digest": "eda3fd3fe05382dceed82ed188991b49e99c8cfb4ee8c4fb270a8a8ef627122e" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.tsx", + "interactionCount": 9, + "digest": "dafd26be87896a2fd6107c5a41c37e463c2dc65745deaae07dd94be910f03c0c" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.tsx", + "interactionCount": 25, + "digest": "def315fbe8f3babb50978509bb54f34310947f1d51daa65887576dc379e6d90d" + }, + { + "sourceFile": "src/web-ui/src/tools/git/components/PushButton/PushButton.tsx", + "interactionCount": 12, + "digest": "7a83675c6693beb49f8b41f8209175830b7637ff54442a706766469cd5088bae" + }, + { + "sourceFile": "src/web-ui/src/tools/lsp/components/LspPluginList/LspPluginList.tsx", + "interactionCount": 6, + "digest": "16b654b54d296e41aa421b57a2d160b7834dbd499c9f8b68b5b93b46d3d636a0" + }, + { + "sourceFile": "src/web-ui/src/tools/lsp/components/ReferencesPanel/ReferencesPanel.tsx", + "interactionCount": 3, + "digest": "5d6404dcad9f4764b13ae606f8ad6bbb929e844ff23ec459c70ab82d5be6e028" + }, + { + "sourceFile": "src/web-ui/src/tools/terminal/components/ConnectedTerminal.tsx", + "interactionCount": 6, + "digest": "f150df201ad5d57ec8e80220384889749f70b2fe1090e71b994ebff77053efbf" + }, + { + "sourceFile": "src/web-ui/src/tools/workspace/components/WorkspaceManager.tsx", + "interactionCount": 10, + "digest": "ce40c43c7f377eba85f32535f29d478680269689dd4fc46f57918aeb378de58d" + } + ] +} diff --git a/package.json b/package.json index f375e52f4c..5b439043d0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "i18n:contract:test:ci": "cross-env BITFUN_I18N_CONTRACT_TEST_PROFILE=ci node --test scripts/i18n-contract.test.mjs", "test:ppt-live": "node --test src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/test/*.test.mjs", "i18n:audit": "node scripts/i18n-audit.mjs", + "capabilities:generate": "node scripts/generate-interactive-capabilities.mjs", + "capabilities:check": "node scripts/generate-interactive-capabilities.mjs --check", + "capabilities:test": "node --test scripts/interactive-capabilities.test.mjs", "iconography:generate": "node scripts/iconography/generate.mjs", "iconography:check": "node scripts/iconography/generate.mjs --check", "theme:color-audit": "node scripts/audit-theme-colors.mjs", @@ -116,6 +119,7 @@ "build:relay-page-auth": "pnpm run type-check:relay-page-auth && esbuild src/crates/services/relay-service/web/page-auth-client.ts --bundle --minify --format=iife --platform=browser --target=es2020 --legal-comments=inline --outfile=src/crates/services/relay-service/src/routes/page_auth_client.bundle.js", "test:relay-page-auth": "node --test src/crates/services/relay-service/web/page-auth-client.test.mjs", "website:dev": "pnpm --dir website run dev", + "website:test": "pnpm --dir website run test", "website:build": "pnpm --dir website run build", "website:preview": "pnpm --dir website run preview", "website:install": "pnpm --dir website install", diff --git a/scripts/check-core-boundaries.test.mjs b/scripts/check-core-boundaries.test.mjs index d81c13aa29..4661c0d1ac 100644 --- a/scripts/check-core-boundaries.test.mjs +++ b/scripts/check-core-boundaries.test.mjs @@ -1,5 +1,6 @@ -import { access, readFile } from 'node:fs/promises'; +import { access, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; import { spawnSync } from 'node:child_process'; +import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; import test from 'node:test'; @@ -8,6 +9,7 @@ import assert from 'node:assert/strict'; import { collectCargoMetadataGraph, collectCargoMetadataPackages, + discoverCargoManifestPaths, findCargoLayerViolations, findFeatureGatedTestTargetViolations, findProductEntrypointCoreFeatureViolations, @@ -64,6 +66,26 @@ const MODULES = [ const TEST_ROOT = join('C:', 'repo'); +test('Cargo manifest discovery ignores nested local-agent worktrees', async (t) => { + const root = await mkdtemp(join(tmpdir(), 'bitfun-core-boundaries-')); + t.after(() => rm(root, { recursive: true, force: true })); + await Promise.all([ + mkdir(join(root, 'src', 'crate'), { recursive: true }), + mkdir(join(root, '.claude', 'worktrees', 'other'), { recursive: true }), + mkdir(join(root, '.cursor', 'worktrees', 'other'), { recursive: true }), + ]); + await Promise.all([ + writeFile(join(root, 'Cargo.toml'), '[workspace]\n'), + writeFile(join(root, 'src', 'crate', 'Cargo.toml'), '[package]\nname="kept"\nversion="0.1.0"\n'), + writeFile(join(root, '.claude', 'worktrees', 'other', 'Cargo.toml'), '[package]\nname="ignored-claude"\nversion="0.1.0"\n'), + writeFile(join(root, '.cursor', 'worktrees', 'other', 'Cargo.toml'), '[package]\nname="ignored-cursor"\nversion="0.1.0"\n'), + ]); + + const manifests = discoverCargoManifestPaths(root) + .map((manifest) => manifest.slice(root.length + 1).replaceAll('\\', '/')); + assert.deepEqual(manifests, ['Cargo.toml', 'src/crate/Cargo.toml']); +}); + test('App Server TypeScript capability is owned by the protocol crate', () => { const appServerTs = coreClosedFeatureProfileRules.find( (rule) => rule.manifestPath === 'src/crates/interfaces/app-server/Cargo.toml' diff --git a/scripts/core-boundaries/cargo-dependency-boundaries.mjs b/scripts/core-boundaries/cargo-dependency-boundaries.mjs index 9c9cbdcaa4..594f88d33b 100644 --- a/scripts/core-boundaries/cargo-dependency-boundaries.mjs +++ b/scripts/core-boundaries/cargo-dependency-boundaries.mjs @@ -11,8 +11,12 @@ import { } from './rules/feature-rules.mjs'; const SKIPPED_DIRECTORIES = new Set([ + '.bitfun', + '.claude', + '.cursor', '.git', '.targets', + '.tmp', '.worktrees', 'node_modules', 'target', diff --git a/scripts/generate-interactive-capabilities.mjs b/scripts/generate-interactive-capabilities.mjs new file mode 100644 index 0000000000..8c0c774467 --- /dev/null +++ b/scripts/generate-interactive-capabilities.mjs @@ -0,0 +1,841 @@ +#!/usr/bin/env node + +import { createHash } from 'node:crypto'; +import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; +import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const SOURCE_PATH = path.join(REPO_ROOT, 'src/shared/interactive-capabilities/catalog.json'); +const DESKTOP_ROOT = path.join(REPO_ROOT, 'src/apps/desktop/src'); +const DESKTOP_LIB = path.join(DESKTOP_ROOT, 'lib.rs'); +const REMOTE_POLICY = path.join(DESKTOP_ROOT, 'api/remote_workspace_policy.rs'); +const SETTINGS_REGISTRY = path.join(REPO_ROOT, 'src/web-ui/src/app/scenes/settings/settingsRegistry.ts'); +const SETTINGS_TYPES = path.join(REPO_ROOT, 'src/web-ui/src/app/scenes/settings/settingsTypes.ts'); +const PRODUCT_ACTION_CATALOG = path.join(REPO_ROOT, 'src/web-ui/src/app/global-search/productActionCatalog.ts'); +const SCENE_TYPES = path.join(REPO_ROOT, 'src/web-ui/src/app/components/SceneBar/types.ts'); +const DOCS_ROOT = path.join(REPO_ROOT, 'docs/interactive-capabilities'); +const DOCS_CAPABILITIES_ROOT = path.join(DOCS_ROOT, 'capabilities'); +const PUBLIC_CATALOG_PATH = path.join(DOCS_ROOT, 'capabilities.json'); +const TECHNICAL_MAP_PATH = path.join(DOCS_ROOT, 'technical/tauri-command-map.json'); +const UI_INTERACTION_MAP_PATH = path.join(DOCS_ROOT, 'technical/ui-interaction-inventory.json'); +const RUNTIME_CATALOG_PATH = path.join( + REPO_ROOT, + 'src/web-ui/src/app/global-search/generated/interactive-capabilities.json', +); +const REQUIRED_INTERACTION_ROOTS = ['src/web-ui/src']; +const GENERATED_MARKER = ''; + +const checkMode = process.argv.includes('--check'); +const quiet = process.argv.includes('--quiet'); + +function toPosix(value) { + return value.split(path.sep).join('/'); +} + +function walkFiles(root, predicate) { + const results = []; + if (!existsSync(root)) return results; + for (const name of readdirSync(root)) { + const absolute = path.join(root, name); + const stat = statSync(absolute); + if (stat.isDirectory()) results.push(...walkFiles(absolute, predicate)); + else if (predicate(absolute)) results.push(absolute); + } + return results; +} + +function stripRustComments(source) { + return source.replace(/\/\*[\s\S]*?\*\//gu, '').replace(/\/\/.*$/gmu, ''); +} + +export function parseRegisteredCommands(source) { + const match = source.match(/\.invoke_handler\(tauri::generate_handler!\[([\s\S]*?)\]\)/u); + if (!match) throw new Error('Desktop invoke_handler registration block was not found'); + const entries = stripRustComments(match[1]) + .split(',') + .map((entry) => entry.trim()) + .filter(Boolean); + const invalid = entries.filter((entry) => !/^[A-Za-z0-9_:]+$/u.test(entry)); + if (invalid.length) throw new Error(`Unsupported invoke_handler entries: ${invalid.join(', ')}`); + return entries.map((rustPath) => ({ id: rustPath.split('::').at(-1), rustPath })); +} + +function findBalancedFunctionEnd(source, start) { + let parenDepth = 0; + let angleDepth = 0; + let bracketDepth = 0; + let inString = false; + let escaped = false; + for (let index = start; index < source.length; index += 1) { + const char = source[index]; + if (inString) { + if (escaped) escaped = false; + else if (char === '\\') escaped = true; + else if (char === '"') inString = false; + continue; + } + if (char === '"') inString = true; + else if (char === '(') parenDepth += 1; + else if (char === ')') parenDepth -= 1; + else if (char === '<') angleDepth += 1; + else if (char === '>') angleDepth = Math.max(0, angleDepth - 1); + else if (char === '[') bracketDepth += 1; + else if (char === ']') bracketDepth -= 1; + else if (char === '{' && parenDepth === 0 && angleDepth === 0 && bracketDepth === 0) return index; + } + return -1; +} + +function collectTauriFunctions() { + const byName = new Map(); + const rustFiles = walkFiles(DESKTOP_ROOT, (file) => file.endsWith('.rs')); + const marker = /#\[tauri::command(?:\([^\]]*\))?\]/gu; + for (const file of rustFiles) { + const source = readFileSync(file, 'utf8'); + for (const attribute of source.matchAll(marker)) { + const tailStart = attribute.index + attribute[0].length; + const tail = source.slice(tailStart); + const fnMatch = tail.match(/^(?:\s*#\[[^\]]+\])*\s*(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z0-9_]+)\s*\(/u); + if (!fnMatch) continue; + const functionStart = tailStart + fnMatch.index + fnMatch[0].indexOf('fn '); + const functionEnd = findBalancedFunctionEnd(source, functionStart); + if (functionEnd < 0) throw new Error(`Could not parse command signature in ${file}`); + const value = { + name: fnMatch[1], + sourceFile: toPosix(path.relative(REPO_ROOT, file)), + signature: source.slice(functionStart, functionEnd).replace(/\s+/gu, ' ').trim(), + }; + const existing = byName.get(value.name) ?? []; + existing.push(value); + byName.set(value.name, existing); + } + } + return byName; +} + +export function parseRemotePolicies(source) { + const policies = new Map(); + const entry = /\(\s*"([^"]+)"\s*,\s*RemoteWorkspacePolicy::([A-Za-z]+)\s*,?\s*\)/gu; + for (const match of source.matchAll(entry)) { + if (policies.has(match[1])) throw new Error(`Duplicate remote workspace policy: ${match[1]}`); + policies.set(match[1], match[2]); + } + return policies; +} + +function normalizeConditionalSignature(signature) { + return signature.replace(/\b_([a-z][a-z0-9_]*)\s*:/gu, '$1:'); +} + +function resolveRegisteredFunction(id, rustPath, allCandidates) { + const moduleHint = rustPath.split('::').at(-2); + const moduleCandidates = moduleHint + ? allCandidates.filter(({ sourceFile }) => { + const withoutExtension = sourceFile.replace(/\.rs$/u, ''); + return withoutExtension.endsWith(`/${moduleHint}`) || withoutExtension.includes(`/${moduleHint}/`); + }) + : []; + const candidates = moduleCandidates.length ? moduleCandidates : allCandidates; + if (!candidates.length) throw new Error(`Registered command ${id} has no matching #[tauri::command] function`); + const shapes = new Set(candidates.map(({ signature }) => normalizeConditionalSignature(signature))); + if (shapes.size !== 1) throw new Error(`Registered command ${id} has incompatible conditional implementations`); + return candidates.find(({ signature }) => !/\b_[a-z][a-z0-9_]*\s*:/u.test(signature)) ?? candidates[0]; +} + +function commandModule(sourceFile) { + const basename = path.basename(sourceFile, '.rs'); + if (basename === 'commands' || basename === 'lib') return basename; + return basename.replace(/_api$/u, ''); +} + +function extractSingleQuotedIds(source) { + return new Set([...source.matchAll(/(?:id|actionId|sceneId):\s*'([^']+)'/gu)].map((match) => match[1])); +} + +function extractTypeUnionIds(source, typeName) { + const match = source.match(new RegExp(`export type ${typeName}\\s*=([\\s\\S]*?);`, 'u')); + if (!match) throw new Error(`${typeName} union was not found`); + return new Set([...match[1].matchAll(/'([^']+)'/gu)].map((value) => value[1])); +} + +function assertBilingual(capability, field) { + const zh = capability[`${field}Zh`]; + const en = capability[`${field}En`]; + if (typeof zh !== 'string' || !/[\u3400-\u9fff]/u.test(zh)) { + throw new Error(`${capability.id}.${field}Zh must contain Chinese text`); + } + if (typeof en !== 'string' || !/[A-Za-z]/u.test(en)) { + throw new Error(`${capability.id}.${field}En must contain English text`); + } +} + +function buildInteractionInventory(roots) { + const signature = []; + const files = []; + const interactionLine = /(?:<(?:button|input|select|textarea)\b|\b(?:type|role)=["'](?:button|checkbox|radio|search|menuitem|option|switch|tab)["']|\bon(?:Click|Change|Submit|Select|Press|DoubleClick|ContextMenu|KeyDown|Drop|DragEnd|Blur)=|<(?:Button|IconButton|Checkbox|Switch|Toggle|Select|MenuItem|DropdownMenuItem|Tabs?|Slider|Input|Textarea)\b|\b(?:definePage|registerProductAction)\s*\(|\b(?:actionId|sceneId|eventName)\s*:|startElementSelection|insert-context-tag)/u; + for (const relativeRoot of roots) { + const absoluteRoot = path.join(REPO_ROOT, ...relativeRoot.split('/')); + if (!existsSync(absoluteRoot) || !statSync(absoluteRoot).isDirectory()) { + throw new Error(`Reviewed interaction root does not exist: ${relativeRoot}`); + } + const sourceFiles = walkFiles(absoluteRoot, (file) => { + const normalized = toPosix(file); + return /\.(?:ts|tsx)$/u.test(file) + && !/\.(?:test|spec|stories|example)\.(?:ts|tsx)$/u.test(file) + && !normalized.includes('/__tests__/'); + }).sort(); + for (const file of sourceFiles) { + const relativeFile = toPosix(path.relative(REPO_ROOT, file)); + const matchedLines = readFileSync(file, 'utf8') + .split(/\r?\n/u) + .map((line) => line.trim().replace(/\s+/gu, ' ')) + .filter((line) => interactionLine.test(line)); + if (!matchedLines.length) continue; + signature.push(relativeFile, ...matchedLines); + files.push({ + sourceFile: relativeFile, + interactionCount: matchedLines.length, + digest: createHash('sha256').update(matchedLines.join('\n')).digest('hex'), + }); + } + } + return { + roots, + digest: createHash('sha256').update(signature.join('\n')).digest('hex'), + fileCount: files.length, + interactionCount: files.reduce((total, file) => total + file.interactionCount, 0), + files, + }; +} + +function validateInteractionContract(source) { + const contract = source.reviewedInteractionContract; + if (!contract || !Array.isArray(contract.roots) || typeof contract.digest !== 'string') { + throw new Error('reviewedInteractionContract must declare roots and a reviewed digest'); + } + if (JSON.stringify(contract.roots) !== JSON.stringify(REQUIRED_INTERACTION_ROOTS)) { + throw new Error(`reviewedInteractionContract.roots must be ${JSON.stringify(REQUIRED_INTERACTION_ROOTS)}`); + } + const inventory = buildInteractionInventory(contract.roots); + if (contract.digest !== inventory.digest) { + throw new Error( + 'User-visible UI interactions changed. Audit the feature/setting inventories and their evidence, ' + + `then set reviewedInteractionContract.digest to ${inventory.digest}`, + ); + } + return inventory; +} + +function validateValueSchema(schema, owner) { + if (!schema || !['boolean', 'string', 'integer', 'number', 'object', 'array'].includes(schema.type)) { + throw new Error(`${owner} needs a supported value schema`); + } + if (schema.enum && (!Array.isArray(schema.enum) || schema.enum.length === 0)) { + throw new Error(`${owner}.valueSchema.enum must be a non-empty array`); + } +} + +function validateSource(source) { + if (source.schemaVersion !== 3) throw new Error('Interactive capability source must use schemaVersion 3'); + const capabilityIds = new Set(); + const settingsSource = readFileSync(SETTINGS_REGISTRY, 'utf8'); + const settingsIds = new Set( + [...settingsSource.matchAll(/definePage\(\{\s*id:\s*'([^']+)'/gu)].map((match) => match[1]), + ); + const settingsViewIds = extractTypeUnionIds(readFileSync(SETTINGS_TYPES, 'utf8'), 'SettingsViewId'); + const actionIds = extractSingleQuotedIds(readFileSync(PRODUCT_ACTION_CATALOG, 'utf8')); + const sceneIds = new Set([ + ...readFileSync(SCENE_TYPES, 'utf8').matchAll(/^\s*\|\s*'([^']+)'/gmu), + ].map((match) => match[1])); + + const validateDestination = (destination, owner) => { + if (destination.kind === 'settings') { + if (!settingsIds.has(destination.pageId)) { + throw new Error(`${owner} targets unknown settings page ${destination.pageId}`); + } + if (destination.viewId && !settingsViewIds.has(destination.viewId)) { + throw new Error(`${owner} targets unknown settings view ${destination.viewId}`); + } + return; + } + if (destination.kind === 'action' && !actionIds.has(destination.actionId)) { + throw new Error(`${owner} targets unknown product action ${destination.actionId}`); + } + if (destination.kind === 'scene' && !sceneIds.has(destination.sceneId)) { + throw new Error(`${owner} targets unknown scene ${destination.sceneId}`); + } + if (destination.kind === 'event' && !/^bitfun:[a-z0-9-]+$/u.test(destination.eventName)) { + throw new Error(`${owner} has an invalid UI event destination`); + } + if (!['settings', 'action', 'scene', 'event'].includes(destination.kind)) { + throw new Error(`${owner} has an unsupported destination`); + } + }; + + for (const capability of source.capabilities) { + if (!/^(feature|setting)\.[a-z0-9.-]+$/u.test(capability.id)) { + throw new Error(`Invalid user-facing capability ID: ${capability.id}`); + } + if (capabilityIds.has(capability.id)) throw new Error(`Duplicate capability ID: ${capability.id}`); + capabilityIds.add(capability.id); + if (!['feature', 'setting'].includes(capability.kind)) throw new Error(`${capability.id} needs kind feature or setting`); + if (!source.categories[capability.categoryId]) throw new Error(`${capability.id} has an unknown category`); + for (const field of ['title', 'summary']) assertBilingual(capability, field); + for (const field of ['keywordsZh', 'keywordsEn', 'highlightsZh', 'highlightsEn', 'stepsZh', 'stepsEn', 'agentExamplesZh', 'agentExamplesEn']) { + if (!Array.isArray(capability[field]) || capability[field].length === 0) { + throw new Error(`${capability.id}.${field} must be a non-empty array`); + } + } + for (const field of ['highlights', 'steps', 'agentExamples']) { + if (capability[`${field}Zh`].length !== capability[`${field}En`].length) { + throw new Error(`${capability.id}.${field} must have matching Chinese and English entries`); + } + } + if (capability.agentControl) { + if (typeof capability.agentControl.tool !== 'string' || !capability.agentControl.tool.trim()) { + throw new Error(`${capability.id}.agentControl.tool must name the controlling Agent tool`); + } + for (const field of ['workflowZh', 'workflowEn']) { + if (!Array.isArray(capability.agentControl[field]) || capability.agentControl[field].length === 0) { + throw new Error(`${capability.id}.agentControl.${field} must be a non-empty array`); + } + } + if (capability.agentControl.workflowZh.length !== capability.agentControl.workflowEn.length) { + throw new Error(`${capability.id}.agentControl workflows must have matching Chinese and English entries`); + } + } + const minimumItems = capability.kind === 'feature' ? 6 : 4; + if (!Array.isArray(capability.items) || capability.items.length < minimumItems) { + throw new Error(`${capability.id}.items must document at least ${minimumItems} user-visible sub-capabilities`); + } + const itemIds = new Set(); + for (const item of capability.items) { + if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(item.id ?? '')) { + throw new Error(`${capability.id} has an invalid documented item ID: ${item.id ?? ''}`); + } + if (itemIds.has(item.id)) throw new Error(`${capability.id} has duplicate documented item ${item.id}`); + itemIds.add(item.id); + assertBilingual({ ...item, id: `${capability.id}.${item.id}` }, 'title'); + if (item.destination) { + validateDestination(item.destination, `${capability.id}.${item.id}`); + if ( + item.destination.kind === 'settings' + && capability.destination.kind === 'settings' + && item.destination.pageId !== capability.destination.pageId + ) { + throw new Error(`${capability.id}.${item.id} must stay inside its owning settings page`); + } + } + if (!Array.isArray(item.evidence) || item.evidence.length === 0) { + throw new Error(`${capability.id}.${item.id}.evidence must not be empty`); + } + } + + validateDestination(capability.destination, capability.id); + + const operationIds = new Set(); + for (const operation of capability.operations ?? []) { + if (operationIds.has(operation.id)) throw new Error(`${capability.id} has duplicate operation ${operation.id}`); + operationIds.add(operation.id); + assertBilingual({ ...operation, id: `${capability.id}.${operation.id}` }, 'title'); + assertBilingual({ ...operation, id: `${capability.id}.${operation.id}` }, 'description'); + if (!operation.inputSchema || operation.inputSchema.type !== 'object') { + throw new Error(`${capability.id}.${operation.id} needs an object input schema`); + } + if ( + operation.inputSchema.additionalProperties !== false + || Object.keys(operation.inputSchema.properties ?? {}).length > 0 + ) { + throw new Error( + `${capability.id}.${operation.id} declares operation arguments, but its handler cannot consume them`, + ); + } + if (operation.handler.kind !== 'productAction' || !actionIds.has(operation.handler.actionId)) { + throw new Error(`${capability.id}.${operation.id} has an unsupported operation handler`); + } + } + + const optionIds = new Set(); + for (const option of capability.options ?? []) { + if (capability.kind !== 'setting') throw new Error(`${capability.id} exposes options but is not a setting`); + if (optionIds.has(option.id)) throw new Error(`${capability.id} has duplicate option ${option.id}`); + optionIds.add(option.id); + assertBilingual({ ...option, id: `${capability.id}.${option.id}` }, 'title'); + assertBilingual({ ...option, id: `${capability.id}.${option.id}` }, 'description'); + validateValueSchema(option.valueSchema, `${capability.id}.${option.id}`); + if (option.handler.kind === 'config' && !option.handler.path) { + throw new Error(`${capability.id}.${option.id} needs a config path`); + } + if (option.handler.kind === 'mergeConfig' && (!option.handler.path || !option.handler.fields?.length)) { + throw new Error(`${capability.id}.${option.id} needs a merge path and fields`); + } + if (!['config', 'mergeConfig', 'appearanceSelection', 'language'].includes(option.handler.kind)) { + throw new Error(`${capability.id}.${option.id} has an unsupported option handler`); + } + } + } + + const documentedItemCount = source.capabilities.reduce( + (total, capability) => total + capability.items.length, + 0, + ); + if (source.reviewedDocumentedItemCount !== documentedItemCount) { + throw new Error( + `Documented item count changed from reviewed ${source.reviewedDocumentedItemCount} to ${documentedItemCount}. ` + + 'Complete the source-evidence review, then update reviewedDocumentedItemCount in the same catalog.', + ); + } + + const semanticSettings = new Set(source.capabilities + .filter(({ kind }) => kind === 'setting') + .map(({ destination }) => destination.kind === 'settings' ? destination.pageId : null) + .filter(Boolean)); + const missingSettings = [...settingsIds].filter((id) => !semanticSettings.has(id)); + const staleSettings = [...semanticSettings].filter((id) => !settingsIds.has(id)); + if (missingSettings.length || staleSettings.length) { + throw new Error([ + missingSettings.length ? `Settings pages missing from the semantic manual: ${missingSettings.join(', ')}` : '', + staleSettings.length ? `Semantic settings without a registered page: ${staleSettings.join(', ')}` : '', + ].filter(Boolean).join('\n')); + } + + const semanticSettingsViews = new Set(source.capabilities.flatMap((capability) => + capability.items + .map(({ destination }) => destination?.kind === 'settings' ? destination.viewId : null) + .filter(Boolean))); + const missingSettingsViews = [...settingsViewIds].filter((id) => !semanticSettingsViews.has(id)); + const staleSettingsViews = [...semanticSettingsViews].filter((id) => !settingsViewIds.has(id)); + if (missingSettingsViews.length || staleSettingsViews.length) { + throw new Error([ + missingSettingsViews.length + ? `Settings views missing direct semantic destinations: ${missingSettingsViews.join(', ')}` + : '', + staleSettingsViews.length + ? `Semantic destinations without registered settings views: ${staleSettingsViews.join(', ')}` + : '', + ].filter(Boolean).join('\n')); + } + + for (const [label, owners, actual] of [ + ['product action', source.productActionOwners, actionIds], + ['scene', source.sceneOwners, sceneIds], + ]) { + const ownerIds = new Set(Object.keys(owners ?? {})); + const missing = [...actual].filter((id) => !ownerIds.has(id)); + const stale = [...ownerIds].filter((id) => !actual.has(id)); + if (missing.length || stale.length) { + throw new Error([ + missing.length ? `${label}s missing semantic owners: ${missing.join(', ')}` : '', + stale.length ? `Semantic ${label} owners without registry entries: ${stale.join(', ')}` : '', + ].filter(Boolean).join('\n')); + } + for (const [id, capabilityId] of Object.entries(owners)) { + if (!capabilityIds.has(capabilityId)) { + throw new Error(`${label} ${id} targets unknown capability ${capabilityId}`); + } + } + } + return capabilityIds; +} + +function parseSourceEvidence(reference, owner) { + const separator = reference.indexOf('#'); + if (separator <= 'source:'.length || separator === reference.length - 1) { + throw new Error(`${owner} has invalid source evidence: ${reference}`); + } + const relativePath = reference.slice('source:'.length, separator); + const marker = reference.slice(separator + 1); + if (relativePath.includes('..') || !/^(?:src|docs)\//u.test(relativePath)) { + throw new Error(`${owner} source evidence must stay inside src/ or docs/: ${relativePath}`); + } + const absolutePath = path.join(REPO_ROOT, ...relativePath.split('/')); + if (!existsSync(absolutePath) || !statSync(absolutePath).isFile()) { + throw new Error(`${owner} source evidence file does not exist: ${relativePath}`); + } + const source = readFileSync(absolutePath, 'utf8'); + let markerExists = source.includes(marker); + if (!markerExists && relativePath.endsWith('.json')) { + try { + let value = JSON.parse(source); + for (const segment of marker.split('.')) { + if (!value || typeof value !== 'object' || !Object.hasOwn(value, segment)) { + value = undefined; + break; + } + value = value[segment]; + } + markerExists = value !== undefined; + } catch {} + } + if (!markerExists) { + throw new Error(`${owner} source evidence marker is missing from ${relativePath}: ${marker}`); + } +} + +function validateDocumentationEvidence(source, technicalCommands) { + const commandIds = new Set(technicalCommands.map(({ id }) => id)); + for (const capability of source.capabilities) { + capability.items.forEach((item) => { + const owner = `${capability.id}.${item.id}`; + const references = item.evidence; + for (const reference of references) { + if (typeof reference !== 'string') throw new Error(`${owner} references must be strings`); + if (reference.startsWith('command:')) { + const commandId = reference.slice('command:'.length); + if (!commandIds.has(commandId)) throw new Error(`${owner} references unknown command ${commandId}`); + } else if (reference.startsWith('source:')) { + parseSourceEvidence(reference, owner); + } else { + throw new Error(`${owner} has unsupported evidence: ${reference}`); + } + } + }); + } +} + +function runtimeItem(item) { + const { evidence: _evidence, ...value } = item; + return value; +} + +function publicOperation(operation) { + const { handler: _handler, ...value } = operation; + return value; +} + +function publicOption(option) { + const { handler: _handler, ...value } = option; + return value; +} + +function buildTechnicalCoverage(source, capabilityIds) { + const registrations = parseRegisteredCommands(readFileSync(DESKTOP_LIB, 'utf8')); + const duplicateIds = registrations.map(({ id }) => id).filter((id, index, all) => all.indexOf(id) !== index); + if (duplicateIds.length) throw new Error(`Duplicate registered commands: ${duplicateIds.join(', ')}`); + const functions = collectTauriFunctions(); + const policies = parseRemotePolicies(readFileSync(REMOTE_POLICY, 'utf8')); + const registeredSet = new Set(registrations.map(({ id }) => id)); + const missingPolicies = [...registeredSet].filter((id) => !policies.has(id)); + const extraPolicies = [...policies.keys()].filter((id) => !registeredSet.has(id)); + if (missingPolicies.length || extraPolicies.length) { + throw new Error([ + missingPolicies.length ? `Commands missing remote policy: ${missingPolicies.join(', ')}` : '', + extraPolicies.length ? `Policies without commands: ${extraPolicies.join(', ')}` : '', + ].filter(Boolean).join('\n')); + } + + const commands = registrations.map(({ id, rustPath }) => { + const resolved = resolveRegisteredFunction(id, rustPath, functions.get(id) ?? []); + const moduleId = commandModule(resolved.sourceFile); + const owner = source.implementationOwners[moduleId]; + if (!owner) throw new Error(`Tauri module ${moduleId} has no reviewed semantic owner`); + if (owner.capabilityId !== null && !capabilityIds.has(owner.capabilityId)) { + throw new Error(`Tauri module ${moduleId} targets unknown capability ${owner.capabilityId}`); + } + return { + id, + moduleId, + capabilityId: owner.capabilityId, + visibility: owner.capabilityId === null ? 'internal' : 'implementation', + rustPath, + sourceFile: resolved.sourceFile, + signature: resolved.signature, + remoteWorkspacePolicy: policies.get(id), + }; + }).sort((left, right) => left.id.localeCompare(right.id)); + + const actualModules = new Map(); + for (const command of commands) { + const values = actualModules.get(command.moduleId) ?? []; + values.push(command); + actualModules.set(command.moduleId, values); + } + const staleOwners = Object.keys(source.implementationOwners).filter((moduleId) => !actualModules.has(moduleId)); + if (staleOwners.length) throw new Error(`Semantic owners without Tauri modules: ${staleOwners.join(', ')}`); + for (const [moduleId, values] of actualModules) { + const reviewed = source.implementationOwners[moduleId].reviewedCommandCount; + if (reviewed !== values.length) { + throw new Error( + `Tauri module ${moduleId} changed from its reviewed count ${reviewed} to ${values.length}. ` + + 'Review whether this is a new user feature or an existing implementation detail, then update the one semantic source.', + ); + } + } + return commands; +} + +function searchTerms(capability, category) { + return [...new Set([ + capability.id, + capability.titleZh, + capability.titleEn, + category.titleZh, + category.titleEn, + ...capability.keywordsZh, + ...capability.keywordsEn, + ...capability.highlightsZh, + ...capability.highlightsEn, + ...capability.items.flatMap((item) => [item.titleZh, item.titleEn]), + ...(capability.agentControl?.workflowZh ?? []), + ...(capability.agentControl?.workflowEn ?? []), + ...(capability.agentControl?.tool ? [capability.agentControl.tool] : []), + ])]; +} + +export function buildCapabilityCatalog() { + const source = JSON.parse(readFileSync(SOURCE_PATH, 'utf8')); + const capabilityIds = validateSource(source); + const interactionInventory = validateInteractionContract(source); + const technicalCommands = buildTechnicalCoverage(source, capabilityIds); + validateDocumentationEvidence(source, technicalCommands); + + const runtimeCapabilities = source.capabilities.map((capability) => { + const category = source.categories[capability.categoryId]; + return { + ...capability, + items: capability.items.map(runtimeItem), + operations: capability.operations ?? [], + options: capability.options ?? [], + searchTerms: searchTerms(capability, category), + docsUrl: `${source.origin}/capabilities/${capability.id}/`, + }; + }); + const publicCapabilities = runtimeCapabilities.map((capability) => ({ + ...capability, + operations: capability.operations.map(publicOperation), + options: capability.options.map(publicOption), + })); + const digest = createHash('sha256') + .update(JSON.stringify({ categories: source.categories, capabilities: publicCapabilities })) + .digest('hex'); + const common = { + schemaVersion: source.schemaVersion, + product: source.product, + title: source.title, + origin: source.origin, + source: toPosix(path.relative(REPO_ROOT, SOURCE_PATH)), + digest, + counts: { + features: publicCapabilities.filter(({ kind }) => kind === 'feature').length, + settings: publicCapabilities.filter(({ kind }) => kind === 'setting').length, + userFacing: publicCapabilities.length, + documentedItems: publicCapabilities.reduce((total, capability) => total + capability.items.length, 0), + }, + categories: source.categories, + }; + return { + publicCatalog: { ...common, capabilities: publicCapabilities }, + runtimeCatalog: { ...common, capabilities: runtimeCapabilities }, + technicalMap: { + schemaVersion: 1, + generatedFrom: toPosix(path.relative(REPO_ROOT, SOURCE_PATH)), + catalogDigest: digest, + commandCount: technicalCommands.length, + commands: technicalCommands, + }, + interactionMap: { + schemaVersion: 1, + generatedFrom: toPosix(path.relative(REPO_ROOT, SOURCE_PATH)), + catalogDigest: digest, + ...interactionInventory, + }, + }; +} + +function destinationText(destination) { + if (destination.kind === 'settings') return 'BitFun 设置'; + if (destination.kind === 'action') return 'BitFun 功能入口'; + if (destination.kind === 'scene') return 'BitFun 对应场景'; + return 'BitFun 内的对应控制界面'; +} + +function schemaLabel(schema) { + if (schema.enum) return schema.enum.map((value) => `\`${value}\``).join(' / '); + const range = schema.minimum !== undefined || schema.maximum !== undefined + ? ` (${schema.minimum ?? '…'}–${schema.maximum ?? '…'})` + : ''; + return `\`${schema.type}\`${range}`; +} + +function renderCapabilityMarkdown(capability) { + const kindZh = capability.kind === 'feature' ? '功能' : '设置'; + const kindEn = capability.kind === 'feature' ? 'Feature' : 'Setting'; + const operations = capability.agentControl + ? capability.agentControl.workflowZh.map((step, index) => + `| ${capability.agentControl.tool} · ${index + 1} | ${step} | ${capability.agentControl.workflowEn[index] ?? ''} |`, + ).join('\n') + : capability.operations.length + ? capability.operations.map((operation) => + `| ${operation.titleZh} / ${operation.titleEn} | ${operation.descriptionZh} | ${operation.descriptionEn} |`, + ).join('\n') + : '| 打开对应界面 / Open the UI | 进入 BitFun 中对应的功能界面。 | Open the matching feature in BitFun. |'; + const options = capability.options.length + ? capability.options.map((option) => + `| ${option.titleZh} / ${option.titleEn} | ${schemaLabel(option.valueSchema)} | ${option.descriptionZh} | ${option.descriptionEn} |`, + ).join('\n') + : '| 在界面中配置 / Configure in the UI | — | 此页面的设置在对应界面中完成。 | Configure this page in its matching UI. |'; + const steps = capability.stepsZh.map((step, index) => `${index + 1}. ${step}\n ${capability.stepsEn[index] ?? ''}`).join('\n'); + const inventory = capability.items.map((item) => `- ${item.titleZh}\n - ${item.titleEn}`).join('\n'); + const examples = capability.agentExamplesZh.map((item, index) => `- “${item}”\n - “${capability.agentExamplesEn[index] ?? ''}”`).join('\n'); + return `${GENERATED_MARKER} +--- +id: ${capability.id} +kind: ${capability.kind} +category: ${capability.categoryId} +title_zh: ${JSON.stringify(capability.titleZh)} +title_en: ${JSON.stringify(capability.titleEn)} +--- + +# ${capability.titleZh} / ${capability.titleEn} + +> ${kindZh} / ${kindEn} + +${capability.summaryZh} + +${capability.summaryEn} + +## 完整功能清单 / Everything included + +${inventory} + +## 怎么用 / How to use it + +${steps} + +入口 / Entry: ${destinationText(capability.destination)} + +## Agent 可替你做什么 / What an agent can do for you + +| 操作 / Action | 中文说明 | English description | +| --- | --- | --- | +${operations} + +## 可配置选项 / Configurable options + +| 选项 / Option | 可用值 / Values | 中文说明 | English description | +| --- | --- | --- | --- | +${options} + +## 可以直接对 Agent 说 / Try saying + +${examples} + +Agent 会先查找相关功能或设置,确认目标后再替你打开、执行或修改。完整能力目录不会预先塞进对话上下文。 + +The agent first finds the relevant feature or setting, confirms the target, and then opens, runs, or changes it for you. The full catalog is never embedded in the conversation context. +`; +} + +function renderReadme(catalog, technicalMap, interactionMap) { + return `${GENERATED_MARKER} +# BitFun 功能与设置目录 / BitFun Features & Settings + +BitFun Playbook 当前包含 **${catalog.counts.features} 个功能**和 **${catalog.counts.settings} 个设置页**,共 **${catalog.counts.userFacing} 个**用户可理解的条目、**${catalog.counts.documentedItems} 项**有源码证据的子能力。每个条目有独立 Markdown,并直接服务于说明书网站、BitFun 全局搜索和 \`BitFunControl\` Agent 工具。 + +BitFun Playbook currently contains **${catalog.counts.features} features**, **${catalog.counts.settings} settings pages**, and **${catalog.counts.documentedItems}** source-backed sub-capabilities across **${catalog.counts.userFacing}** user-facing entries. Every entry has its own Markdown page and directly powers the website, in-app global search, and the \`BitFunControl\` agent tool. + +## 唯一事实源 / Single source of truth + +- 手工维护的唯一语义目录:\`${catalog.source}\` +- 生成的公开目录:\`docs/interactive-capabilities/capabilities.json\` +- 生成的前端运行目录:\`src/web-ui/src/app/global-search/generated/interactive-capabilities.json\` +- 生成的底层审计表:\`docs/interactive-capabilities/technical/tauri-command-map.json\` +- 生成的可见交互审计表:\`docs/interactive-capabilities/technical/ui-interaction-inventory.json\` + +说明书、网站、搜索和 Agent 只看“功能 + 设置 + 子能力”。每项子能力都必须引用已注册 Tauri Command 或可解析的源码标记;这些证据不会进入公开目录。当前 **${technicalMap.commandCount}** 个 Tauri 命令,以及 **${interactionMap.fileCount}** 个产品交互源码文件中的 **${interactionMap.interactionCount}** 个交互候选,只用于实现覆盖审计。 + +Docs, website, search, and agents see only features, settings, and documented sub-capabilities. Every sub-capability must reference a registered Tauri command or a resolvable source marker; evidence is stripped from public projections. The **${technicalMap.commandCount}** Tauri commands and **${interactionMap.interactionCount}** interaction candidates across **${interactionMap.fileCount}** product UI source files remain implementation-audit evidence only. + +## 控制边界 / Control boundary + +- 每个功能或设置都有可执行的产品入口;存在多视图的设置页还必须把每个视图映射到至少一个子能力,搜索和 Agent 可携带子能力 ID 精确跳转。 +- 简单、稳定且适合自动化的行为才声明为类型化 \`operations\` 或 \`options\`。复杂流程由 Agent 打开对应界面交给用户继续,不向 Agent 暴露原始 Tauri Command。 +- \`BitFunControl list\` 一次返回完整的精简目录(目录上限 50 项);\`search\` 默认只返回前 20 项。完整目录和 ${catalog.counts.documentedItems} 项子能力都不会写入 system prompt。 +- Desktop 只有在前端控制监听器完成握手后才发布工具;CLI、Detached Dispatch 等没有交互界面的运行方式明确不提供该工具。只读 Agent 只能发现和读取目录。 + +- Every feature or setting has an executable product destination. Multi-view settings pages must map every registered view to at least one documented item, so search and agents can carry an item ID for exact navigation. +- Only simple, stable, automation-safe behavior becomes a typed \`operation\` or \`option\`. Complex flows open their owning UI instead of exposing raw Tauri commands to agents. +- One default \`BitFunControl list\` call returns the complete curated catalog (hard limit: 50); \`search\` defaults to 20 results. Neither the full catalog nor its ${catalog.counts.documentedItems} documented items enters the system prompt. +- Desktop advertises the tool only after the frontend control listener completes its readiness handshake. Headless surfaces such as CLI and Detached Dispatch explicitly omit it, and read-only agents may only discover and inspect entries. + +## 防腐化门禁 / Anti-drift gates + +- 设置页、产品动作与场景注册表必须全部映射到一个语义条目。 +- 所有设置子视图必须有同源的子能力直达目标,失效的页签 ID 会阻断生成。 +- 每个功能至少 6 项、每个设置至少 4 项子能力,且中英文、稳定 ID 与证据缺一不可。 +- 当前操作处理器不接受参数;若目录误声明参数,生成会失败,避免 Agent 看到实际不会生效的参数。 +- Tauri 模块命令数和用户可见交互源码摘要均为 reviewed contract;变化会让 \`capabilities:check\` 失败并给出新的摘要值。 +- 维护者必须先核对功能清单与证据,再只在本语义源中更新 reviewed count/digest,随后运行 \`pnpm run capabilities:generate\`。 + +- Every settings page, product action, and scene registration must map to one semantic entry. +- Every settings subview needs a same-source item destination; stale view IDs fail generation. +- Features need at least six documented items and settings need at least four, each with bilingual text, a stable ID, and source evidence. +- Current operation handlers accept no arguments, and generation fails if the catalog advertises arguments that would be ignored. +- Reviewed Tauri module counts and the user-visible interaction-source digest fail \`capabilities:check\` on drift. +- Maintainers review the inventories and evidence first, update the reviewed count/digest only in this semantic source, then run \`pnpm run capabilities:generate\`. +`; +} + +async function compareOrWrite(file, content, drift) { + if (checkMode) { + let actual = null; + try { actual = await readFile(file, 'utf8'); } catch {} + if (actual !== content) drift.push(toPosix(path.relative(REPO_ROOT, file))); + return; + } + await mkdir(path.dirname(file), { recursive: true }); + await writeFile(file, content, 'utf8'); +} + +async function generatedMarkdownFiles() { + try { + return (await readdir(DOCS_CAPABILITIES_ROOT, { withFileTypes: true })) + .filter((entry) => entry.isFile() && entry.name.endsWith('.md')) + .map((entry) => path.join(DOCS_CAPABILITIES_ROOT, entry.name)); + } catch { + return []; + } +} + +async function main() { + const { publicCatalog, runtimeCatalog, technicalMap, interactionMap } = buildCapabilityCatalog(); + const drift = []; + await compareOrWrite(PUBLIC_CATALOG_PATH, `${JSON.stringify(publicCatalog, null, 2)}\n`, drift); + await compareOrWrite(RUNTIME_CATALOG_PATH, `${JSON.stringify(runtimeCatalog, null, 2)}\n`, drift); + await compareOrWrite(TECHNICAL_MAP_PATH, `${JSON.stringify(technicalMap, null, 2)}\n`, drift); + await compareOrWrite(UI_INTERACTION_MAP_PATH, `${JSON.stringify(interactionMap, null, 2)}\n`, drift); + await compareOrWrite(path.join(DOCS_ROOT, 'README.md'), renderReadme(publicCatalog, technicalMap, interactionMap), drift); + + const expectedDocs = new Set(); + for (const capability of publicCatalog.capabilities) { + const file = path.join(DOCS_CAPABILITIES_ROOT, `${capability.id}.md`); + expectedDocs.add(file); + await compareOrWrite(file, renderCapabilityMarkdown(capability), drift); + } + for (const file of await generatedMarkdownFiles()) { + if (expectedDocs.has(file)) continue; + const content = await readFile(file, 'utf8'); + if (!content.startsWith(GENERATED_MARKER)) throw new Error(`Refusing to remove non-generated document: ${file}`); + if (checkMode) drift.push(toPosix(path.relative(REPO_ROOT, file))); + else await rm(file); + } + + if (drift.length) { + console.error('Interactive capability artifacts are stale or missing:'); + drift.sort().forEach((file) => console.error(`- ${file}`)); + console.error('Run: pnpm run capabilities:generate'); + process.exitCode = 1; + return; + } + if (!quiet) { + console.log( + `${checkMode ? 'Verified' : 'Generated'} ${publicCatalog.counts.features} features + ` + + `${publicCatalog.counts.settings} settings; audited ${technicalMap.commandCount} Tauri commands ` + + `(${publicCatalog.digest.slice(0, 12)}).`, + ); + } +} + +if (path.resolve(process.argv[1] ?? '') === fileURLToPath(import.meta.url)) await main(); diff --git a/scripts/interactive-capabilities.test.mjs b/scripts/interactive-capabilities.test.mjs new file mode 100644 index 0000000000..1656723bcc --- /dev/null +++ b/scripts/interactive-capabilities.test.mjs @@ -0,0 +1,210 @@ +import assert from 'node:assert/strict'; +import { readdir, readFile } from 'node:fs/promises'; +import path from 'node:path'; +import test from 'node:test'; +import { fileURLToPath } from 'node:url'; + +import { + buildCapabilityCatalog, + parseRegisteredCommands, +} from './generate-interactive-capabilities.mjs'; + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const read = (relativePath) => readFile(path.join(repositoryRoot, relativePath), 'utf8'); + +test('the public contract is a compact feature-and-settings manual', () => { + const { publicCatalog } = buildCapabilityCatalog(); + const featureCount = publicCatalog.capabilities.filter(({ kind }) => kind === 'feature').length; + const settingCount = publicCatalog.capabilities.filter(({ kind }) => kind === 'setting').length; + const documentedItemCount = publicCatalog.capabilities.reduce( + (total, capability) => total + capability.items.length, + 0, + ); + assert.equal(publicCatalog.counts.features, featureCount); + assert.equal(publicCatalog.counts.settings, settingCount); + assert.equal(publicCatalog.counts.userFacing, publicCatalog.capabilities.length); + assert.equal(publicCatalog.counts.documentedItems, documentedItemCount); + assert.deepEqual(new Set(publicCatalog.capabilities.map(({ kind }) => kind)), new Set(['feature', 'setting'])); + assert.equal(new Set(publicCatalog.capabilities.map(({ id }) => id)).size, publicCatalog.capabilities.length); + assert.ok(publicCatalog.capabilities.length <= 50, 'one default list call must return the curated catalog'); + assert.equal(publicCatalog.capabilities.some(({ id }) => id === 'get_configs'), false); + assert.equal(JSON.stringify(publicCatalog).includes('tauri::'), false); + assert.equal(JSON.stringify(publicCatalog).includes('implementationCoverage'), false); + assert.equal(JSON.stringify(publicCatalog).includes('tauriCommandsAudited'), false); + assert.equal(JSON.stringify(publicCatalog).includes('evidence'), false); + assert.equal(JSON.stringify(publicCatalog).includes('reviewedInteractionContract'), false); +}); + +test('the technical audit exactly covers Desktop Tauri registration without exposing it as UX', async () => { + const registrations = parseRegisteredCommands(await read('src/apps/desktop/src/lib.rs')); + const { publicCatalog, technicalMap } = buildCapabilityCatalog(); + assert.equal(technicalMap.commands.length, registrations.length); + assert.deepEqual( + new Set(technicalMap.commands.map(({ id }) => id)), + new Set(registrations.map(({ id }) => id)), + ); + assert.equal(technicalMap.commandCount, registrations.length); + assert.ok(technicalMap.commands.every(({ capabilityId, visibility }) => + capabilityId === null ? visibility === 'internal' : visibility === 'implementation')); +}); + +test('every manual entry has bilingual discovery, instructions, routing, and agent recipes', () => { + const { publicCatalog } = buildCapabilityCatalog(); + for (const capability of publicCatalog.capabilities) { + assert.match(capability.titleZh, /[\u3400-\u9fff]/u, `${capability.id} needs a Chinese title`); + assert.match(capability.titleEn, /[A-Za-z]/u, `${capability.id} needs an English title`); + assert.ok(capability.searchTerms.some((term) => /[\u3400-\u9fff]/u.test(term))); + assert.ok(capability.searchTerms.some((term) => /[A-Za-z]/u.test(term))); + assert.ok(capability.highlightsZh.length > 0); + assert.ok(capability.items.length >= (capability.kind === 'feature' ? 6 : 4)); + assert.equal(new Set(capability.items.map(({ id }) => id)).size, capability.items.length); + assert.ok(capability.items.every(({ titleZh, titleEn }) => + /[\u3400-\u9fff]/u.test(titleZh) && /[A-Za-z]/u.test(titleEn))); + assert.ok(capability.stepsZh.length > 0); + assert.ok(capability.agentExamplesZh.length > 0); + assert.ok(['settings', 'action', 'scene', 'event'].includes(capability.destination.kind)); + assert.equal(capability.docsUrl, `${publicCatalog.origin}/capabilities/${capability.id}/`); + assert.doesNotMatch(JSON.stringify(capability), /"handler"/u); + } +}); + +test('the built-in browser manual covers its element picker in both languages', () => { + const { publicCatalog } = buildCapabilityCatalog(); + const browser = publicCatalog.capabilities.find(({ id }) => id === 'feature.browser'); + assert.ok(browser); + assert.ok(browser.items.some(({ id, titleZh, titleEn }) => + id === 'element-picker' && titleZh.includes('元素选择器') && /element picker/iu.test(titleEn))); + assert.ok(browser.items.some(({ id, titleZh, titleEn }) => + id === 'element-context' && titleZh.includes('CSS 路径') && /session context/iu.test(titleEn))); + assert.ok(browser.searchTerms.includes('启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class')); + assert.ok(browser.searchTerms.includes('Start the element picker to highlight hovered elements and show tag, ID, and class details')); +}); + +test('built-in and external browsers share one agent action contract', async () => { + const { publicCatalog } = buildCapabilityCatalog(); + const browser = publicCatalog.capabilities.find(({ id }) => id === 'feature.browser'); + assert.ok(browser); + assert.ok(browser.items.some(({ id }) => id === 'agent-page-automation')); + assert.ok(browser.items.some(({ id }) => id === 'shared-browser-action-contract')); + assert.ok(browser.searchTerms.some((term) => /Agent.*内置网页/u.test(term))); + assert.ok(browser.searchTerms.some((term) => /one BrowserActions/iu.test(term))); + assert.equal(browser.agentControl.tool, 'ControlHub'); + assert.ok(browser.agentControl.workflowZh.some((step) => step.includes('browser.open_builtin'))); + assert.ok(browser.agentControl.workflowEn.some((step) => /share.*contract/iu.test(step))); + + const actions = await read( + 'src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs', + ); + const clientContract = await read( + 'src/crates/assembly/core/src/agentic/tools/browser_control/automation_client.rs', + ); + const cdpAdapter = await read( + 'src/crates/assembly/core/src/agentic/tools/browser_control/cdp_client.rs', + ); + const builtinCoreAdapter = await read( + 'src/crates/assembly/core/src/agentic/tools/browser_control/builtin_browser.rs', + ); + const builtinDesktopAdapter = await read('src/apps/desktop/src/builtin_browser_host.rs'); + const controlHub = await read( + 'src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs', + ); + const browserSurface = await read( + 'src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts', + ); + + assert.match(actions, /client: &'a dyn BrowserAutomationClient/u); + assert.match(clientContract, /trait BrowserAutomationClient/u); + assert.match(clientContract, /struct BrowserAutomationEvent/u); + assert.doesNotMatch(clientContract, /use super::cdp_client/u); + assert.match(cdpAdapter, /impl BrowserAutomationClient for CdpClient/u); + assert.match(builtinCoreAdapter, /impl BrowserAutomationClient for BuiltInBrowserClient/u); + assert.match(builtinDesktopAdapter, /EmbeddedWebviewAutomation/u); + assert.doesNotMatch(builtinDesktopAdapter, /SNAPSHOT_SCRIPT|data-cdp-ref|element_center_js/u); + assert.match(controlHub, /SHARED_BROWSER_ACTIONS/u); + assert.match(controlHub, /BrowserActions::new\(target\.client\(\)\)/u); + assert.match(browserSurface, /browser_webview_set_agent_target_state/u); + assert.doesNotMatch(browserSurface, /BrowserActions|SHARED_BROWSER_ACTIONS/u); +}); + +test('docs, runtime, and technical views are generated projections of one semantic source', async () => { + const source = JSON.parse(await read('src/shared/interactive-capabilities/catalog.json')); + const publicCatalog = JSON.parse(await read('docs/interactive-capabilities/capabilities.json')); + const runtimeCatalog = JSON.parse(await read( + 'src/web-ui/src/app/global-search/generated/interactive-capabilities.json', + )); + const technicalMap = JSON.parse(await read( + 'docs/interactive-capabilities/technical/tauri-command-map.json', + )); + const interactionMap = JSON.parse(await read( + 'docs/interactive-capabilities/technical/ui-interaction-inventory.json', + )); + + const sourceIds = source.capabilities.map(({ id }) => id); + assert.equal( + source.reviewedDocumentedItemCount, + source.capabilities.reduce((total, capability) => total + capability.items.length, 0), + ); + assert.deepEqual(interactionMap.roots, source.reviewedInteractionContract.roots); + assert.deepEqual(publicCatalog.capabilities.map(({ id }) => id), sourceIds); + assert.deepEqual(runtimeCatalog.capabilities.map(({ id }) => id), sourceIds); + assert.equal(publicCatalog.digest, runtimeCatalog.digest); + assert.equal(publicCatalog.digest, technicalMap.catalogDigest); + assert.equal(publicCatalog.digest, interactionMap.catalogDigest); + assert.equal(interactionMap.digest, source.reviewedInteractionContract.digest); + assert.ok(interactionMap.fileCount >= 300); + assert.ok(interactionMap.interactionCount >= 4_000); + assert.ok(interactionMap.files.some(({ sourceFile }) => + sourceFile.endsWith('/BrowserPanel.tsx'))); + assert.ok(interactionMap.files.some(({ sourceFile }) => + sourceFile.endsWith('/AssistantDefaultsPage.tsx'))); + assert.ok(interactionMap.files.some(({ sourceFile }) => + sourceFile.endsWith('/AppearanceSettingsPage.tsx'))); + assert.equal(publicCatalog.source, 'src/shared/interactive-capabilities/catalog.json'); + + const publicById = new Map(publicCatalog.capabilities.map((capability) => [capability.id, capability])); + for (const runtime of runtimeCatalog.capabilities) { + const publicValue = publicById.get(runtime.id); + assert.deepEqual(runtime.operations.map(({ handler: _handler, ...value }) => value), publicValue.operations); + assert.deepEqual(runtime.options.map(({ handler: _handler, ...value }) => value), publicValue.options); + } + + const docs = (await readdir(path.join(repositoryRoot, 'docs/interactive-capabilities/capabilities'))) + .filter((file) => file.endsWith('.md')); + assert.equal(docs.length, sourceIds.length); +}); + +test('website, global search, and agent control consume generated semantic projections', async () => { + const websiteBuild = await read('website/scripts/build.mjs'); + const frontendCatalog = await read('src/web-ui/src/app/global-search/interactiveCapabilityCatalog.ts'); + const searchProvider = await read( + 'src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.ts', + ); + const searchProviders = await read('src/web-ui/src/app/global-search/providers/index.ts'); + const controlBridge = await read('src/web-ui/src/app/global-search/bitfunControlBridge.ts'); + const controlTool = await read( + 'src/crates/assembly/core/src/agentic/tools/implementations/bitfun_control_tool.rs', + ); + + assert.match(websiteBuild, /docs\/interactive-capabilities\/capabilities\.json/u); + assert.match(frontendCatalog, /generated\/interactive-capabilities\.json/u); + assert.match(searchProvider, /INTERACTIVE_CAPABILITY_CATALOG/u); + assert.doesNotMatch(searchProviders, /settingsSearchProvider/u); + assert.match(controlBridge, /INTERACTIVE_CAPABILITY_CATALOG/u); + assert.doesNotMatch(controlTool, /include_(?:str|bytes)!/u); + assert.match(controlTool, /two-step/u); +}); + +test('Desktop and Web UI share the BitFunControl transport contract', async () => { + const host = await read('src/apps/desktop/src/bitfun_control_host.rs'); + const bridge = await read('src/web-ui/src/app/global-search/bitfunControlBridge.ts'); + const desktopRegistration = await read('src/apps/desktop/src/lib.rs'); + + for (const source of [host, bridge]) { + assert.match(source, /agentic:\/\/bitfun-control-request/u); + } + assert.match(host, /#\[serde\(rename_all = "camelCase"\)\]/u); + assert.match(bridge, /api\.invoke\('mark_bitfun_control_surface_ready'\)/u); + assert.match(bridge, /api\.invoke\('report_bitfun_control_result'/u); + assert.match(desktopRegistration, /bitfun_control_host::mark_bitfun_control_surface_ready/u); + assert.match(desktopRegistration, /bitfun_control_host::report_bitfun_control_result/u); +}); diff --git a/src/apps/cli/src/peer_host/deny.rs b/src/apps/cli/src/peer_host/deny.rs index 5b428ea1ce..6e88539b7b 100644 --- a/src/apps/cli/src/peer_host/deny.rs +++ b/src/apps/cli/src/peer_host/deny.rs @@ -74,6 +74,7 @@ static LOCAL_ONLY_COMMANDS: &[&str] = &[ "remote_connect_set_bot_verbose_mode", "computer_use_request_permissions", "computer_use_open_system_settings", + "browser_webview_set_agent_target_state", "relay_deploy_preflight", "relay_deploy_install_docker", "relay_deploy_start", @@ -211,6 +212,13 @@ mod tests { } } + #[test] + fn built_in_browser_target_lifecycle_stays_on_the_controller_device() { + assert!(is_local_only_command( + "browser_webview_set_agent_target_state" + )); + } + /// Reading why Git refuses a repository is safe to answer for a controller /// and is implemented here; granting the exception writes this user's /// global Git configuration and must be decided at this machine. Being diff --git a/src/apps/desktop/src/api/browser_api.rs b/src/apps/desktop/src/api/browser_api.rs index 2bfe51b87b..671892fdce 100644 --- a/src/apps/desktop/src/api/browser_api.rs +++ b/src/apps/desktop/src/api/browser_api.rs @@ -3,7 +3,10 @@ //! Browser webviews are created as native child webviews by this desktop //! adapter so stream-specific initialization can run before page scripts. +use bitfun_core::agentic::tools::browser_control::BuiltInBrowserTarget; use serde::Deserialize; +use std::collections::HashMap; +use std::sync::{Mutex, OnceLock}; use tauri::Manager; const VIDEO_DECODER_MODE_ENV: &str = "BITFUN_BROWSER_VIDEO_DECODER_MODE"; @@ -98,7 +101,37 @@ pub struct WebviewCreateRequest { pub height: f64, } -fn validate_browser_label(label: &str) -> Result<(), String> { +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BrowserAgentTargetStateRequest { + pub label: String, + pub active: bool, +} + +#[derive(Clone, Debug, Default)] +struct BrowserTargetRecord { + active: bool, + last_active_seq: u64, + url: String, + title: Option, +} + +#[derive(Default)] +struct BrowserTargetRegistry { + next_seq: u64, + records: HashMap, +} + +static BROWSER_TARGETS: OnceLock> = OnceLock::new(); + +fn lock_browser_targets() -> std::sync::MutexGuard<'static, BrowserTargetRegistry> { + BROWSER_TARGETS + .get_or_init(|| Mutex::new(BrowserTargetRegistry::default())) + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) +} + +pub(crate) fn validate_browser_label(label: &str) -> Result<(), String> { if label.starts_with("embedded-browser-view-") || label.starts_with("embedded-browser-panel-view-") { @@ -108,6 +141,71 @@ fn validate_browser_label(label: &str) -> Result<(), String> { } } +fn register_browser_target(label: &str, url: &str) { + lock_browser_targets().records.insert( + label.to_string(), + BrowserTargetRecord { + url: url.to_string(), + ..BrowserTargetRecord::default() + }, + ); +} + +pub(crate) fn update_browser_target_url(label: &str, url: &str) { + if let Some(record) = lock_browser_targets().records.get_mut(label) { + record.url = url.to_string(); + // A navigation invalidates the cached document title. The async + // automation host refreshes it from the page before target discovery + // is returned to ControlHub. + record.title = None; + } +} + +pub(crate) fn update_browser_target_metadata(label: &str, url: &str, title: &str) { + if let Some(record) = lock_browser_targets().records.get_mut(label) { + record.url = url.to_string(); + record.title = Some(title.to_string()); + } +} + +pub(crate) fn unregister_browser_target(label: &str) { + lock_browser_targets().records.remove(label); +} + +pub(crate) fn list_browser_targets(app: &tauri::AppHandle) -> Vec { + let mut registry = lock_browser_targets(); + registry + .records + .retain(|label, _| app.get_webview(label).is_some()); + let mut targets = registry + .records + .iter() + .map(|(label, record)| { + let url = app + .get_webview(label) + .and_then(|webview| { + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| webview.url())) + .ok() + .and_then(Result::ok) + }) + .map(|url| url.to_string()) + .filter(|url| !url.is_empty()) + .unwrap_or_else(|| record.url.clone()); + ( + record.last_active_seq, + BuiltInBrowserTarget { + id: label.clone(), + url, + title: record.title.clone().unwrap_or_default(), + active: record.active, + }, + ) + }) + .collect::>(); + targets.sort_by(|left, right| right.0.cmp(&left.0)); + targets.into_iter().map(|(_, target)| target).collect() +} + fn validate_webview_bounds(x: f64, y: f64, width: f64, height: f64) -> Result<(), String> { if !x.is_finite() || !y.is_finite() @@ -163,7 +261,34 @@ pub async fn browser_webview_create( webview .hide() - .map_err(|e| format!("failed to hide browser webview before positioning: {e}")) + .map_err(|e| format!("failed to hide browser webview before positioning: {e}"))?; + let target_url = webview.url().map(|url| url.to_string()).unwrap_or_default(); + register_browser_target(webview.label(), &target_url); + Ok(()) +} + +/// Advertise which built-in browser surface the Agent should target. This is +/// lifecycle metadata only; browser actions remain in the shared Rust action +/// layer and native WebView adapter. +#[tauri::command] +pub async fn browser_webview_set_agent_target_state( + request: BrowserAgentTargetStateRequest, +) -> Result<(), String> { + validate_browser_label(&request.label)?; + let mut registry = lock_browser_targets(); + if request.active { + registry.next_seq = registry.next_seq.saturating_add(1); + let next_seq = registry.next_seq; + for record in registry.records.values_mut() { + record.active = false; + } + let record = registry.records.entry(request.label).or_default(); + record.active = true; + record.last_active_seq = next_seq; + } else if let Some(record) = registry.records.get_mut(&request.label) { + record.active = false; + } + Ok(()) } #[tauri::command] diff --git a/src/apps/desktop/src/api/peer_host_invoke.rs b/src/apps/desktop/src/api/peer_host_invoke.rs index fcc2800946..cf64e056fb 100644 --- a/src/apps/desktop/src/api/peer_host_invoke.rs +++ b/src/apps/desktop/src/api/peer_host_invoke.rs @@ -103,6 +103,8 @@ static LOCAL_ONLY_COMMANDS: &[&str] = &[ // This-machine computer-use / OS permission prompts "computer_use_request_permissions", "computer_use_open_system_settings", + // Native child-WebView lifecycle belongs to the controller window. + "browser_webview_set_agent_target_state", // Detached dispatch uses controller-owned SSH credentials and observers. "dispatch_list_targets", "dispatch_probe_target", @@ -530,6 +532,13 @@ mod tests { } } + #[test] + fn built_in_browser_target_lifecycle_is_refused_on_the_peer() { + assert!(is_local_only_command( + "browser_webview_set_agent_target_state" + )); + } + /// Reading why Git refuses a repository is safe to answer for a /// controller; granting the exception writes this user's global Git /// configuration and must be decided at this machine. diff --git a/src/apps/desktop/src/api/remote_workspace_policy.rs b/src/apps/desktop/src/api/remote_workspace_policy.rs index e36545181d..1e6ac055ad 100644 --- a/src/apps/desktop/src/api/remote_workspace_policy.rs +++ b/src/apps/desktop/src/api/remote_workspace_policy.rs @@ -240,6 +240,10 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "browser_webview_set_bounds", RemoteWorkspacePolicy::LocalOnly, ), + ( + "browser_webview_set_agent_target_state", + RemoteWorkspacePolicy::LocalOnly, + ), ("btw_ask_stream", RemoteWorkspacePolicy::RemoteRouted), ("btw_cancel", RemoteWorkspacePolicy::RemoteRouted), ( @@ -1559,6 +1563,10 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = RemoteWorkspacePolicy::RemoteRouted, ), ("remote_write_file", RemoteWorkspacePolicy::RemoteRouted), + ( + "mark_bitfun_control_surface_ready", + RemoteWorkspacePolicy::WorkspaceAgnostic, + ), ( "remove_recent_workspace", RemoteWorkspacePolicy::LegacyUnaudited, @@ -1572,6 +1580,10 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "replace_mode_skill_selection", RemoteWorkspacePolicy::LegacyUnaudited, ), + ( + "report_bitfun_control_result", + RemoteWorkspacePolicy::WorkspaceAgnostic, + ), ( "report_canvas_runtime_error", RemoteWorkspacePolicy::LegacyUnaudited, diff --git a/src/apps/desktop/src/bitfun_control_host.rs b/src/apps/desktop/src/bitfun_control_host.rs new file mode 100644 index 0000000000..ed47af414c --- /dev/null +++ b/src/apps/desktop/src/bitfun_control_host.rs @@ -0,0 +1,112 @@ +//! Desktop adapter for the platform-neutral BitFunControl tool host port. + +use std::collections::HashMap; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, Mutex, OnceLock}; +use std::time::Duration; + +use bitfun_core::agentic::tools::bitfun_control_host::{ + set_bitfun_control_handler, BitFunControlHostRequest, +}; +use bitfun_core::infrastructure::events::{emit_global_event, BackendEvent}; +use serde::Deserialize; +use serde_json::Value; +use tokio::sync::oneshot; + +const BITFUN_CONTROL_REQUEST_EVENT: &str = "agentic://bitfun-control-request"; +const BITFUN_CONTROL_RESPONSE_TIMEOUT: Duration = Duration::from_secs(120); + +type PendingResponse = oneshot::Sender>; + +static NEXT_REQUEST_ID: AtomicU64 = AtomicU64::new(1); +static PENDING_RESPONSES: OnceLock>> = OnceLock::new(); + +fn pending_responses() -> &'static Mutex> { + PENDING_RESPONSES.get_or_init(|| Mutex::new(HashMap::new())) +} + +fn lock_pending_responses() -> std::sync::MutexGuard<'static, HashMap> { + pending_responses() + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) +} + +async fn dispatch_request(request: BitFunControlHostRequest) -> Result { + let request_id = format!( + "bitfun-control-{}-{}", + std::process::id(), + NEXT_REQUEST_ID.fetch_add(1, Ordering::Relaxed) + ); + let (sender, receiver) = oneshot::channel(); + lock_pending_responses().insert(request_id.clone(), sender); + + let mut payload = serde_json::to_value(request).map_err(|error| error.to_string())?; + let Some(payload) = payload.as_object_mut() else { + lock_pending_responses().remove(&request_id); + return Err("BitFunControl request serialization produced an invalid payload".to_string()); + }; + payload.insert("requestId".to_string(), Value::String(request_id.clone())); + + if let Err(error) = emit_global_event(BackendEvent::Custom { + event_name: BITFUN_CONTROL_REQUEST_EVENT.to_string(), + payload: Value::Object(payload.clone()), + }) + .await + { + lock_pending_responses().remove(&request_id); + return Err(format!("Failed to send BitFunControl request: {error}")); + } + + match tokio::time::timeout(BITFUN_CONTROL_RESPONSE_TIMEOUT, receiver).await { + Ok(Ok(result)) => result, + Ok(Err(_)) => Err("BitFunControl response channel closed".to_string()), + Err(_) => { + lock_pending_responses().remove(&request_id); + Err("BitFunControl timed out waiting for the active product surface".to_string()) + } + } +} + +pub(crate) fn install() { + set_bitfun_control_handler(Arc::new(|request| { + Box::pin(async move { dispatch_request(request).await }) + })); +} + +/// Advertise BitFunControl only after the Web UI listener is installed. +#[tauri::command] +pub(crate) fn mark_bitfun_control_surface_ready() { + install(); +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct ReportBitFunControlResultRequest { + request_id: String, + success: bool, + #[serde(default)] + result: Option, + #[serde(default)] + error: Option, +} + +/// Return a product-surface result to the waiting BitFunControl tool call. +#[tauri::command] +pub(crate) async fn report_bitfun_control_result( + request: ReportBitFunControlResultRequest, +) -> Result<(), String> { + let sender = lock_pending_responses() + .remove(&request.request_id) + .ok_or_else(|| "BitFunControl request is no longer pending".to_string())?; + let result = if request.success { + Ok(request.result.unwrap_or(Value::Null)) + } else { + Err(request + .error + .filter(|message| !message.trim().is_empty()) + .unwrap_or_else(|| "BitFunControl request failed".to_string())) + }; + sender + .send(result) + .map_err(|_| "BitFunControl request receiver is no longer available".to_string()) +} diff --git a/src/apps/desktop/src/builtin_browser_host.rs b/src/apps/desktop/src/builtin_browser_host.rs new file mode 100644 index 0000000000..c75308d92e --- /dev/null +++ b/src/apps/desktop/src/builtin_browser_host.rs @@ -0,0 +1,123 @@ +//! Desktop adapter for the built-in browser automation host port. + +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +use async_trait::async_trait; +use bitfun_core::agentic::tools::browser_control::builtin_browser::{ + set_builtin_browser_host, BuiltInBrowserCommand, BuiltInBrowserHost, BuiltInBrowserTarget, +}; +use serde_json::{json, Value}; +use tauri::AppHandle; +use tokio::sync::RwLock; + +use crate::api::browser_api; + +struct DesktopBuiltInBrowserHost { + app: AppHandle, + drivers: RwLock>>, +} + +impl DesktopBuiltInBrowserHost { + fn new(app: AppHandle) -> Self { + Self { + app, + drivers: RwLock::new(HashMap::new()), + } + } + + async fn driver( + &self, + target_id: &str, + ) -> Result, String> { + browser_api::validate_browser_label(target_id)?; + if let Some(driver) = self.drivers.read().await.get(target_id).cloned() { + return Ok(driver); + } + let driver = Arc::new( + bitfun_webdriver::EmbeddedWebviewAutomation::attach(self.app.clone(), target_id) + .await?, + ); + self.drivers + .write() + .await + .insert(target_id.to_string(), driver.clone()); + Ok(driver) + } +} + +#[async_trait] +impl BuiltInBrowserHost for DesktopBuiltInBrowserHost { + async fn list_targets(&self) -> Result, String> { + let mut targets = browser_api::list_browser_targets(&self.app); + let live_ids = targets + .iter() + .map(|target| target.id.clone()) + .collect::>(); + let stale_drivers = { + let mut drivers = self.drivers.write().await; + let stale_ids = drivers + .keys() + .filter(|target_id| !live_ids.contains(*target_id)) + .cloned() + .collect::>(); + stale_ids + .into_iter() + .filter_map(|target_id| drivers.remove(&target_id)) + .collect::>() + }; + for driver in stale_drivers { + driver.detach().await; + } + for target in &mut targets { + if target.title.is_empty() { + if let Ok(driver) = self.driver(&target.id).await { + if let Ok(result) = driver + .execute( + "Runtime.evaluate", + Some(json!({ + "expression": "({ title: document.title, url: window.location.href })", + "returnByValue": true, + "awaitPromise": true, + })), + ) + .await + { + if let Some(identity) = result.pointer("/result/value") { + if let Some(url) = identity.get("url").and_then(Value::as_str) { + target.url = url.to_string(); + } + if let Some(title) = identity.get("title").and_then(Value::as_str) { + target.title = title.to_string(); + } + browser_api::update_browser_target_metadata( + &target.id, + &target.url, + &target.title, + ); + } + } + } + } + if target.title.is_empty() { + target.title = "Built-in browser".to_string(); + } + } + Ok(targets) + } + + async fn execute(&self, command: BuiltInBrowserCommand) -> Result { + let driver = self.driver(&command.target_id).await?; + let result = driver.execute(&command.method, command.params).await; + if command.method == "Page.close" && result.is_ok() { + self.drivers.write().await.remove(&command.target_id); + driver.detach().await; + browser_api::unregister_browser_target(&command.target_id); + } + result + } +} + +pub(crate) fn install(app: AppHandle) { + set_builtin_browser_host(Arc::new(DesktopBuiltInBrowserHost::new(app))); +} diff --git a/src/apps/desktop/src/lib.rs b/src/apps/desktop/src/lib.rs index 34376fd767..601abe25d0 100644 --- a/src/apps/desktop/src/lib.rs +++ b/src/apps/desktop/src/lib.rs @@ -22,6 +22,8 @@ pub mod api; pub mod appearance; +mod bitfun_control_host; +mod builtin_browser_host; pub mod computer_use; pub mod crash_diagnostics; mod embedded_relay_host; @@ -757,13 +759,20 @@ pub async fn run() { tauri::webview::PageLoadEvent::Started => "started", tauri::webview::PageLoadEvent::Finished => "finished", }; + let url = payload.url().to_string(); + api::browser_api::update_browser_target_url(label, &url); + bitfun_core::agentic::tools::browser_control::builtin_browser::publish_builtin_browser_page_load( + label, + event, + &url, + ); let _ = webview.emit_to( "main", BROWSER_WEBVIEW_PAGE_LOAD_EVENT, serde_json::json!({ "label": label, "event": event, - "url": payload.url(), + "url": url, }), ); } @@ -1020,6 +1029,7 @@ pub async fn run() { ); let webdriver_started = Instant::now(); bitfun_webdriver::maybe_start(app_handle.clone()); + builtin_browser_host::install(app_handle.clone()); startup_trace.record_elapsed_step( "native_setup", "maybe_start_webdriver", @@ -1327,6 +1337,8 @@ pub async fn run() { initialize_workspace_startup_state, get_available_tools, report_ide_control_result, + bitfun_control_host::mark_bitfun_control_surface_ready, + bitfun_control_host::report_bitfun_control_result, get_health_status, get_statistics, test_ai_connection, @@ -1841,6 +1853,7 @@ pub async fn run() { api::browser_api::browser_webview_navigate, api::browser_api::browser_webview_reload, api::browser_api::browser_webview_set_bounds, + api::browser_api::browser_webview_set_agent_target_state, api::browser_api::browser_get_url, // Browser Control API (CDP-based user browser control) api::browser_control_api::browser_control_list_browsers, diff --git a/src/crates/adapters/webdriver/src/automation.rs b/src/crates/adapters/webdriver/src/automation.rs new file mode 100644 index 0000000000..86352afc8a --- /dev/null +++ b/src/crates/adapters/webdriver/src/automation.rs @@ -0,0 +1,410 @@ +//! Native WebView adapter for BitFun's shared browser-action contract. +//! +//! This module translates browser-engine primitives only. Snapshot refs, +//! selector resolution, click guards, waits, and every other product action +//! remain in `bitfun-core::BrowserActions` and are therefore identical for +//! CDP and built-in browser targets. + +use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; +use base64::Engine as _; +use image::codecs::jpeg::JpegEncoder; +use serde_json::{json, Value}; +use tauri::{AppHandle, Manager}; + +use crate::executor::session::{build_native_cookie, to_webdriver_cookie}; +use crate::platform::{self, Cookie}; +use crate::runtime; +use crate::server::AppState; +use crate::webdriver::Session; + +use std::sync::Arc; + +const SCRIPT_TIMEOUT_MS: u64 = 30_000; + +#[derive(Clone)] +pub struct EmbeddedWebviewAutomation { + state: Arc, + session: Session, +} + +impl EmbeddedWebviewAutomation { + pub async fn attach(app: AppHandle, label: &str) -> Result { + if app.get_webview(label).is_none() { + return Err(format!("Webview not found: {label}")); + } + let state = crate::automation_state(app); + let mut session = state.sessions.write().await.create(label.to_string()); + session.timeouts.page_load = 15_000; + session.timeouts.script = SCRIPT_TIMEOUT_MS; + if let Ok(stored) = state.sessions.write().await.get_mut(&session.id) { + stored.timeouts = session.timeouts.clone(); + } + Ok(Self { state, session }) + } + + pub fn target_id(&self) -> &str { + &self.session.current_window + } + + pub async fn detach(&self) { + self.state.sessions.write().await.delete(&self.session.id); + } + + fn webview(&self) -> Result { + self.state + .app + .get_webview(&self.session.current_window) + .ok_or_else(|| format!("Webview not found: {}", self.session.current_window)) + } + + async fn run_script(&self, script: &str, args: Vec) -> Result { + runtime::run_script(self.state.clone(), &self.session.id, script, args, false) + .await + .map_err(format_webdriver_error) + } + + async fn evaluate_expression(&self, expression: &str) -> Result { + self.run_script( + "async (expression) => await (0, eval)(expression)", + vec![Value::String(expression.to_string())], + ) + .await + } + + async fn perform_actions(&self, actions: Value) -> Result<(), String> { + self.run_script( + "async (actions) => { await window.__bitfunWd.performActions(actions); return null; }", + vec![actions], + ) + .await?; + Ok(()) + } + + pub async fn execute(&self, method: &str, params: Option) -> Result { + let params = params.unwrap_or_else(|| json!({})); + match method { + "Page.enable" + | "Runtime.enable" + | "Network.enable" + | "DOM.enable" + | "Page.setLifecycleEventsEnabled" + | "Emulation.clearDeviceMetricsOverride" => Ok(json!({})), + "Page.navigate" => { + let url = required_string(¶ms, "url", method)?; + let parsed = url + .parse::() + .map_err(|error| format!("Invalid navigation URL: {error}"))?; + match parsed.scheme() { + "http" | "https" => {} + scheme => return Err(format!("Unsupported navigation protocol: {scheme}")), + } + self.webview()? + .navigate(parsed) + .map_err(|error| format!("Navigation failed: {error}"))?; + Ok(json!({ "frameId": self.target_id() })) + } + "Page.reload" => { + self.webview()? + .reload() + .map_err(|error| format!("Reload failed: {error}"))?; + Ok(json!({})) + } + "Runtime.evaluate" => { + let expression = required_string(¶ms, "expression", method)?; + match self.evaluate_expression(expression).await { + Ok(value) => Ok(json!({ + "result": { + "type": javascript_type(&value), + "value": value, + } + })), + Err(error) => Ok(json!({ + "exceptionDetails": { + "text": error, + "exception": { "description": error }, + } + })), + } + } + "Input.dispatchMouseEvent" => self.dispatch_mouse_event(¶ms).await, + "Input.insertText" => { + let text = required_string(¶ms, "text", method)?; + self.run_script( + "(text) => { const target = document.activeElement; if (!target) throw new Error('No focused element'); window.__bitfunWd.insertText(target, text); return null; }", + vec![Value::String(text.to_string())], + ) + .await?; + Ok(json!({})) + } + "Input.dispatchKeyEvent" => self.dispatch_key_event(¶ms).await, + "Page.getLayoutMetrics" => { + let value = self + .evaluate_expression( + "(() => ({ width: Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth || 0), height: Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight || 0) }))()", + ) + .await?; + let width = value.get("width").cloned().unwrap_or(json!(0)); + let height = value.get("height").cloned().unwrap_or(json!(0)); + Ok(json!({ + "cssContentSize": { "x": 0, "y": 0, "width": width, "height": height }, + "contentSize": { "x": 0, "y": 0, "width": width, "height": height }, + })) + } + "Page.captureScreenshot" => { + let format = params + .get("format") + .and_then(Value::as_str) + .unwrap_or("png"); + let quality = params + .get("quality") + .and_then(Value::as_u64) + .unwrap_or(80) + .min(100) as u8; + let png = platform::take_screenshot(self.webview()?, SCRIPT_TIMEOUT_MS) + .await + .map_err(format_webdriver_error)?; + let data = if format.eq_ignore_ascii_case("jpeg") { + png_to_jpeg(png, quality).await? + } else { + png + }; + Ok(json!({ "data": data })) + } + "Network.getCookies" => { + let cookies = self + .webview()? + .cookies() + .map_err(|error| format!("Failed to read cookies: {error}"))?; + let cookies = cookies + .iter() + .map(to_webdriver_cookie) + .map(|cookie| { + let mut value = serde_json::to_value(cookie).unwrap_or(Value::Null); + if let Some(object) = value.as_object_mut() { + if let Some(expiry) = object.remove("expiry") { + object.insert("expires".to_string(), expiry); + } + } + value + }) + .collect::>(); + Ok(json!({ "cookies": cookies })) + } + "Network.setCookie" => { + let cookie = cookie_from_cdp(¶ms)?; + self.webview()? + .set_cookie(build_native_cookie(&cookie).map_err(format_webdriver_error)?) + .map_err(|error| format!("Failed to set cookie: {error}"))?; + Ok(json!({ "success": true })) + } + "Page.close" => { + self.webview()? + .close() + .map_err(|error| format!("Failed to close WebView: {error}"))?; + Ok(json!({})) + } + "Emulation.setDeviceMetricsOverride" => Err( + "Full-page device-metrics override is not available for an embedded WebView" + .to_string(), + ), + method if method.starts_with("DOM.") => Err(format!( + "{method} is a CDP-only extension and is not available for an embedded WebView" + )), + other => Err(format!( + "Browser primitive {other} is not supported by the embedded WebView adapter" + )), + } + } + + async fn dispatch_mouse_event(&self, params: &Value) -> Result { + let event_type = required_string(params, "type", "Input.dispatchMouseEvent")?; + let x = params + .get("x") + .and_then(Value::as_f64) + .unwrap_or(0.0) + .round() as i64; + let y = params + .get("y") + .and_then(Value::as_f64) + .unwrap_or(0.0) + .round() as i64; + let actions = match event_type { + "mousePressed" => json!([{ + "type": "pointer", "id": "bitfun-mouse", + "parameters": { "pointerType": "mouse" }, + "actions": [ + { "type": "pointerMove", "x": x, "y": y, "duration": 0, "origin": "viewport" }, + { "type": "pointerDown", "button": 0 } + ] + }]), + "mouseReleased" => json!([{ + "type": "pointer", "id": "bitfun-mouse", + "parameters": { "pointerType": "mouse" }, + "actions": [ + { "type": "pointerMove", "x": x, "y": y, "duration": 0, "origin": "viewport" }, + { "type": "pointerUp", "button": 0 } + ] + }]), + "mouseMoved" => json!([{ + "type": "pointer", "id": "bitfun-mouse", + "parameters": { "pointerType": "mouse" }, + "actions": [ + { "type": "pointerMove", "x": x, "y": y, "duration": 0, "origin": "viewport" } + ] + }]), + "mouseWheel" => json!([{ + "type": "wheel", "id": "bitfun-wheel", + "actions": [{ + "type": "scroll", "x": x, "y": y, + "deltaX": params.get("deltaX").and_then(Value::as_i64).unwrap_or(0), + "deltaY": params.get("deltaY").and_then(Value::as_i64).unwrap_or(0), + "duration": 0, "origin": "viewport" + }] + }]), + other => return Err(format!("Unsupported mouse event type: {other}")), + }; + self.perform_actions(actions).await?; + Ok(json!({})) + } + + async fn dispatch_key_event(&self, params: &Value) -> Result { + let event_type = required_string(params, "type", "Input.dispatchKeyEvent")?; + let key = params.get("key").and_then(Value::as_str).unwrap_or(""); + let value = webdriver_key(key); + let action_type = match event_type { + "keyDown" | "rawKeyDown" => "keyDown", + "keyUp" => "keyUp", + other => return Err(format!("Unsupported key event type: {other}")), + }; + self.perform_actions(json!([{ + "type": "key", "id": "bitfun-keyboard", + "actions": [{ "type": action_type, "value": value }] + }])) + .await?; + Ok(json!({})) + } +} + +fn required_string<'a>(params: &'a Value, key: &str, method: &str) -> Result<&'a str, String> { + params + .get(key) + .and_then(Value::as_str) + .ok_or_else(|| format!("{method} requires '{key}'")) +} + +fn javascript_type(value: &Value) -> &'static str { + match value { + Value::Null => "object", + Value::Bool(_) => "boolean", + Value::Number(_) => "number", + Value::String(_) => "string", + Value::Array(_) | Value::Object(_) => "object", + } +} + +fn webdriver_key(key: &str) -> &str { + match key { + "Backspace" => "\u{E003}", + "Tab" => "\u{E004}", + "Enter" | "Return" => "\u{E007}", + "Escape" | "Esc" => "\u{E00C}", + "Space" => "\u{E00D}", + "PageUp" => "\u{E00E}", + "PageDown" => "\u{E00F}", + "End" => "\u{E010}", + "Home" => "\u{E011}", + "ArrowLeft" => "\u{E012}", + "ArrowUp" => "\u{E013}", + "ArrowRight" => "\u{E014}", + "ArrowDown" => "\u{E015}", + "Delete" => "\u{E017}", + other => other, + } +} + +fn cookie_from_cdp(params: &Value) -> Result { + let name = required_string(params, "name", "Network.setCookie")?.to_string(); + let value = required_string(params, "value", "Network.setCookie")?.to_string(); + Ok(Cookie { + name, + value, + path: params + .get("path") + .and_then(Value::as_str) + .map(str::to_string), + domain: params + .get("domain") + .and_then(Value::as_str) + .map(str::to_string), + secure: params + .get("secure") + .and_then(Value::as_bool) + .unwrap_or(false), + http_only: params + .get("httpOnly") + .and_then(Value::as_bool) + .unwrap_or(false), + expiry: params + .get("expires") + .or_else(|| params.get("expiry")) + .and_then(Value::as_f64) + .filter(|value| value.is_finite() && *value >= 0.0) + .map(|value| value as u64), + same_site: params + .get("sameSite") + .and_then(Value::as_str) + .map(str::to_string), + }) +} + +fn format_webdriver_error(error: crate::server::response::WebDriverErrorResponse) -> String { + if let Some(stacktrace) = error.stacktrace.filter(|value| !value.trim().is_empty()) { + format!("{}: {}\n{}", error.error, error.message, stacktrace) + } else { + format!("{}: {}", error.error, error.message) + } +} + +async fn png_to_jpeg(png_base64: String, quality: u8) -> Result { + tokio::task::spawn_blocking(move || { + let bytes = BASE64_STANDARD + .decode(png_base64) + .map_err(|error| format!("Invalid screenshot PNG: {error}"))?; + let image = image::load_from_memory(&bytes) + .map_err(|error| format!("Failed to decode screenshot PNG: {error}"))?; + let mut jpeg = Vec::new(); + JpegEncoder::new_with_quality(&mut jpeg, quality) + .encode_image(&image) + .map_err(|error| format!("Failed to encode screenshot JPEG: {error}"))?; + Ok(BASE64_STANDARD.encode(jpeg)) + }) + .await + .map_err(|error| format!("Screenshot conversion task failed: {error}"))? +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn key_translation_matches_webdriver_special_key_contract() { + assert_eq!(webdriver_key("Enter"), "\u{E007}"); + assert_eq!(webdriver_key("Escape"), "\u{E00C}"); + assert_eq!(webdriver_key("a"), "a"); + } + + #[test] + fn cdp_cookie_shape_maps_to_native_cookie_contract() { + let cookie = cookie_from_cdp(&json!({ + "name": "session", + "value": "abc", + "httpOnly": true, + "sameSite": "Lax", + "expires": 1234, + })) + .expect("cookie"); + assert_eq!(cookie.name, "session"); + assert!(cookie.http_only); + assert_eq!(cookie.expiry, Some(1234)); + } +} diff --git a/src/crates/adapters/webdriver/src/executor/mod.rs b/src/crates/adapters/webdriver/src/executor/mod.rs index 463bdb0171..868ddf878d 100644 --- a/src/crates/adapters/webdriver/src/executor/mod.rs +++ b/src/crates/adapters/webdriver/src/executor/mod.rs @@ -1,7 +1,7 @@ mod element; mod interaction; mod navigation; -mod session; +pub(crate) mod session; mod window; use std::sync::Arc; diff --git a/src/crates/adapters/webdriver/src/executor/session.rs b/src/crates/adapters/webdriver/src/executor/session.rs index efa8c7d602..1f31c03b91 100644 --- a/src/crates/adapters/webdriver/src/executor/session.rs +++ b/src/crates/adapters/webdriver/src/executor/session.rs @@ -74,7 +74,7 @@ impl BridgeExecutor { } } -fn to_webdriver_cookie(cookie: &NativeCookie<'_>) -> Cookie { +pub(crate) fn to_webdriver_cookie(cookie: &NativeCookie<'_>) -> Cookie { Cookie { name: cookie.name().to_string(), value: cookie.value().to_string(), @@ -102,7 +102,9 @@ fn parse_same_site(value: Option<&str>) -> Result, WebDriverErr } } -fn build_native_cookie(cookie: &Cookie) -> Result, WebDriverErrorResponse> { +pub(crate) fn build_native_cookie( + cookie: &Cookie, +) -> Result, WebDriverErrorResponse> { let mut builder = NativeCookie::build((cookie.name.clone(), cookie.value.clone())); if let Some(path) = cookie.path.clone() { diff --git a/src/crates/adapters/webdriver/src/lib.rs b/src/crates/adapters/webdriver/src/lib.rs index dbfdc8664a..888c803fee 100644 --- a/src/crates/adapters/webdriver/src/lib.rs +++ b/src/crates/adapters/webdriver/src/lib.rs @@ -1,3 +1,4 @@ +mod automation; mod executor; pub mod platform; mod runtime; @@ -5,16 +6,33 @@ pub mod server; pub mod webdriver; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use serde_json::Value; use tauri::AppHandle; use server::AppState; +pub use automation::EmbeddedWebviewAutomation; + const DEFAULT_WEBDRIVER_LABEL: &str = "main"; static SERVER_STARTED: AtomicBool = AtomicBool::new(false); +static SHARED_STATE: OnceLock> = OnceLock::new(); + +fn shared_state(app: AppHandle, preferred_label: String, port: u16) -> Arc { + SHARED_STATE + .get_or_init(|| { + let state = Arc::new(AppState::new(app.clone(), preferred_label, port)); + runtime::register_listener(app, state.clone()); + state + }) + .clone() +} + +pub(crate) fn automation_state(app: AppHandle) -> Arc { + shared_state(app, DEFAULT_WEBDRIVER_LABEL.to_string(), 0) +} pub fn maybe_start(app: AppHandle) { if !(cfg!(debug_assertions) || cfg!(feature = "embedded")) { @@ -34,9 +52,7 @@ pub fn maybe_start(app: AppHandle) { let preferred_label = std::env::var("BITFUN_WEBDRIVER_LABEL").unwrap_or_else(|_| DEFAULT_WEBDRIVER_LABEL.into()); - let state = Arc::new(AppState::new(app.clone(), preferred_label, port)); - - runtime::register_listener(app, state.clone()); + let state = shared_state(app, preferred_label, port); server::start(state); } diff --git a/src/crates/assembly/core/src/agentic/agents/registry/query.rs b/src/crates/assembly/core/src/agentic/agents/registry/query.rs index f5717f26a0..11105f2762 100644 --- a/src/crates/assembly/core/src/agentic/agents/registry/query.rs +++ b/src/crates/assembly/core/src/agentic/agents/registry/query.rs @@ -17,6 +17,23 @@ use bitfun_agent_runtime::agents::subagent_source_presentation_rank; use std::collections::HashSet; use std::path::Path; +const DEFAULT_PRODUCT_CONTROL_TOOL: &str = "BitFunControl"; + +fn append_default_product_control_tool( + allowed_tools: &mut Vec, + registered_tool_names: &[String], +) { + if registered_tool_names + .iter() + .any(|tool| tool == DEFAULT_PRODUCT_CONTROL_TOOL) + && !allowed_tools + .iter() + .any(|tool| tool == DEFAULT_PRODUCT_CONTROL_TOOL) + { + allowed_tools.push(DEFAULT_PRODUCT_CONTROL_TOOL.to_string()); + } +} + impl AgentRegistry { /// Return every effective local agent definition that can participate in /// product-level external-source conflict resolution. Main-agent modes and @@ -87,10 +104,10 @@ impl AgentRegistry { permission_constraints: Default::default(), }; }; - match entry.category { + let registered_tool_names = get_all_registered_tool_names().await; + let mut policy = match entry.category { AgentCategory::Mode => { let mode_configs = get_mode_configs().await; - let registered_tool_names = get_all_registered_tool_names().await; let valid_tools: HashSet = registered_tool_names.iter().cloned().collect(); let profile_id = resolve_mode_config_profile_id(agent_type); let default_tools = entry.agent.default_tools(); @@ -127,7 +144,9 @@ impl AgentRegistry { permission_constraints: entry.agent.permission_constraints().clone(), } } - } + }; + append_default_product_control_tool(&mut policy.allowed_tools, ®istered_tool_names); + policy } /// get agent tools from config @@ -474,3 +493,31 @@ fn local_conflict_info( info.state_reason = availability.state_reason; Some(info) } + +#[cfg(test)] +mod product_control_tool_tests { + use super::*; + + #[test] + fn product_control_is_added_once_when_the_runtime_registered_it() { + let registered = vec!["Read".to_string(), DEFAULT_PRODUCT_CONTROL_TOOL.to_string()]; + let mut allowed = vec!["Read".to_string()]; + + append_default_product_control_tool(&mut allowed, ®istered); + append_default_product_control_tool(&mut allowed, ®istered); + + assert_eq!( + allowed, + vec!["Read".to_string(), DEFAULT_PRODUCT_CONTROL_TOOL.to_string()] + ); + } + + #[test] + fn product_control_is_not_advertised_when_the_runtime_omits_it() { + let mut allowed = vec!["Read".to_string()]; + + append_default_product_control_tool(&mut allowed, &["Read".to_string()]); + + assert_eq!(allowed, vec!["Read".to_string()]); + } +} diff --git a/src/crates/assembly/core/src/agentic/tools/bitfun_control_host.rs b/src/crates/assembly/core/src/agentic/tools/bitfun_control_host.rs new file mode 100644 index 0000000000..7f98d35a39 --- /dev/null +++ b/src/crates/assembly/core/src/agentic/tools/bitfun_control_host.rs @@ -0,0 +1,82 @@ +//! Platform-neutral host port for controlling the active BitFun product surface. + +use std::future::Future; +use std::pin::Pin; +use std::sync::{Arc, OnceLock}; + +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BitFunControlHostRequest { + pub action: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub query: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub capability_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub item_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub operation_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub option_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, +} + +pub type BitFunControlFuture = Pin> + Send>>; +pub type BitFunControlHandler = + Arc BitFunControlFuture + Send + Sync>; + +static BITFUN_CONTROL_HANDLER: OnceLock = OnceLock::new(); + +/// Register the product-surface adapter. The first registered host owns the process. +pub fn set_bitfun_control_handler(handler: BitFunControlHandler) { + let _ = BITFUN_CONTROL_HANDLER.set(handler); +} + +pub fn bitfun_control_host_available() -> bool { + BITFUN_CONTROL_HANDLER.get().is_some() +} + +pub async fn invoke_bitfun_control(request: BitFunControlHostRequest) -> Result { + let Some(handler) = BITFUN_CONTROL_HANDLER.get() else { + return Err("BitFunControl host is not available on this product surface".to_string()); + }; + handler(request).await +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn host_request_uses_the_frontend_camel_case_contract() { + let serialized = serde_json::to_value(BitFunControlHostRequest { + action: "open".to_string(), + query: None, + capability_id: Some("setting.application.input".to_string()), + item_id: Some("shortcut-browser".to_string()), + operation_id: None, + option_id: None, + value: None, + cursor: None, + limit: None, + }) + .unwrap(); + + assert_eq!( + serialized["capabilityId"], + json!("setting.application.input") + ); + assert_eq!(serialized["itemId"], json!("shortcut-browser")); + assert!(serialized.get("capability_id").is_none()); + assert!(serialized.get("item_id").is_none()); + } +} diff --git a/src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs b/src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs index 5459442cde..0300c0c09f 100644 --- a/src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs +++ b/src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs @@ -1,6 +1,6 @@ -//! Atomic browser actions implemented via CDP commands. +//! Atomic browser actions shared by every browser target adapter. -use super::cdp_client::{CdpClient, CdpEvent}; +use super::automation_client::{BrowserAutomationClient, BrowserAutomationEvent}; use crate::agentic::tools::implementations::control_hub::{coded_tool_error, ErrorCode}; use crate::util::errors::{BitFunError, BitFunResult}; use serde_json::{json, Value}; @@ -17,7 +17,7 @@ pub const MAX_WAIT_MS: u64 = 60 * 60 * 1_000; /// not say. Matches the previous hard-coded lifecycle and selector budgets. pub const DEFAULT_CONDITION_TIMEOUT_MS: u64 = 15_000; -/// Result of waiting for a CDP `Page.lifecycleEvent`. +/// Result of waiting for a shared browser lifecycle event. enum LifecycleOutcome { /// One of the requested lifecycle names fired in time. Carries the name /// (e.g. `"load"`, `"networkIdle"`) so callers can report which condition @@ -33,7 +33,7 @@ enum LifecycleOutcome { /// given `frame_id` (or any frame if `frame_id` is `None`). Bounded by a hard /// timeout so a hung page can never wedge the agent. async fn wait_for_lifecycle( - events: &mut broadcast::Receiver, + events: &mut broadcast::Receiver, frame_id: Option<&str>, wanted: &[&str], timeout_ms: u64, @@ -126,16 +126,19 @@ pub(crate) fn classify_evaluate_exception(message: &str) -> BitFunError { } } -/// Classify a CDP transport failure (send/receive level). A dead WebSocket or -/// closed target means the session is unusable and must be re-attached; a CDP -/// timeout means the page did not answer. Anything else passes through so the -/// heuristic fallback in `map_dispatch_error` still applies. +/// Classify a browser-target transport failure (send/receive level). A dead +/// WebSocket or missing native WebView means the session is unusable and must +/// be re-attached; a transport timeout means the page did not answer. Anything +/// else passes through so the heuristic fallback in `map_dispatch_error` still +/// applies. pub(crate) fn classify_transport_error(err: BitFunError) -> BitFunError { let raw = err.to_string(); let message = raw.strip_prefix("Tool error: ").unwrap_or(raw.as_str()); if message.contains("CDP send failed") || message.contains("CDP response channel closed") || message.contains("Target closed") + || message.contains("Webview not found") + || message.contains("WebView not found") { structured_error( ErrorCode::WrongTab, @@ -350,13 +353,13 @@ const SNAPSHOT_SCRIPT: &str = r#" })() "#; -/// High-level browser actions backed by CDP method calls. +/// High-level browser actions backed by a target adapter. pub struct BrowserActions<'a> { - client: &'a CdpClient, + client: &'a dyn BrowserAutomationClient, } impl<'a> BrowserActions<'a> { - pub fn new(client: &'a CdpClient) -> Self { + pub fn new(client: &'a dyn BrowserAutomationClient) -> Self { Self { client } } @@ -422,7 +425,7 @@ impl<'a> BrowserActions<'a> { } LifecycleOutcome::Closed => { return Err(BitFunError::tool( - "Browser closed the CDP connection before page finished loading.".to_string(), + "Browser target closed before the page finished loading.".to_string(), )); } } @@ -508,7 +511,7 @@ impl<'a> BrowserActions<'a> { .unwrap_or("{}"); let mut parsed: Value = serde_json::from_str(text).unwrap_or(json!({})); - if with_backend_node_ids { + if with_backend_node_ids && self.client.capabilities().backend_node_ids { if let Err(e) = self.attach_backend_node_ids(&mut parsed).await { // Don't fail the snapshot — the elements list is still // useful without backendNodeIds. Surface the failure so the @@ -520,6 +523,16 @@ impl<'a> BrowserActions<'a> { ); } } + } else if with_backend_node_ids { + if let Value::Object(map) = &mut parsed { + map.insert( + "backend_node_ids_warning".to_string(), + json!(format!( + "backend node ids are not available for the {} browser target", + self.client.target_kind() + )), + ); + } } Self::attach_snapshot_text(&mut parsed); Ok(parsed) @@ -1215,7 +1228,8 @@ impl<'a> BrowserActions<'a> { "jpeg" }; - if full_page { + let full_page_supported = self.client.capabilities().full_page_screenshot; + if full_page && full_page_supported { if let Ok(metrics) = self.client.send("Page.getLayoutMetrics", None).await { let size = metrics .get("cssContentSize") @@ -1260,7 +1274,7 @@ impl<'a> BrowserActions<'a> { .client .send("Page.captureScreenshot", Some(params)) .await?; - if full_page { + if full_page && full_page_supported { let _ = self .client .send("Emulation.clearDeviceMetricsOverride", None) @@ -1271,7 +1285,16 @@ impl<'a> BrowserActions<'a> { "success": true, "action": "screenshot", "format": normalized, - "full_page": full_page, + "full_page": full_page && full_page_supported, + "full_page_requested": full_page, + "warning": if full_page && !full_page_supported { + Value::String(format!( + "full-page capture is not available for the {} browser target; captured the visible viewport", + self.client.target_kind() + )) + } else { + Value::Null + }, "data_length": data.len(), "base64_data": data, "data_url": format!("data:image/{};base64,{}", normalized, data), @@ -1638,6 +1661,118 @@ impl<'a> BrowserActions<'a> { } } +#[cfg(test)] +mod shared_target_tests { + use super::*; + use crate::agentic::tools::browser_control::{ + BrowserAutomationCapabilities, BrowserAutomationEvent, + }; + use std::sync::Mutex; + + struct FakeEmbeddedClient { + events: broadcast::Sender, + methods: Mutex>, + } + + impl FakeEmbeddedClient { + fn new() -> Self { + Self { + events: broadcast::channel(8).0, + methods: Mutex::new(Vec::new()), + } + } + + fn methods(&self) -> Vec { + self.methods + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) + .clone() + } + } + + #[async_trait::async_trait] + impl BrowserAutomationClient for FakeEmbeddedClient { + async fn send(&self, method: &str, params: Option) -> BitFunResult { + self.methods + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) + .push(method.to_string()); + match method { + "Runtime.evaluate" => { + let expression = params + .as_ref() + .and_then(|value| value.get("expression")) + .and_then(Value::as_str) + .unwrap_or(""); + let value = if expression.contains("offscreen_count") { + json!({ + "url": "https://example.test/", + "title": "Example", + "elements": [{ "ref": "@e1", "tag": "button", "text": "Continue" }], + "offscreen_count": 0, + "cross_origin_frames": 0, + }) + .to_string() + } else { + json!({ + "x": 32, + "y": 24, + "visible": true, + "disabled": false, + "blocked_by": null, + "cross_origin_frame": false, + }) + .to_string() + }; + Ok(json!({ "result": { "type": "string", "value": value } })) + } + "Input.dispatchMouseEvent" => Ok(json!({})), + other => Err(BitFunError::tool(format!("unexpected primitive: {other}"))), + } + } + + fn subscribe_events(&self) -> broadcast::Receiver { + self.events.subscribe() + } + + fn is_connected(&self) -> bool { + true + } + + fn capabilities(&self) -> BrowserAutomationCapabilities { + BrowserAutomationCapabilities::embedded_webview() + } + + fn target_kind(&self) -> &'static str { + "builtin" + } + } + + #[tokio::test] + async fn embedded_target_runs_snapshot_and_click_through_browser_actions() { + let client = FakeEmbeddedClient::new(); + let actions = BrowserActions::new(&client); + + let snapshot = actions.snapshot_with_options(true).await.expect("snapshot"); + assert_eq!(snapshot["elements"][0]["ref"], "@e1"); + assert!(snapshot["backend_node_ids_warning"] + .as_str() + .is_some_and(|warning| warning.contains("builtin"))); + + let clicked = actions.click("@e1").await.expect("click"); + assert_eq!(clicked["success"], true); + assert_eq!( + client.methods(), + vec![ + "Runtime.evaluate", + "Runtime.evaluate", + "Input.dispatchMouseEvent", + "Input.dispatchMouseEvent", + ] + ); + } +} + #[cfg(test)] mod structured_error_tests { use super::*; @@ -1687,6 +1822,16 @@ mod structured_error_tests { assert!(msg.contains("[TIMEOUT]"), "got: {msg}"); } + #[test] + fn classify_transport_error_maps_missing_builtin_target_to_wrong_tab() { + let msg = classify_transport_error(BitFunError::tool( + "Built-in browser adapter failed for Runtime.evaluate: Webview not found".to_string(), + )) + .to_string(); + assert!(msg.contains("[WRONG_TAB]"), "got: {msg}"); + assert!(msg.contains("switch_page"), "got: {msg}"); + } + #[test] fn classify_transport_error_passes_through_other_errors() { let msg = classify_transport_error(BitFunError::tool("CDP error: some detail".to_string())) diff --git a/src/crates/assembly/core/src/agentic/tools/browser_control/automation_client.rs b/src/crates/assembly/core/src/agentic/tools/browser_control/automation_client.rs new file mode 100644 index 0000000000..db8f1f7817 --- /dev/null +++ b/src/crates/assembly/core/src/agentic/tools/browser_control/automation_client.rs @@ -0,0 +1,153 @@ +//! Target-neutral transport contract used by the shared browser action layer. + +use async_trait::async_trait; +use serde_json::Value; +use tokio::sync::broadcast; + +use crate::util::errors::BitFunResult; + +/// A lifecycle or diagnostic event emitted by a browser-engine adapter. +/// +/// The shape intentionally matches CDP's method/params envelope because the +/// shared action layer only needs that small neutral fact. Native WebViews +/// synthesize the same lifecycle events without depending on CDP. +#[derive(Debug, Clone)] +pub struct BrowserAutomationEvent { + pub method: String, + pub params: Value, +} + +/// User-facing actions guaranteed to route through the shared action/session +/// contract on both browser targets. Keep discovery metadata and tests wired +/// to this constant so target parity cannot silently drift. +pub const SHARED_BROWSER_ACTIONS: &[&str] = &[ + "connect", + "tab_new", + "navigate", + "back", + "forward", + "reload", + "snapshot", + "click", + "hover", + "fill", + "type", + "check", + "uncheck", + "select", + "press_key", + "scroll", + "auto_scroll", + "wait", + "get", + "get_text", + "get_url", + "get_title", + "get_html", + "screenshot", + "evaluate", + "fetch", + "cookies", + "set_cookies", + "read_article", + "close", + "list_pages", + "tab_query", + "switch_page", + "list_sessions", +]; + +/// Explicit protocol extensions which cannot be promised by an arbitrary +/// native WebView engine. +pub const EXTERNAL_CDP_EXTENSIONS: &[&str] = &[ + "cdp", + "network", + "network_requests", + "console", + "errors", + "trace", + "dialog", + "set_file_input_files", +]; + +/// Optional target features which cannot be implemented uniformly by every +/// browser engine. The normal DOM interaction surface is intentionally not +/// represented here: implementing [`BrowserAutomationClient`] means those +/// actions use the same [`super::BrowserActions`] code path. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct BrowserAutomationCapabilities { + /// Stable CDP backend node ids can be attached to snapshot entries. + pub backend_node_ids: bool, + /// The target can resize/capture beyond the visible viewport. + pub full_page_screenshot: bool, + /// A native file chooser can be populated by local file paths. + pub file_input: bool, + /// Arbitrary allow-listed CDP methods may be sent by the caller. + pub raw_cdp: bool, + /// CDP network, console, error, and trace event streams are available. + pub protocol_diagnostics: bool, +} + +impl BrowserAutomationCapabilities { + pub const fn cdp() -> Self { + Self { + backend_node_ids: true, + full_page_screenshot: true, + file_input: true, + raw_cdp: true, + protocol_diagnostics: true, + } + } + + pub const fn embedded_webview() -> Self { + Self { + backend_node_ids: false, + full_page_screenshot: false, + file_input: false, + raw_cdp: false, + protocol_diagnostics: false, + } + } +} + +/// Minimal browser-engine port consumed by [`super::BrowserActions`]. +/// +/// The command names form an internal adapter envelope. External Chromium +/// passes them through to CDP; the desktop adapter translates the same +/// primitives to the native WebView/WebDriver implementation. Product logic +/// must stay in `BrowserActions`, never in either adapter. +#[async_trait] +pub trait BrowserAutomationClient: Send + Sync { + async fn send(&self, method: &str, params: Option) -> BitFunResult; + + fn subscribe_events(&self) -> broadcast::Receiver; + + fn is_connected(&self) -> bool; + + fn capabilities(&self) -> BrowserAutomationCapabilities; + + fn target_kind(&self) -> &'static str; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn shared_actions_and_cdp_extensions_are_disjoint_and_unique() { + let shared = SHARED_BROWSER_ACTIONS + .iter() + .copied() + .collect::>(); + let extensions = EXTERNAL_CDP_EXTENSIONS + .iter() + .copied() + .collect::>(); + assert_eq!(shared.len(), SHARED_BROWSER_ACTIONS.len()); + assert_eq!(extensions.len(), EXTERNAL_CDP_EXTENSIONS.len()); + assert!(shared.is_disjoint(&extensions)); + for required in ["snapshot", "click", "fill", "scroll", "screenshot"] { + assert!(shared.contains(required)); + } + } +} diff --git a/src/crates/assembly/core/src/agentic/tools/browser_control/builtin_browser.rs b/src/crates/assembly/core/src/agentic/tools/browser_control/builtin_browser.rs new file mode 100644 index 0000000000..2517196f37 --- /dev/null +++ b/src/crates/assembly/core/src/agentic/tools/browser_control/builtin_browser.rs @@ -0,0 +1,386 @@ +//! Platform-neutral host port for automating BitFun's built-in browser. + +use std::collections::HashMap; +use std::sync::{Arc, OnceLock, RwLock}; + +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use tokio::sync::broadcast; + +use super::automation_client::{ + BrowserAutomationCapabilities, BrowserAutomationClient, BrowserAutomationEvent, +}; +use crate::util::errors::{BitFunError, BitFunResult}; + +const BUILTIN_EVENT_CAPACITY: usize = 128; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct BuiltInBrowserTarget { + pub id: String, + pub url: String, + pub title: String, + pub active: bool, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct BuiltInBrowserCommand { + pub target_id: String, + pub method: String, + #[serde(default)] + pub params: Option, +} + +#[async_trait] +pub trait BuiltInBrowserHost: Send + Sync { + async fn list_targets(&self) -> Result, String>; + + async fn execute(&self, command: BuiltInBrowserCommand) -> Result; +} + +type HostSlot = RwLock>>; + +static BUILTIN_BROWSER_HOST: OnceLock = OnceLock::new(); +static BUILTIN_BROWSER_EVENTS: OnceLock< + RwLock>>, +> = OnceLock::new(); +static DEFAULT_BUILTIN_TARGET: OnceLock>> = OnceLock::new(); + +fn host_slot() -> &'static HostSlot { + BUILTIN_BROWSER_HOST.get_or_init(|| RwLock::new(None)) +} + +fn event_channels() -> &'static RwLock>> { + BUILTIN_BROWSER_EVENTS.get_or_init(|| RwLock::new(HashMap::new())) +} + +fn default_target_slot() -> &'static RwLock> { + DEFAULT_BUILTIN_TARGET.get_or_init(|| RwLock::new(None)) +} + +fn read_lock(lock: &RwLock) -> std::sync::RwLockReadGuard<'_, T> { + lock.read().unwrap_or_else(|poisoned| poisoned.into_inner()) +} + +fn write_lock(lock: &RwLock) -> std::sync::RwLockWriteGuard<'_, T> { + lock.write() + .unwrap_or_else(|poisoned| poisoned.into_inner()) +} + +pub fn set_builtin_browser_host(host: Arc) { + *write_lock(host_slot()) = Some(host); +} + +pub fn builtin_browser_host_available() -> bool { + read_lock(host_slot()).is_some() +} + +fn host() -> BitFunResult> { + read_lock(host_slot()).clone().ok_or_else(|| { + BitFunError::tool( + "BitFun's built-in browser automation host is unavailable in this runtime. This capability requires an active Desktop product surface." + .to_string(), + ) + }) +} + +pub async fn list_builtin_browser_targets() -> BitFunResult> { + host()?.list_targets().await.map_err(|error| { + BitFunError::tool(format!("Built-in browser target discovery failed: {error}")) + }) +} + +pub fn default_builtin_browser_target_id() -> Option { + read_lock(default_target_slot()).clone() +} + +pub fn set_default_builtin_browser_target(target_id: Option) { + *write_lock(default_target_slot()) = target_id; +} + +fn event_sender(target_id: &str) -> broadcast::Sender { + let mut channels = write_lock(event_channels()); + channels + .entry(target_id.to_string()) + .or_insert_with(|| broadcast::channel(BUILTIN_EVENT_CAPACITY).0) + .clone() +} + +/// Feed native WebView load notifications into the same lifecycle stream used +/// by CDP-backed actions. Desktop calls this from its single `on_page_load` +/// adapter; no page-action implementation lives in the frontend. +pub fn publish_builtin_browser_page_load(target_id: &str, event: &str, url: &str) { + let lifecycle_name = match event { + "started" => "init", + "finished" => "load", + _ => return, + }; + let sender = event_sender(target_id); + let _ = sender.send(BrowserAutomationEvent { + method: "Page.lifecycleEvent".to_string(), + params: json!({ + "frameId": target_id, + "name": lifecycle_name, + "url": url, + }), + }); + if event == "finished" { + // Native WebView APIs expose a load-finished boundary rather than + // CDP's finer-grained DOMContentLoaded and network-idle events. + // Publish that boundary under both shared lifecycle names so every + // documented wait condition remains portable and explicitly marks + // the approximation in diagnostic payloads. + for name in ["DOMContentLoaded", "networkIdle"] { + let _ = sender.send(BrowserAutomationEvent { + method: "Page.lifecycleEvent".to_string(), + params: json!({ + "frameId": target_id, + "name": name, + "url": url, + "approximation": "native_load_finished", + }), + }); + } + } +} + +pub async fn connect_builtin_browser( + requested_target_id: Option<&str>, +) -> BitFunResult { + connect_builtin_browser_matching(requested_target_id, None, None).await +} + +/// Attach to a built-in page using the same selection inputs exposed by the +/// external CDP `connect` path. An explicit session id is exact and never +/// falls back to another page; URL/title filters are case-insensitive +/// substrings and must both match when both are present. +pub async fn connect_builtin_browser_matching( + requested_target_id: Option<&str>, + target_url: Option<&str>, + target_title: Option<&str>, +) -> BitFunResult { + let targets = list_builtin_browser_targets().await?; + let target = select_builtin_browser_target( + &targets, + requested_target_id, + target_url, + target_title, + default_builtin_browser_target_id().as_deref(), + )?; + + set_default_builtin_browser_target(Some(target.id.clone())); + Ok(BuiltInBrowserClient { + events: event_sender(&target.id), + target, + }) +} + +fn select_builtin_browser_target( + targets: &[BuiltInBrowserTarget], + requested_target_id: Option<&str>, + target_url: Option<&str>, + target_title: Option<&str>, + default_target_id: Option<&str>, +) -> BitFunResult { + if targets.is_empty() { + return Err(BitFunError::tool( + "No built-in browser target is available. Open a URL with browser.open_builtin first." + .to_string(), + )); + } + + if let Some(requested_id) = requested_target_id { + return targets + .iter() + .find(|target| target.id == requested_id) + .cloned() + .ok_or_else(|| { + BitFunError::tool(format!( + "Built-in browser page '{requested_id}' was not found. It may have been closed." + )) + }); + } + + let normalized_url = target_url.map(str::to_lowercase); + let normalized_title = target_title.map(str::to_lowercase); + if normalized_url.is_some() || normalized_title.is_some() { + return targets + .iter() + .find(|target| { + normalized_url + .as_ref() + .map(|needle| target.url.to_lowercase().contains(needle)) + .unwrap_or(true) + && normalized_title + .as_ref() + .map(|needle| target.title.to_lowercase().contains(needle)) + .unwrap_or(true) + }) + .cloned() + .ok_or_else(|| { + BitFunError::tool(format!( + "No built-in browser page matched target_url={normalized_url:?} target_title={normalized_title:?}" + )) + }); + } + + default_target_id + .and_then(|id| targets.iter().find(|target| target.id == id)) + .or_else(|| targets.iter().find(|target| target.active)) + .or_else(|| targets.first()) + .cloned() + .ok_or_else(|| { + BitFunError::tool( + "No built-in browser target is available. Open a URL with browser.open_builtin first." + .to_string(), + ) + }) +} + +pub struct BuiltInBrowserClient { + target: BuiltInBrowserTarget, + events: broadcast::Sender, +} + +impl BuiltInBrowserClient { + pub fn target(&self) -> &BuiltInBrowserTarget { + &self.target + } +} + +#[async_trait] +impl BrowserAutomationClient for BuiltInBrowserClient { + async fn send(&self, method: &str, params: Option) -> BitFunResult { + host()? + .execute(BuiltInBrowserCommand { + target_id: self.target.id.clone(), + method: method.to_string(), + params, + }) + .await + .map_err(|error| { + BitFunError::tool(format!( + "Built-in browser adapter failed for {method}: {error}" + )) + }) + } + + fn subscribe_events(&self) -> broadcast::Receiver { + self.events.subscribe() + } + + fn is_connected(&self) -> bool { + true + } + + fn capabilities(&self) -> BrowserAutomationCapabilities { + BrowserAutomationCapabilities::embedded_webview() + } + + fn target_kind(&self) -> &'static str { + "builtin" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn page_load_events_use_the_shared_lifecycle_shape() { + let mut receiver = event_sender("embedded-browser-test").subscribe(); + publish_builtin_browser_page_load( + "embedded-browser-test", + "finished", + "https://example.test/", + ); + let event = receiver.try_recv().expect("lifecycle event"); + assert_eq!(event.method, "Page.lifecycleEvent"); + assert_eq!(event.params["name"], "load"); + assert_eq!(event.params["frameId"], "embedded-browser-test"); + let dom_content_loaded = receiver.try_recv().expect("dom-content-loaded event"); + assert_eq!(dom_content_loaded.params["name"], "DOMContentLoaded"); + assert_eq!( + dom_content_loaded.params["approximation"], + "native_load_finished" + ); + let network_idle = receiver.try_recv().expect("network-idle event"); + assert_eq!(network_idle.params["name"], "networkIdle"); + assert_eq!(network_idle.params["approximation"], "native_load_finished"); + } + + #[test] + fn embedded_capabilities_keep_protocol_only_extensions_explicit() { + let capabilities = BrowserAutomationCapabilities::embedded_webview(); + assert!(!capabilities.raw_cdp); + assert!(!capabilities.protocol_diagnostics); + assert!(!capabilities.backend_node_ids); + } + + fn target(id: &str, url: &str, title: &str, active: bool) -> BuiltInBrowserTarget { + BuiltInBrowserTarget { + id: id.to_string(), + url: url.to_string(), + title: title.to_string(), + active, + } + } + + #[test] + fn explicit_target_id_never_silently_falls_back() { + let targets = vec![target( + "embedded-browser-panel-view-1", + "https://example.com/", + "Example", + true, + )]; + let error = select_builtin_browser_target( + &targets, + Some("embedded-browser-panel-view-missing"), + None, + None, + None, + ) + .expect_err("a stale exact id must fail"); + assert!(error.to_string().contains("was not found")); + } + + #[test] + fn url_and_title_filters_match_like_external_connect() { + let targets = vec![ + target( + "embedded-browser-panel-view-docs", + "https://docs.example.com/guide", + "Example Guide", + false, + ), + target( + "embedded-browser-panel-view-mail", + "https://mail.example.com/inbox", + "Inbox", + true, + ), + ]; + let selected = select_builtin_browser_target( + &targets, + None, + Some("DOCS.EXAMPLE"), + Some("guide"), + Some("embedded-browser-panel-view-mail"), + ) + .expect("filters should take precedence over the default target"); + assert_eq!(selected.id, "embedded-browser-panel-view-docs"); + + let error = select_builtin_browser_target( + &targets, + None, + Some("mail.example"), + Some("guide"), + None, + ) + .expect_err("both filters must match one page"); + assert!(error + .to_string() + .contains("No built-in browser page matched")); + } +} diff --git a/src/crates/assembly/core/src/agentic/tools/browser_control/cdp_client.rs b/src/crates/assembly/core/src/agentic/tools/browser_control/cdp_client.rs index 408233289a..9f74198055 100644 --- a/src/crates/assembly/core/src/agentic/tools/browser_control/cdp_client.rs +++ b/src/crates/assembly/core/src/agentic/tools/browser_control/cdp_client.rs @@ -17,6 +17,7 @@ use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream}; use super::browser_launcher::BrowserKind; +use super::{BrowserAutomationCapabilities, BrowserAutomationClient, BrowserAutomationEvent}; type WsSink = SplitSink>, Message>; type WsStream = SplitStream>>; @@ -27,12 +28,8 @@ type SessionStatuses = Arc>>>; const PAGE_CDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(30); const USER_PROFILE_APPROVAL_TIMEOUT: Duration = Duration::from_secs(90); -/// A single CDP event emitted by the browser (no `id`, has `method` + `params`). -#[derive(Debug, Clone)] -pub struct CdpEvent { - pub method: String, - pub params: Value, -} +/// Backward-compatible name for events recorded by CDP-only diagnostics. +pub type CdpEvent = BrowserAutomationEvent; struct CdpTransport { sink: Arc>, @@ -537,6 +534,29 @@ impl CdpClient { } } +#[async_trait::async_trait] +impl BrowserAutomationClient for CdpClient { + async fn send(&self, method: &str, params: Option) -> BitFunResult { + CdpClient::send(self, method, params).await + } + + fn subscribe_events(&self) -> broadcast::Receiver { + CdpClient::subscribe_events(self) + } + + fn is_connected(&self) -> bool { + CdpClient::is_connected(self) + } + + fn capabilities(&self) -> BrowserAutomationCapabilities { + BrowserAutomationCapabilities::cdp() + } + + fn target_kind(&self) -> &'static str { + "external_cdp" + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/crates/assembly/core/src/agentic/tools/browser_control/mod.rs b/src/crates/assembly/core/src/agentic/tools/browser_control/mod.rs index a20745e6a7..3a611ba7d1 100644 --- a/src/crates/assembly/core/src/agentic/tools/browser_control/mod.rs +++ b/src/crates/assembly/core/src/agentic/tools/browser_control/mod.rs @@ -1,18 +1,27 @@ -//! Browser control via Chrome DevTools Protocol (CDP). +//! Browser automation shared by external CDP browsers and BitFun's built-in +//! browser WebViews. //! -//! Connects to a Chromium-family browser over CDP, enabling page navigation, -//! DOM interaction, screenshots, JS evaluation and more. Chrome 144+ and Edge -//! use user-approved live-profile endpoints so existing tabs, cookies, -//! extensions and login sessions are preserved. Other Chromium browsers reuse -//! a real-profile endpoint when available and retain a managed fallback. +//! [`BrowserActions`] owns the product-level action semantics (snapshot refs, +//! click guards, filling, waiting, capture, and so on). Concrete browser hosts +//! implement [`BrowserAutomationClient`], so a second target never grows a +//! second copy of the action implementation. pub mod actions; +pub mod automation_client; pub mod browser_launcher; +pub mod builtin_browser; pub mod cdp_client; pub mod session_registry; pub use actions::BrowserActions; +pub use automation_client::{ + BrowserAutomationCapabilities, BrowserAutomationClient, BrowserAutomationEvent, +}; pub use browser_launcher::BrowserLauncher; +pub use builtin_browser::{ + connect_builtin_browser, connect_builtin_browser_matching, list_builtin_browser_targets, + BuiltInBrowserClient, BuiltInBrowserTarget, +}; pub use cdp_client::CdpClient; pub use session_registry::{ BrowserSession, BrowserSessionRegistry, BrowserSessionState, DialogHandler, diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/bitfun_control_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/bitfun_control_tool.rs new file mode 100644 index 0000000000..1082897285 --- /dev/null +++ b/src/crates/assembly/core/src/agentic/tools/implementations/bitfun_control_tool.rs @@ -0,0 +1,452 @@ +//! BitFunControl — discover and control user-facing BitFun features and settings. + +use crate::agentic::agents::get_agent_registry; +use crate::agentic::tools::bitfun_control_host::{ + bitfun_control_host_available, invoke_bitfun_control, BitFunControlHostRequest, +}; +use crate::agentic::tools::framework::{ + PermissionIntent, Tool, ToolResult, ToolUseContext, ValidationResult, +}; +use crate::util::errors::{BitFunError, BitFunResult}; +use async_trait::async_trait; +use serde_json::{json, Value}; + +const ACTIONS: &[&str] = &["list", "search", "get", "open", "execute", "configure"]; + +pub struct BitFunControlTool; + +impl BitFunControlTool { + pub fn new() -> Self { + Self + } + + fn action(input: &Value) -> Option<&str> { + input.get("action").and_then(Value::as_str).map(str::trim) + } + + fn requires_capability_id(action: &str) -> bool { + matches!(action, "get" | "open" | "execute" | "configure") + } + + fn agent_is_readonly(context: &ToolUseContext) -> bool { + let Some(agent_type) = context.agent_type.as_deref() else { + return false; + }; + get_agent_registry() + .get_agent(agent_type, context.workspace_root()) + .is_some_and(|agent| agent.is_readonly()) + } +} + +impl Default for BitFunControlTool { + fn default() -> Self { + Self::new() + } +} + +#[async_trait] +impl Tool for BitFunControlTool { + fn name(&self) -> &str { + "BitFunControl" + } + + async fn description(&self) -> BitFunResult { + Ok( + "Control BitFun features and settings through its internal API. Use a two-step flow: first call `list` or `search` (then `get` when needed) to discover a user-facing capability, then call `open`, `execute`, or `configure`. The catalog is loaded only on demand and is not embedded in this description." + .to_string(), + ) + } + + fn short_description(&self) -> String { + "Discover and control BitFun features and settings.".to_string() + } + + fn input_schema(&self) -> Value { + json!({ + "type": "object", + "additionalProperties": false, + "required": ["action"], + "properties": { + "action": { + "type": "string", + "enum": ACTIONS, + "description": "Discovery: list/search/get. Control: open/execute/configure. Discover a capability before controlling it." + }, + "query": { + "type": "string", + "description": "Chinese or English query for search." + }, + "capability_id": { + "type": "string", + "description": "Stable capability ID returned by list/search/get." + }, + "item_id": { + "type": "string", + "description": "Optional documented item ID returned by search/get; open uses it to navigate to an exact subview." + }, + "operation_id": { + "type": "string", + "description": "User-level operation ID returned by get; required for execute." + }, + "option_id": { + "type": "string", + "description": "User-level setting option ID returned by get; required for configure." + }, + "value": { + "description": "New option value for configure, following the value schema returned by get." + }, + "cursor": { + "type": "integer", + "minimum": 0, + "description": "Zero-based list/search cursor." + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "description": "Maximum discovery results. Defaults to all 50 slots for list and 20 for search; maximum 50." + } + } + }) + } + + async fn is_available_in_context(&self, _context: Option<&ToolUseContext>) -> bool { + bitfun_control_host_available() + } + + fn is_readonly(&self) -> bool { + false + } + + fn is_concurrency_safe(&self, input: Option<&Value>) -> bool { + input + .and_then(Self::action) + .is_some_and(|action| matches!(action, "list" | "search" | "get")) + } + + fn permission_intents( + &self, + input: &Value, + _context: &ToolUseContext, + ) -> BitFunResult> { + let action = Self::action(input).unwrap_or(""); + if matches!(action, "list" | "search" | "get") { + return Ok(Vec::new()); + } + let capability_id = input + .get("capability_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .unwrap_or(""); + let target = match action { + "execute" => input + .get("operation_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(|value| format!("{capability_id}:{value}")) + .unwrap_or_else(|| capability_id.to_string()), + "configure" => input + .get("option_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(|value| format!("{capability_id}:{value}")) + .unwrap_or_else(|| capability_id.to_string()), + "open" => input + .get("item_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(|value| format!("{capability_id}:{value}")) + .unwrap_or_else(|| capability_id.to_string()), + _ => capability_id.to_string(), + }; + Ok(vec![PermissionIntent::new( + "bitfun_control", + vec![format!("{action}:{target}")], + )]) + } + + async fn validate_input( + &self, + input: &Value, + _context: Option<&ToolUseContext>, + ) -> ValidationResult { + let invalid = |message: &str| ValidationResult { + result: false, + message: Some(message.to_string()), + error_code: None, + meta: None, + }; + if !input.is_object() { + return invalid("Input must be an object."); + } + let Some(action) = Self::action(input) else { + return invalid("action is required."); + }; + if !ACTIONS.contains(&action) { + return invalid( + "action must be one of list, search, get, open, execute, or configure.", + ); + } + if action == "search" + && !input + .get("query") + .and_then(Value::as_str) + .is_some_and(|query| !query.trim().is_empty()) + { + return invalid("query is required for search."); + } + if Self::requires_capability_id(action) + && !input + .get("capability_id") + .and_then(Value::as_str) + .is_some_and(|id| !id.trim().is_empty()) + { + return invalid("capability_id is required for get, open, execute, and configure."); + } + if input.get("item_id").is_some_and(|value| { + !value + .as_str() + .is_some_and(|item_id| !item_id.trim().is_empty()) + }) { + return invalid("item_id must be a non-empty string when provided."); + } + if action == "execute" + && !input + .get("operation_id") + .and_then(Value::as_str) + .is_some_and(|id| !id.trim().is_empty()) + { + return invalid("operation_id is required for execute."); + } + if action == "configure" + && !input + .get("option_id") + .and_then(Value::as_str) + .is_some_and(|id| !id.trim().is_empty()) + { + return invalid("option_id is required for configure."); + } + if action == "configure" && input.get("value").is_none() { + return invalid("value is required for configure."); + } + if input + .get("cursor") + .is_some_and(|value| value.as_u64().is_none()) + { + return invalid("cursor must be a non-negative integer when provided."); + } + if input.get("limit").is_some_and(|value| { + value + .as_u64() + .is_none_or(|limit| !(1..=50).contains(&limit)) + }) { + return invalid("limit must be an integer between 1 and 50."); + } + ValidationResult::default() + } + + async fn call_impl( + &self, + input: &Value, + context: &ToolUseContext, + ) -> BitFunResult> { + if !bitfun_control_host_available() { + return Err(BitFunError::tool( + "BitFunControl is unavailable on this product surface".to_string(), + )); + } + let action = Self::action(input) + .ok_or_else(|| BitFunError::tool("action is required".to_string()))?; + if matches!(action, "open" | "execute" | "configure") && Self::agent_is_readonly(context) { + return Err(BitFunError::tool( + "This read-only agent may discover BitFun features and settings but cannot control them" + .to_string(), + )); + } + + let result = invoke_bitfun_control(BitFunControlHostRequest { + action: action.to_string(), + query: input + .get("query") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string), + capability_id: input + .get("capability_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string), + item_id: input + .get("item_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string), + operation_id: input + .get("operation_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string), + option_id: input + .get("option_id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string), + value: input.get("value").cloned(), + cursor: input + .get("cursor") + .and_then(Value::as_u64) + .and_then(|value| usize::try_from(value).ok()), + limit: input + .get("limit") + .and_then(Value::as_u64) + .and_then(|value| usize::try_from(value).ok()), + }) + .await + .map_err(BitFunError::tool)?; + + let assistant = match action { + "list" | "search" => { + let count = result + .get("items") + .and_then(Value::as_array) + .map(Vec::len) + .unwrap_or_default(); + format!("BitFun feature and setting discovery returned {count} item(s). Use a returned capability ID with get, open, execute, or configure.") + } + "get" => "Loaded the BitFun feature or setting manual, including its user-level operations and configurable options.".to_string(), + "open" => "Opened the BitFun feature or setting in the active product surface.".to_string(), + "execute" => "Executed the selected user-level BitFun operation.".to_string(), + "configure" => "Updated the selected BitFun setting option.".to_string(), + _ => "BitFunControl completed.".to_string(), + }; + Ok(vec![ToolResult::ok(result, Some(assistant))]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + + fn context() -> ToolUseContext { + ToolUseContext { + tool_call_id: None, + agent_type: None, + session_id: None, + dialog_turn_id: None, + workspace: None, + loaded_deferred_tool_specs: Vec::new(), + primary_model_facts: tool_runtime::context::PrimaryModelFacts::default(), + custom_data: HashMap::new(), + computer_use_host: None, + runtime_tool_restrictions: Default::default(), + runtime_handles: bitfun_runtime_ports::ToolRuntimeHandles::default(), + } + } + + #[tokio::test] + async fn description_keeps_the_catalog_out_of_the_prompt() { + let description = BitFunControlTool::new().description().await.unwrap(); + assert!(description.contains("two-step")); + assert!(description.contains("list")); + assert!(description.contains("search")); + assert!(!description.contains("get_configs")); + assert!(description.len() < 600); + } + + #[tokio::test] + async fn validates_the_discover_then_execute_contract() { + let tool = BitFunControlTool::new(); + assert!( + tool.validate_input(&json!({ "action": "list" }), None) + .await + .result + ); + assert!( + !tool + .validate_input(&json!({ "action": "search" }), None) + .await + .result + ); + assert!( + !tool + .validate_input(&json!({ "action": "execute" }), None) + .await + .result + ); + assert!( + tool.validate_input( + &json!({ + "action": "execute", + "capability_id": "feature.ai-assistant", + "operation_id": "new-session" + }), + None, + ) + .await + .result + ); + assert!( + tool.validate_input( + &json!({ + "action": "configure", + "capability_id": "setting.application.general", + "option_id": "auto-update", + "value": false + }), + None, + ) + .await + .result + ); + } + + #[test] + fn discovery_is_permission_free_but_execution_is_scoped() { + let tool = BitFunControlTool::new(); + assert!(tool + .permission_intents(&json!({ "action": "search", "query": "theme" }), &context()) + .unwrap() + .is_empty()); + let intents = tool + .permission_intents( + &json!({ + "action": "configure", + "capability_id": "setting.application.general", + "option_id": "auto-update", + "value": false + }), + &context(), + ) + .unwrap(); + assert_eq!(intents[0].action, "bitfun_control"); + assert_eq!( + intents[0].resources, + vec!["configure:setting.application.general:auto-update"] + ); + + let open_intents = tool + .permission_intents( + &json!({ + "action": "open", + "capability_id": "setting.application.input", + "item_id": "shortcut-browser" + }), + &context(), + ) + .unwrap(); + assert_eq!( + open_intents[0].resources, + vec!["open:setting.application.input:shortcut-browser"] + ); + } +} diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs index 7f3132c58a..382ccbf013 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs @@ -1,7 +1,7 @@ //! ControlHub — unified entry point for browser, terminal, and routing metadata. //! //! Routes requests by `domain` to the appropriate backend: -//! browser → CDP-based browser control (new) +//! browser → target-neutral browser actions over CDP or a built-in WebView //! terminal → TerminalApi (existing) //! meta → capability and route introspection //! @@ -9,9 +9,17 @@ //! dedicated ComputerUse tool/agent, not through public ControlHub domains. use crate::agentic::tools::browser_control::actions::{BrowserActions, MAX_WAIT_MS}; +use crate::agentic::tools::browser_control::automation_client::{ + BrowserAutomationClient, EXTERNAL_CDP_EXTENSIONS, SHARED_BROWSER_ACTIONS, +}; use crate::agentic::tools::browser_control::browser_launcher::{ BrowserKind, BrowserLauncher, LaunchResult, DEFAULT_CDP_PORT, }; +use crate::agentic::tools::browser_control::builtin_browser::{ + builtin_browser_host_available, connect_builtin_browser, connect_builtin_browser_matching, + default_builtin_browser_target_id, list_builtin_browser_targets, + set_default_builtin_browser_target, BuiltInBrowserClient, +}; use crate::agentic::tools::browser_control::cdp_client::{CdpClient, CdpPageInfo, CdpVersionInfo}; use crate::agentic::tools::browser_control::session_registry::{ BrowserSession, BrowserSessionRegistry, BrowserSessionState, DialogHandler, @@ -58,6 +66,49 @@ fn browser_sessions() -> Arc { .clone() } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum BrowserTargetKind { + External, + BuiltIn, +} + +impl BrowserTargetKind { + fn as_str(self) -> &'static str { + match self { + Self::External => "external", + Self::BuiltIn => "builtin", + } + } +} + +enum ResolvedBrowserTarget { + External(BrowserSession), + BuiltIn(BuiltInBrowserClient), +} + +impl ResolvedBrowserTarget { + fn client(&self) -> &dyn BrowserAutomationClient { + match self { + Self::External(session) => session.client.as_ref(), + Self::BuiltIn(client) => client, + } + } + + fn external(&self) -> Option<&BrowserSession> { + match self { + Self::External(session) => Some(session), + Self::BuiltIn(_) => None, + } + } + + fn session_id(&self) -> &str { + match self { + Self::External(session) => &session.session_id, + Self::BuiltIn(client) => &client.target().id, + } + } +} + pub struct ControlHubTool; impl Default for ControlHubTool { @@ -71,6 +122,115 @@ impl ControlHubTool { Self } + fn browser_target_kind(params: &Value) -> Result { + let explicit = params + .get("target") + .or_else(|| params.get("browser_target")) + .and_then(Value::as_str); + match explicit { + Some("builtin" | "built_in" | "embedded" | "bitfun") => Ok(BrowserTargetKind::BuiltIn), + Some("external" | "cdp" | "headless") | None => { + if explicit.is_none() + && params + .get("session_id") + .and_then(Value::as_str) + .map(|id| { + id.starts_with("embedded-browser-view-") + || id.starts_with("embedded-browser-panel-view-") + }) + .unwrap_or(false) + { + Ok(BrowserTargetKind::BuiltIn) + } else { + Ok(BrowserTargetKind::External) + } + } + Some(other) => Err(ControlHubError::new( + ErrorCode::InvalidParams, + format!("Unknown browser target '{other}'. Use 'builtin' or 'external'."), + )), + } + } + + fn builtin_extension_error(action: &str) -> Vec { + err_response( + "browser", + action, + ControlHubError::new( + ErrorCode::NotAvailable, + format!( + "browser.{action} is a CDP protocol extension and is not available for BitFun's built-in WebView target." + ), + ) + .with_hint( + "Portable actions (navigate, snapshot, click, fill, type, scroll, wait, get, screenshot, evaluate, fetch, cookies, and read_article) use the same BrowserActions implementation on both targets.", + ) + .with_hint( + "Use target='external' only when raw CDP, network/console tracing, or native file-input injection is genuinely required.", + ), + ) + } + + fn builtin_target_json( + target: &crate::agentic::tools::browser_control::BuiltInBrowserTarget, + ) -> Value { + json!({ + "id": target.id, + "session_id": target.id, + "title": target.title, + "url": target.url, + "type": "page", + "target": "builtin", + "active": target.active, + "is_default_session": default_builtin_browser_target_id().as_deref() == Some(target.id.as_str()), + }) + } + + fn urls_equivalent(left: &str, right: &str) -> bool { + left.trim_end_matches('/') == right.trim_end_matches('/') + } + + async fn wait_for_opened_builtin_target( + url: &str, + previous_ids: &[String], + ) -> Result { + let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(10); + loop { + match list_builtin_browser_targets().await { + Ok(targets) => { + let selected = targets.iter().find(|target| { + target.active + && (Self::urls_equivalent(&target.url, url) + || !previous_ids.contains(&target.id)) + }); + if let Some(target) = selected { + return connect_builtin_browser(Some(&target.id)) + .await + .map_err(|error| { + ControlHubError::new(ErrorCode::NotAvailable, error.to_string()) + }); + } + } + Err(error) => { + return Err(ControlHubError::new( + ErrorCode::NotAvailable, + error.to_string(), + )); + } + } + if tokio::time::Instant::now() >= deadline { + return Err(ControlHubError::new( + ErrorCode::Timeout, + "The built-in browser surface did not become ready for Agent control after it was opened.", + ) + .with_hint( + "Keep the BitFun Desktop window open and retry browser.open_builtin; CLI/headless runtimes do not provide a built-in browser surface.", + )); + } + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + } + } + fn browser_connect_mode_from_params(params: &Value) -> &'static str { match params.get("mode").and_then(|v| v.as_str()) { Some("headless") => "headless", @@ -256,23 +416,26 @@ Use this tool via `{ domain, action, params }` for browser automation, terminal ## Domains -### domain: "browser" (DOM/CDP browser control) +### domain: "browser" (shared browser automation) +- Target selection: + * `params.target: "builtin" | "external"` selects BitFun's native built-in WebView or an external CDP browser. Existing calls default to `external`; a built-in `session_id` also selects `builtin` automatically. + * Portable actions use one `BrowserActions` implementation on both targets, with the same parameters, @eN refs, results, and errors. The browser engine is the adapter, not a second action stack. - Default URL-opening policy: * For requests that only open, show, preview, or view a URL, use `open_builtin`. This is the default browser-opening action and keeps the page inside BitFun. - * Do not call `connect`, `tab_new`, or `navigate` merely to display a URL. Use the CDP workflow only when the agent must read page content or interact with the DOM. -- UI action: - * `open_builtin { url, title?, replace_existing? }` — open an http(s) URL in BitFun's built-in right-side browser panel. This changes the BitFun UI only; it does not fetch page text for reasoning. The panel is display-only for the user — the agent cannot snapshot, read, or interact with it; use `connect` + `snapshot` when page content is needed. + * `open_builtin { url, title?, replace_existing? }` opens the page and returns its built-in `session_id`; the Agent can immediately snapshot/read/interact with it using `target: "builtin"`. +- Shared workflow: `connect { target, target_url?, target_title? }` -> navigate -> snapshot (returns @e1, @e2 ... refs) -> click/fill with `{ target, selector: "@e1" }`. URL/title matching and exact `session_id` selection work on both targets; take a fresh snapshot after DOM mutations. - Automation modes (external browser): * `connect { mode: "default" }` (default) — on Chrome 144+ and current Edge, request a user-approved connection to the currently running real profile so existing tabs and login state are preserved. Other supported Chromium browsers also reuse the real profile when it publishes DevToolsActivePort; otherwise BitFun starts or attaches its persistent managed profile on port 9222. * `connect { mode: "headless" }` — attach to an already-running headless browser on the headless test port 9223. This mode never starts a browser; when nothing is listening it returns `NOT_AVAILABLE` together with the exact launch command. * `params.port` overrides the CDP port for `connect` and for every other CDP action; after `connect`, actions reuse the connected session's port automatically. +- Target-specific extensions: + * Raw `cdp`, network/console/error tracing, native file-input injection, backend node ids, and true full-page capture require `target: "external"`. They return `NOT_AVAILABLE` on the built-in WebView instead of silently pretending to work. - Actions: open_builtin, connect, tab_new, navigate, back, forward, reload, snapshot, click, hover, fill, type, check, uncheck, select, press_key, scroll, auto_scroll, wait, get, get_text, get_url, get_title, get_html, screenshot, evaluate, fetch, cookies, set_cookies, set_file_input_files, cdp, network, console, errors, trace, dialog, read_article, close, list_pages, tab_query, switch_page, list_sessions. - Pausing: * `wait { duration_ms }` — pause for a fixed time, up to 60 minutes (`ms` and `seconds` are accepted spellings). This is the action to use when you must idle between rounds of work, e.g. `{ "duration_ms": 1800000 }` to resume in 30 minutes. It needs no browser session, and the result reports the `ms` actually waited, so check that figure before assuming the full pause happened. * `wait { condition, timeout_ms? }` — wait on the page instead: 'load' | 'domcontentloaded' | 'networkidle' | a CSS/@ref selector, bounded by `timeout_ms` (default 15s). Requires a connected session. When a `condition` is present it always wins, and any duration you pass becomes its timeout rather than a separate sleep. * A `wait` carrying neither is rejected with `INVALID_PARAMS` — it never silently returns. * `wait` holds the turn open for its whole duration, so it suits a one-off pause, not a schedule. For work that should repeat ("produce another round every 30 minutes") or resume more than an hour out, create a job with the `Cron` tool instead, then **end your turn** — creating the job does not end it for you. The job re-invokes you when it fires, so a turn left running is idling with the context loaded and only delays the next round. Every built-in mode that has ControlHub also has `Cron`; if it is genuinely absent from your tool list, say so rather than substituting a chain of long `wait` calls. -- Automation workflow: connect -> navigate -> snapshot (returns @e1, @e2 ... refs) -> click/fill with `{ "selector": "@e1" }` (the key `ref` is accepted too). - Take a fresh snapshot after any DOM mutation; a stale `@eN` ref returns `error.code = STALE_REF`, while a selector that matches nothing returns `NOT_FOUND`. ### domain: "terminal" @@ -394,6 +557,14 @@ Branch on `ok` and `error.code`, not on English messages. let likely_terminal_available = context.computer_use_host.is_some(); let browser_default = browser_sessions().default_id().await; let browser_session_count = browser_sessions().list().await.len(); + let builtin_host_available = builtin_browser_host_available(); + let builtin_targets = if builtin_host_available { + list_builtin_browser_targets().await.unwrap_or_default() + } else { + Vec::new() + }; + let builtin_target_count = builtin_targets.len(); + let builtin_default = default_builtin_browser_target_id(); let os = std::env::consts::OS; let arch = std::env::consts::ARCH; @@ -436,15 +607,29 @@ Branch on `ok` and `error.code`, not on English messages. "domains": { "browser": { "available": true, - "default_session_id": browser_default, - "session_count": browser_session_count, - "default_browser": browser_kind, - "cdp_supported": browser_cdp_supported, - "ui_surface": { - "built_in_browser_panel": true, - "open_action": "open_builtin", - "event": OPEN_BUILT_IN_BROWSER_EVENT, + "shared_actions": SHARED_BROWSER_ACTIONS, + "targets": { + "builtin": { + "available": builtin_host_available, + "default_session_id": builtin_default, + "session_count": builtin_target_count, + "action_contract": "shared", + "open_action": "open_builtin", + "event": OPEN_BUILT_IN_BROWSER_EVENT, + }, + "external": { + "available": true, + "action_contract": "shared", + "default_session_id": browser_default, + "session_count": browser_session_count, + "default_browser": browser_kind, + "cdp_supported": browser_cdp_supported, + "extensions": EXTERNAL_CDP_EXTENSIONS, + "capture_extensions": ["full_page_screenshot", "backend_node_ids"], + }, }, + "default_target": "external", + "shared_action_contract": true, }, "terminal": { "available": likely_terminal_available, "reason": if likely_terminal_available { Value::Null } else { json!("TerminalApi is only available in contexts that registered it") } }, "meta": { "available": true }, @@ -466,7 +651,7 @@ Branch on `ok` and `error.code`, not on English messages. json!("Computer Use is disabled (ai.computer_use_enabled = false) or no desktop host is present") }, }, - "schema_version": "1.4", + "schema_version": "1.5", }); // The value of a capability probe is entirely in the field // values, so the assistant-visible text must be the payload @@ -549,7 +734,7 @@ Branch on `ok` and `error.code`, not on English messages. "browser", None, 85, - "Matches browser/URL keywords; default to browser.open_builtin for opening or showing URLs, and use browser.connect only when DOM reading or interaction is required", + "Matches browser/URL keywords; default to browser.open_builtin, then use the returned built-in session with target='builtin' for DOM reading or interaction. Choose target='external' only for an external tab or CDP-only diagnostics.", ); break; } @@ -785,6 +970,25 @@ Branch on `ok` and `error.code`, not on English messages. .get("session_id") .and_then(|v| v.as_str()) .map(str::to_string); + let mut browser_target_kind = match Self::browser_target_kind(params) { + Ok(target) => target, + Err(error) => return Ok(err_response("browser", action, error)), + }; + let target_was_explicit = params.get("target").is_some() + || params.get("browser_target").is_some() + || session_id_param.is_some(); + if !target_was_explicit + && action != "connect" + && browser_target_kind == BrowserTargetKind::External + && browser_sessions().default_id().await.is_none() + && default_builtin_browser_target_id().is_some() + { + // `open_builtin` establishes the built-in target as the natural + // follow-up when there is no external default. This keeps the + // common open -> snapshot -> click flow concise without stealing + // an existing external CDP session from backward-compatible calls. + browser_target_kind = BrowserTargetKind::BuiltIn; + } let port = match params.get("port").and_then(|v| v.as_u64()) { Some(p) => p as u16, @@ -827,6 +1031,26 @@ Branch on `ok` and `error.code`, not on English messages. .and_then(Value::as_bool) .unwrap_or(true); + if !builtin_browser_host_available() { + return Ok(err_response( + "browser", + "open_builtin", + ControlHubError::new( + ErrorCode::NotAvailable, + "BitFun's built-in browser requires an active Desktop product surface; it is unavailable in this runtime.", + ) + .with_hint( + "Use target='external' for a CDP browser in CLI/headless runtimes, or open this task in BitFun Desktop.", + ), + )); + } + let previous_ids = list_builtin_browser_targets() + .await + .unwrap_or_default() + .into_iter() + .map(|target| target.id) + .collect::>(); + get_global_event_system() .emit(BackendEvent::Custom { event_name: OPEN_BUILT_IN_BROWSER_EVENT.to_string(), @@ -841,26 +1065,88 @@ Branch on `ok` and `error.code`, not on English messages. BitFunError::tool(format!("failed to open built-in browser: {error}")) })?; + let client = match Self::wait_for_opened_builtin_target(&url, &previous_ids).await { + Ok(client) => client, + Err(error) => return Ok(err_response("browser", "open_builtin", error)), + }; + let target = client.target(); + Ok(vec![ToolResult::ok( json!({ "success": true, "url": url, "title": title, "replace_existing": replace_existing, - "observable_by_agent": false, - "note": "The built-in browser panel is display-only for the user; the agent cannot observe or interact with its content.", + "target": "builtin", + "session_id": target.id, + "page_url": target.url, + "observable_by_agent": true, + "controllable_by_agent": true, + "shared_action_contract": true, + "note": "The built-in browser uses the same BrowserActions contract as an external CDP browser. Pass target='builtin' (and this session_id when needed) to snapshot, click, fill, type, scroll, evaluate, or capture it.", "hints": [ - "Do not call snapshot/get_text/click against this panel — it is not a CDP session.", - "To read page content or interact with the DOM, use browser.connect followed by snapshot, then click/fill via @eN refs.", + "Take a snapshot on target='builtin', then use the returned @eN refs for click/fill just as you would with target='external'.", + "Raw CDP and protocol diagnostics remain external-browser extensions; normal page automation is shared.", ], }), Some(format!( - "Opened {url} in the built-in browser side panel (display-only for the user; not observable by the agent — use browser.connect + snapshot to read or interact with a page)." + "Opened {url} in the built-in browser side panel (session {}; Agent-readable and controllable through the shared browser action contract).", + target.id )), )]) } "connect" => { + if browser_target_kind == BrowserTargetKind::BuiltIn { + let target_url = params.get("target_url").and_then(Value::as_str); + let target_title = params.get("target_title").and_then(Value::as_str); + let targeted = target_url.is_some() || target_title.is_some(); + let client = match connect_builtin_browser_matching( + session_id_param.as_deref(), + target_url, + target_title, + ) + .await + { + Ok(client) => client, + Err(error) => { + let code = if session_id_param.is_some() || targeted { + ErrorCode::WrongTab + } else { + ErrorCode::NotAvailable + }; + return Ok(err_response( + "browser", + "connect", + ControlHubError::new(code, error.to_string()).with_hints([ + "Call browser.list_pages or browser.tab_query with target='builtin' to inspect current built-in pages", + "Open a page with browser.open_builtin first, then connect with target='builtin'", + ]), + )); + } + }; + let _ = BrowserActions::new(&client).enable_observers().await; + let target = client.target(); + return Ok(vec![ToolResult::ok( + json!({ + "success": true, + "target": "builtin", + "browser": "BitFun built-in browser", + "browser_mode": "embedded_webview", + "session_id": target.id, + "page_url": target.url, + "page_title": target.title, + "matched_by_target": targeted, + "activated": target.active, + "status": "attached", + "shared_action_contract": true, + }), + Some(format!( + "Connected to BitFun's built-in browser (session {}, page '{}')", + target.id, target.title + )), + )]); + } let mode = Self::browser_connect_mode_from_params(params); if mode == "headless" && !BrowserLauncher::is_cdp_available(port).await { @@ -1091,6 +1377,7 @@ Branch on `ok` and `error.code`, not on English messages. let mut result = json!({ "success": true, + "target": "external", "browser": connected_browser, "browser_mode": mode, "browser_profile": if uses_user_profile { "current_user" } else { "managed" }, @@ -1170,6 +1457,34 @@ Branch on `ok` and `error.code`, not on English messages. } "list_pages" => { + if browser_target_kind == BrowserTargetKind::BuiltIn { + let targets = match list_builtin_browser_targets().await { + Ok(targets) => targets, + Err(error) => { + return Ok(err_response( + "browser", + "list_pages", + ControlHubError::new(ErrorCode::NotAvailable, error.to_string()), + )); + } + }; + let pages = targets + .iter() + .map(Self::builtin_target_json) + .collect::>(); + return Ok(vec![ToolResult::ok( + json!({ + "target": "builtin", + "pages": pages, + "default_session_id": default_builtin_browser_target_id(), + }), + Some(format!( + "{} built-in browser page(s) found (id | title | url):\n{}", + pages.len(), + page_table(&pages) + )), + )]); + } let pages = Self::browser_pages(port).await?; let default_id = browser_sessions().default_id().await; let summary: Vec = pages @@ -1180,12 +1495,14 @@ Branch on `ok` and `error.code`, not on English messages. "title": p.title, "url": p.url, "type": p.page_type, + "target": "external", "is_default_session": Some(&p.id) == default_id.as_ref(), }) }) .collect(); Ok(vec![ToolResult::ok( json!({ + "target": "external", "pages": summary, "default_session_id": default_id, }), @@ -1221,41 +1538,90 @@ Branch on `ok` and `error.code`, not on English messages. .unwrap_or(20) .max(1); - let pages = Self::browser_pages(port).await?; - let default_id = browser_sessions().default_id().await; + let (pages, default_id) = if browser_target_kind == BrowserTargetKind::BuiltIn { + let targets = match list_builtin_browser_targets().await { + Ok(targets) => targets, + Err(error) => { + return Ok(err_response( + "browser", + "tab_query", + ControlHubError::new(ErrorCode::NotAvailable, error.to_string()), + )); + } + }; + ( + targets + .iter() + .map(Self::builtin_target_json) + .collect::>(), + default_builtin_browser_target_id(), + ) + } else { + ( + Self::browser_pages(port) + .await? + .into_iter() + .map(|page| { + json!({ + "id": page.id, + "title": page.title, + "url": page.url, + "type": page.page_type, + "target": "external", + }) + }) + .collect::>(), + browser_sessions().default_id().await, + ) + }; let total = pages.len(); let filtered: Vec = pages .into_iter() .filter(|p| { - if only_pages && p.page_type.as_deref() != Some("page") { + if only_pages && p.get("type").and_then(Value::as_str) != Some("page") { return false; } if let Some(ref needle) = url_contains { - if !p.url.to_lowercase().contains(needle) { + if !p + .get("url") + .and_then(Value::as_str) + .unwrap_or("") + .to_lowercase() + .contains(needle) + { return false; } } if let Some(ref needle) = title_contains { - if !p.title.to_lowercase().contains(needle) { + if !p + .get("title") + .and_then(Value::as_str) + .unwrap_or("") + .to_lowercase() + .contains(needle) + { return false; } } true }) .take(limit) - .map(|p| { - json!({ - "id": p.id, - "title": p.title, - "url": p.url, - "type": p.page_type, - "is_default_session": Some(&p.id) == default_id.as_ref(), - }) + .map(|mut page| { + if let Some(object) = page.as_object_mut() { + let is_default = object + .get("id") + .and_then(Value::as_str) + .map(|id| Some(id) == default_id.as_deref()) + .unwrap_or(false); + object.insert("is_default_session".to_string(), json!(is_default)); + } + page }) .collect(); let matched = filtered.len(); Ok(vec![ToolResult::ok( json!({ + "target": browser_target_kind.as_str(), "pages": filtered, "matched": matched, "total": total, @@ -1271,6 +1637,65 @@ Branch on `ok` and `error.code`, not on English messages. } "tab_new" => { + if browser_target_kind == BrowserTargetKind::BuiltIn { + let raw_url = params.get("url").and_then(Value::as_str).unwrap_or(""); + let computer_use = Self::computer_use_available(context).await; + let url = match Self::normalize_builtin_browser_url(raw_url, computer_use) { + Ok(url) => url, + Err(error) => return Ok(err_response("browser", "tab_new", error)), + }; + if !builtin_browser_host_available() { + return Ok(err_response( + "browser", + "tab_new", + ControlHubError::new( + ErrorCode::NotAvailable, + "BitFun's built-in browser requires an active Desktop product surface.", + ), + )); + } + let previous_ids = list_builtin_browser_targets() + .await + .unwrap_or_default() + .into_iter() + .map(|target| target.id) + .collect::>(); + get_global_event_system() + .emit(BackendEvent::Custom { + event_name: OPEN_BUILT_IN_BROWSER_EVENT.to_string(), + payload: json!({ + "url": url, + "title": "Browser", + "replaceExisting": false, + }), + }) + .await + .map_err(|error| { + BitFunError::tool(format!( + "failed to open built-in browser tab: {error}" + )) + })?; + let client = + match Self::wait_for_opened_builtin_target(&url, &previous_ids).await { + Ok(client) => client, + Err(error) => return Ok(err_response("browser", "tab_new", error)), + }; + let target = client.target(); + return Ok(vec![ToolResult::ok( + json!({ + "success": true, + "target": "builtin", + "session_id": target.id, + "page_url": target.url, + "page_title": target.title, + "activated": true, + }), + Some(format!( + "New built-in browser page opened: {} (session {})", + target.url, target.id + )), + )]); + } let url = params.get("url").and_then(|v| v.as_str()); let activate = params .get("activate") @@ -1294,6 +1719,7 @@ Branch on `ok` and `error.code`, not on English messages. Ok(vec![ToolResult::ok( json!({ "success": true, + "target": "external", "session_id": session.session_id, "page_url": page.url, "page_title": page.title, @@ -1313,6 +1739,33 @@ Branch on `ok` and `error.code`, not on English messages. .ok_or_else(|| { BitFunError::tool("switch_page requires 'page_id'".to_string()) })?; + if browser_target_kind == BrowserTargetKind::BuiltIn { + let client = match connect_builtin_browser(Some(page_id)).await { + Ok(client) => client, + Err(error) => { + return Ok(err_response( + "browser", + "switch_page", + ControlHubError::new(ErrorCode::NotFound, error.to_string()), + )); + } + }; + set_default_builtin_browser_target(Some(page_id.to_string())); + return Ok(vec![ToolResult::ok( + json!({ + "success": true, + "target": "builtin", + "page_id": page_id, + "session_id": client.target().id, + "activated": client.target().active, + "agent_target_selected": true, + }), + Some(format!( + "Switched Agent browser target to built-in page {}", + page_id + )), + )]); + } // Phase 2: by default ALSO surface the chosen tab in the // user's actual browser window via `Page.bringToFront`. The // legacy behavior only swapped the CDP session under the @@ -1367,6 +1820,7 @@ Branch on `ok` and `error.code`, not on English messages. let mut body = json!({ "success": true, + "target": "external", "page_id": page_id, "session_id": session.session_id, "reused": reused, @@ -1390,6 +1844,39 @@ Branch on `ok` and `error.code`, not on English messages. } "list_sessions" | "network" | "network_requests" | "console" | "errors" | "trace" => { + if browser_target_kind == BrowserTargetKind::BuiltIn { + if action != "list_sessions" { + return Ok(Self::builtin_extension_error(action)); + } + let targets = match list_builtin_browser_targets().await { + Ok(targets) => targets, + Err(error) => { + return Ok(err_response( + "browser", + "list_sessions", + ControlHubError::new(ErrorCode::NotAvailable, error.to_string()), + )); + } + }; + let ids = targets + .iter() + .map(|target| target.id.clone()) + .collect::>(); + let default = default_builtin_browser_target_id(); + return Ok(vec![ToolResult::ok( + json!({ + "target": "builtin", + "sessions": ids, + "default_session_id": default, + }), + Some(format!( + "{} built-in browser session(s) tracked (default={}):\n{}", + ids.len(), + default.as_deref().unwrap_or("-"), + ids.join("\n") + )), + )]); + } match action { "list_sessions" => { let registry = browser_sessions(); @@ -1397,6 +1884,7 @@ Branch on `ok` and `error.code`, not on English messages. let default = registry.default_id().await; Ok(vec![ToolResult::ok( json!({ + "target": "external", "sessions": ids, "default_session_id": default, }), @@ -1573,11 +2061,33 @@ Branch on `ok` and `error.code`, not on English messages. } _ => { - // Resolve a session: explicit `session_id` if present, else - // the registry's default. This replaces the prior "global - // singleton" pattern that was racy across concurrent tasks. - let session = browser_sessions().get(session_id_param.as_deref()).await?; - let actions = BrowserActions::new(session.client.as_ref()); + // Resolve a target adapter, then run every portable operation + // through the one shared BrowserActions implementation. + let target = if browser_target_kind == BrowserTargetKind::BuiltIn { + match connect_builtin_browser(session_id_param.as_deref()).await { + Ok(client) => ResolvedBrowserTarget::BuiltIn(client), + Err(error) => { + let code = if session_id_param.is_some() { + ErrorCode::WrongTab + } else { + ErrorCode::NotAvailable + }; + return Ok(err_response( + "browser", + action, + ControlHubError::new(code, error.to_string()).with_hints([ + "Call browser.list_pages with target='builtin' to inspect current built-in pages", + "Open a page with browser.open_builtin first, then retry with target='builtin'", + ]), + )); + } + } + } else { + ResolvedBrowserTarget::External( + browser_sessions().get(session_id_param.as_deref()).await?, + ) + }; + let actions = BrowserActions::new(target.client()); match action { "navigate" => { @@ -2132,6 +2642,9 @@ Branch on `ok` and `error.code`, not on English messages. )]) } "set_file_input_files" | "file_upload" => { + if !target.client().capabilities().file_input { + return Ok(Self::builtin_extension_error(action)); + } let selector = selector_param(params); let files: Vec = params .get("files") @@ -2146,6 +2659,9 @@ Branch on `ok` and `error.code`, not on English messages. Ok(vec![ToolResult::ok(result, Some("Files set on input".to_string()))]) } "cdp" => { + let Some(session) = target.external() else { + return Ok(Self::builtin_extension_error("cdp")); + }; let method = params .get("method") .and_then(|v| v.as_str()) @@ -2171,6 +2687,9 @@ Branch on `ok` and `error.code`, not on English messages. )]) } "dialog" => { + let Some(session) = target.external() else { + return Ok(Self::builtin_extension_error("dialog")); + }; let response = params .get("response") .and_then(|v| v.as_str()) @@ -2209,9 +2728,20 @@ Branch on `ok` and `error.code`, not on English messages. // resolve elements across same-origin iframes directly. "close" => { let result = actions.close_page().await?; - // After a close, drop the session so subsequent calls - // don't try to talk through a half-dead WebSocket. - browser_sessions().remove(&session.session_id).await; + match &target { + ResolvedBrowserTarget::External(session) => { + // After a close, drop the session so subsequent + // calls don't use a half-dead WebSocket. + browser_sessions().remove(&session.session_id).await; + } + ResolvedBrowserTarget::BuiltIn(_) => { + if default_builtin_browser_target_id().as_deref() + == Some(target.session_id()) + { + set_default_builtin_browser_target(None); + } + } + } Ok(vec![ToolResult::ok(result, Some("Page closed".to_string()))]) } other => Err(BitFunError::tool(format!( @@ -2388,7 +2918,8 @@ impl Tool for ControlHubTool { } fn short_description(&self) -> String { - "Control browser, terminal, and desktop helper domains through one tool.".to_string() + "Control built-in or external browsers and existing terminal sessions through one tool." + .to_string() } fn default_exposure(&self) -> ToolExposure { @@ -2417,7 +2948,7 @@ impl Tool for ControlHubTool { }, "action": { "type": "string", - "description": "The atomic action to perform within the domain. For browser URL-opening or display requests, default to open_builtin; use connect and other CDP actions only for DOM reading or interaction." + "description": "The atomic action to perform within the domain. For browser URL-opening or display requests, default to open_builtin. Browser params.target selects builtin or external; both use the same portable action contract." }, "params": { "type": "object", @@ -2812,8 +3343,29 @@ fn map_dispatch_error(domain: &str, _action: &str, err: BitFunError) -> ControlH #[cfg(test)] mod control_hub_tests { use super::*; + use crate::agentic::tools::browser_control::builtin_browser::{ + set_builtin_browser_host, BuiltInBrowserCommand, BuiltInBrowserHost, BuiltInBrowserTarget, + }; use crate::agentic::tools::implementations::computer_use_actions::ComputerUseActions; + struct FakeBuiltInBrowserHost; + + #[async_trait] + impl BuiltInBrowserHost for FakeBuiltInBrowserHost { + async fn list_targets(&self) -> Result, String> { + Ok(vec![BuiltInBrowserTarget { + id: "embedded-browser-panel-view-test".to_string(), + url: "https://example.com".to_string(), + title: "Example".to_string(), + active: true, + }]) + } + + async fn execute(&self, _command: BuiltInBrowserCommand) -> Result { + Ok(json!({})) + } + } + fn empty_context() -> ToolUseContext { ToolUseContext { tool_call_id: None, @@ -3308,7 +3860,8 @@ mod control_hub_tests { } #[tokio::test] - async fn browser_open_builtin_marks_panel_not_observable_by_agent() { + async fn browser_open_builtin_returns_agent_controllable_shared_target() { + set_builtin_browser_host(Arc::new(FakeBuiltInBrowserHost)); let tool = ControlHubTool::new(); let ctx = empty_context(); let results = tool @@ -3319,24 +3872,69 @@ mod control_hub_tests { &ctx, ) .await - .expect("open_builtin succeeds without a frontend emitter"); + .expect("open_builtin succeeds with a desktop host"); let payload = results.first().expect("one result").content(); assert_eq!( payload.get("observable_by_agent").and_then(|v| v.as_bool()), - Some(false), - "open_builtin must state the panel is not agent-observable: {payload}" + Some(true), + "open_builtin must expose the panel to the Agent: {payload}" ); - let text = payload.to_string(); - assert!( - text.contains("display-only"), - "payload must say the panel is display-only: {text}" + assert_eq!( + payload + .get("controllable_by_agent") + .and_then(|v| v.as_bool()), + Some(true), + "open_builtin must make the panel controllable: {payload}" ); assert!( - text.contains("browser.connect"), - "payload must route content reading to browser.connect + snapshot: {text}" + payload + .to_string() + .contains("shared browser action contract") + || payload.to_string().contains("shared_action_contract"), + "payload must identify the shared action contract: {payload}" ); } + #[tokio::test] + async fn builtin_connect_supports_shared_target_filters_and_rejects_stale_ids() { + set_builtin_browser_host(Arc::new(FakeBuiltInBrowserHost)); + let tool = ControlHubTool::new(); + let ctx = empty_context(); + + let matched = tool + .dispatch( + "browser", + "connect", + &json!({ + "target": "builtin", + "target_url": "EXAMPLE.COM", + "target_title": "example", + }), + &ctx, + ) + .await + .expect("matching built-in target should connect"); + let payload = matched.first().expect("one result").content(); + assert_eq!(payload["matched_by_target"], true); + assert_eq!(payload["session_id"], "embedded-browser-panel-view-test"); + + let missing = tool + .dispatch( + "browser", + "connect", + &json!({ + "target": "builtin", + "session_id": "embedded-browser-panel-view-missing", + }), + &ctx, + ) + .await + .expect("stale id should be reported in-band"); + let error = missing.first().expect("one result").content(); + assert_eq!(error["ok"], false); + assert_eq!(error["error"]["code"], "WRONG_TAB"); + } + #[tokio::test] async fn description_points_desktop_and_system_work_to_computer_use() { let desc = ControlHubTool::new().description().await.unwrap(); @@ -3373,8 +3971,9 @@ mod control_hub_tests { assert!( desc.contains("Default URL-opening policy") && desc.contains("use `open_builtin`") - && desc.contains("Do not call `connect`"), - "description must default display-only URL requests to the built-in browser" + && desc.contains("target: \"builtin\"") + && desc.contains("one `BrowserActions` implementation"), + "description must default URL requests to the controllable built-in browser and document the shared action layer" ); assert!( desc.contains("mode: \"headless\"") && desc.contains("mode: \"default\""), @@ -3579,11 +4178,11 @@ mod control_hub_tests { .expect("capabilities should succeed"); let payload = results.first().unwrap().content(); - // schema_version must have been bumped since we added new fields. + // schema_version must be bumped whenever capability shapes change. assert_eq!( payload.get("schema_version").and_then(|v| v.as_str()), - Some("1.4"), - "schema_version must be bumped to 1.4: {payload}" + Some("1.5"), + "schema_version must be bumped to 1.5: {payload}" ); // Computer Use availability is reported here because ControlHub stays @@ -3606,16 +4205,20 @@ mod control_hub_tests { "system must not be advertised by ControlHub capabilities: {payload}" ); - // browser.default_browser key must exist (value may be null on hosts - // without any installed browser, but the field must be present so - // the model knows the probe ran). + let browser = &payload["domains"]["browser"]; + assert_eq!(browser["shared_action_contract"], json!(true)); + assert_eq!(browser["shared_actions"], json!(SHARED_BROWSER_ACTIONS)); + assert_eq!(browser["targets"]["builtin"]["action_contract"], "shared"); + assert_eq!(browser["targets"]["external"]["action_contract"], "shared"); assert!( - payload - .get("domains") - .and_then(|d| d.get("browser")) - .and_then(|b| b.get("cdp_supported")) + browser["targets"]["external"] + .get("cdp_supported") .is_some(), - "browser.cdp_supported missing: {payload}" + "external target CDP support probe missing: {payload}" + ); + assert_eq!( + browser["targets"]["external"]["extensions"], + json!(EXTERNAL_CDP_EXTENSIONS) ); } diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/mod.rs b/src/crates/assembly/core/src/agentic/tools/implementations/mod.rs index 23836bafde..24dc483df8 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/mod.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/mod.rs @@ -9,6 +9,7 @@ pub mod analyze_image_tool; pub mod appearance_publish_tool; pub mod ask_user_question_tool; pub mod bash_tool; +pub mod bitfun_control_tool; #[cfg(feature = "tools-canvas")] pub mod canvas_tools; pub mod code_review_tool; @@ -86,6 +87,7 @@ pub use analyze_image_tool::AnalyzeImageTool; pub use appearance_publish_tool::PublishAppearanceTool; pub use ask_user_question_tool::AskUserQuestionTool; pub use bash_tool::BashTool; +pub use bitfun_control_tool::BitFunControlTool; #[cfg(feature = "tools-canvas")] pub use canvas_tools::{CreateCanvasTool, PatchCanvasTool, ReadCanvasTool, UpdateCanvasTool}; pub use code_review_tool::CodeReviewTool; diff --git a/src/crates/assembly/core/src/agentic/tools/mod.rs b/src/crates/assembly/core/src/agentic/tools/mod.rs index c1035e758c..23575cf91f 100644 --- a/src/crates/assembly/core/src/agentic/tools/mod.rs +++ b/src/crates/assembly/core/src/agentic/tools/mod.rs @@ -1,6 +1,7 @@ //! Tool system - includes Tool interface, tool registry and tool executor pub mod account_login_capability; +pub mod bitfun_control_host; #[cfg(feature = "browser-control")] pub mod browser_control; pub mod computer_use_capability; diff --git a/src/crates/assembly/core/src/agentic/tools/product_runtime/materialization.rs b/src/crates/assembly/core/src/agentic/tools/product_runtime/materialization.rs index 49bca25193..91cc5f705a 100644 --- a/src/crates/assembly/core/src/agentic/tools/product_runtime/materialization.rs +++ b/src/crates/assembly/core/src/agentic/tools/product_runtime/materialization.rs @@ -49,6 +49,7 @@ impl StaticToolProviderFactory for ProductConcreteToolFactory { "ExecControl" => Some(Arc::new(ExecControlTool::new())), "GetTime" => Some(Arc::new(GetTimeTool::new())), "ListModels" => Some(Arc::new(ListModelsTool::new())), + "BitFunControl" => Some(Arc::new(BitFunControlTool::new())), "Task" => Some(Arc::new(TaskTool::new())), "AgentSpawn" => Some(Arc::new(AgentSpawnTool::new())), "AgentSendInput" => Some(Arc::new(AgentSendInputTool::new())), diff --git a/src/crates/assembly/core/src/agentic/tools/registry.rs b/src/crates/assembly/core/src/agentic/tools/registry.rs index ec649c4d80..17cc224620 100644 --- a/src/crates/assembly/core/src/agentic/tools/registry.rs +++ b/src/crates/assembly/core/src/agentic/tools/registry.rs @@ -587,6 +587,7 @@ mod tests { "submit_code_review", "GetToolSpec", "CallDeferredTool", + "BitFunControl", "GetFileDiff", "CreateCanvas", "ReadCanvas", diff --git a/src/crates/execution/tool-provider-groups/src/lib.rs b/src/crates/execution/tool-provider-groups/src/lib.rs index dc388eab33..9c3f5bb910 100644 --- a/src/crates/execution/tool-provider-groups/src/lib.rs +++ b/src/crates/execution/tool-provider-groups/src/lib.rs @@ -105,7 +105,7 @@ pub fn tool_feature_group(tool_name: &str) -> Option { | "AgentDelete" | "AgentWait" | "LaunchReviewAgent" | "Skill" | "AskUserQuestion" | "TodoWrite" | "get_goal" | "create_goal" | "update_goal" | "CreatePlan" | "submit_code_review" | "GetToolSpec" | "CallDeferredTool" | "SessionControl" - | "SessionMessage" | "SessionHistory" | "Cron" | "PortForward" => { + | "SessionMessage" | "SessionHistory" | "Cron" | "PortForward" | "BitFunControl" => { Some(ToolPackFeatureGroup::AgentControl) } _ => None, @@ -205,6 +205,7 @@ const PRODUCT_TOOL_PROVIDER_GROUP_PLAN: &[ToolProviderGroupPlan] = &[ "submit_code_review", "GetToolSpec", "CallDeferredTool", + "BitFunControl", "GetFileDiff", ], }, @@ -505,6 +506,7 @@ mod tests { "submit_code_review", "GetToolSpec", "CallDeferredTool", + "BitFunControl", "GetFileDiff", "CreateCanvas", "ReadCanvas", diff --git a/src/shared/interactive-capabilities/catalog.json b/src/shared/interactive-capabilities/catalog.json new file mode 100644 index 0000000000..7a8faf82c7 --- /dev/null +++ b/src/shared/interactive-capabilities/catalog.json @@ -0,0 +1,1592 @@ +{ + "schemaVersion": 3, + "product": "BitFun", + "title": "BitFun Playbook", + "origin": "https://playbook.openbitfun.com", + "categories": { + "assistant": { + "titleZh": "AI 与协作", + "titleEn": "AI & collaboration", + "descriptionZh": "会话、Agent、记忆与智能协作。", + "descriptionEn": "Sessions, agents, memory, and AI collaboration." + }, + "workspace": { + "titleZh": "项目与开发", + "titleEn": "Projects & development", + "descriptionZh": "项目、文件、终端、Git、浏览器与开发工具。", + "descriptionEn": "Projects, files, terminal, Git, browser, and development tools." + }, + "automation": { + "titleZh": "扩展与自动化", + "titleEn": "Extensions & automation", + "descriptionZh": "Skills、Mini Apps、任务、Hooks 与生态兼容。", + "descriptionEn": "Skills, Mini Apps, tasks, hooks, and ecosystem compatibility." + }, + "connect": { + "titleZh": "连接与发布", + "titleEn": "Connect & publish", + "descriptionZh": "远程工作、多设备控制、派发与页面发布。", + "descriptionEn": "Remote work, multi-device control, dispatch, and publishing." + }, + "application": { + "titleZh": "应用设置", + "titleEn": "Application settings", + "descriptionZh": "外观、输入、开发环境与应用行为。", + "descriptionEn": "Appearance, input, development environment, and app behavior." + }, + "data": { + "titleZh": "数据与诊断", + "titleEn": "Data & diagnostics", + "descriptionZh": "用量、归档、日志与问题诊断。", + "descriptionEn": "Usage, archives, logs, and troubleshooting." + } + }, + "reviewedInteractionContract": { + "roots": ["src/web-ui/src"], + "digest": "644f35d8f903d81ae15754aca9ac5c0ff23d26b6da878cbc1c5cfd2c480d90d0" + }, + "reviewedDocumentedItemCount": 297, + "capabilities": [ + { + "id": "feature.ai-assistant", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "AI 助手与会话", + "titleEn": "AI assistant & sessions", + "summaryZh": "在项目上下文中与 AI 协作,创建会话、继续任务、处理权限请求,并保留完整的工作记录。", + "summaryEn": "Work with AI in project context, create sessions, continue tasks, answer permission requests, and keep a durable work record.", + "keywordsZh": ["对话", "聊天", "会话", "新建会话", "继续任务", "权限", "目标"], + "keywordsEn": ["chat", "conversation", "session", "new session", "continue task", "permission", "goal"], + "highlightsZh": ["创建、归档、恢复和分叉会话", "暂停、继续或引导正在运行的任务", "查看工具调用、权限请求和用量"], + "highlightsEn": ["Create, archive, restore, and fork sessions", "Pause, continue, or steer running work", "Inspect tool calls, permission requests, and usage"], + "items": [ + { "id": "session-lifecycle", "titleZh": "新建、重命名、归档、恢复、删除、分叉与导出会话", "titleEn": "Create, rename, archive, restore, delete, fork, and export sessions", "evidence": ["command:create_session", "command:update_session_title", "command:archive_session", "command:restore_session", "command:delete_session", "command:fork_session", "command:export_session_transcript"] }, + { "id": "model-mode-permissions", "titleZh": "为会话选择模型、工作模式、记忆模式与权限模式", "titleEn": "Choose the model, work mode, memory mode, and permission mode per session", "evidence": ["command:update_session_model", "command:update_session_mode", "command:set_session_memory_mode", "command:update_session_permission_mode"] }, + { "id": "turn-control", "titleZh": "开始、引导、打断、取消或恢复一次 Agent 运行", "titleEn": "Start, steer, interrupt, cancel, or recover an agent turn", "evidence": ["command:start_dialog_turn", "command:steer_dialog_turn", "command:interrupt_dialog_turn", "command:cancel_dialog_turn", "command:recover_interrupted_dialog_turn"] }, + { "id": "permission-mailbox", "titleZh": "查看并逐个或批量回答等待中的权限请求", "titleEn": "Review and answer pending permission requests individually or in a batch", "evidence": ["command:list_pending_permission_requests", "command:respond_permission", "command:respond_permission_batch", "command:subscribe_permission_requests"] }, + { "id": "history-search", "titleZh": "分页加载、搜索和回填历史消息与会话内容", "titleEn": "Page through, search, and backfill historical turns and session content", "evidence": ["command:load_session_turn_window", "command:search_session_content", "command:load_session_event_backfill", "command:list_persisted_sessions_page"] }, + { "id": "tool-activity", "titleZh": "查看工具调用与后台命令,读取输出并继续输入或停止", "titleEn": "Inspect tool calls and background commands, read output, send input, or stop them", "evidence": ["command:get_all_tools_info", "command:list_background_command_activities", "command:read_background_command_output", "command:send_background_command_input", "command:control_background_command"] }, + { "id": "goals", "titleZh": "创建会话目标、更新目标内容与状态并清除目标", "titleEn": "Create session goals, update their objective and status, and clear them", "evidence": ["command:activate_session_goal", "command:update_session_thread_goal_objective", "command:set_session_thread_goal_status", "command:clear_session_thread_goal"] }, + { "id": "usage", "titleZh": "查看单个会话的请求、Token 与成本用量报告", "titleEn": "View request, token, and cost usage for an individual session", "evidence": ["command:get_session_usage_report"] }, + { "id": "context-memory", "titleZh": "重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆", "titleEn": "Reload session context, initialize AGENTS.md, and manage long-term memory", "evidence": ["command:reload_session_context", "command:run_init_agents_md", "command:get_memory_paths", "command:reset_memory"] }, + { "id": "btw-editor-ai", "titleZh": "使用 BTW 轻量问答与编辑器内联 AI,并可随时取消", "titleEn": "Use lightweight BTW questions and inline editor AI, with cancellation", "evidence": ["command:btw_ask_stream", "command:btw_cancel", "command:editor_ai_stream", "command:editor_ai_cancel"] } + ], + "stepsZh": ["打开 AI 助手或新建会话", "选择项目、模型和工作模式", "描述目标;BitFun 会在会话中持续记录进度"], + "stepsEn": ["Open the AI assistant or create a session", "Choose a project, model, and working mode", "Describe the goal; BitFun keeps progress in the session"], + "agentExamplesZh": ["新建一个会话,我们来排查这个构建错误", "打开 AI 助手,我想继续刚才的任务"], + "agentExamplesEn": ["Start a new session so we can debug this build error", "Open the AI assistant; I want to continue my previous task"], + "destination": { "kind": "scene", "sceneId": "session" }, + "operations": [ + { + "id": "new-session", + "titleZh": "新建会话", + "titleEn": "Create a session", + "descriptionZh": "打开一个新的 AI 会话。", + "descriptionEn": "Open a new AI session.", + "risk": "ui", + "inputSchema": { "type": "object", "additionalProperties": false }, + "handler": { "kind": "productAction", "actionId": "session.new" } + } + ] + }, + { + "id": "feature.agents", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "Agent 管理", + "titleEn": "Agents", + "summaryZh": "管理内置、自定义和子 Agent,让不同角色分工处理研究、编码、评审等任务。", + "summaryEn": "Manage built-in, custom, and subagents so specialized roles can handle research, coding, review, and more.", + "keywordsZh": ["智能体", "子 Agent", "自定义 Agent", "多 Agent", "并行协作"], + "keywordsEn": ["agent", "subagent", "custom agent", "multi-agent", "parallel collaboration"], + "highlightsZh": ["查看可用 Agent", "创建和编辑自定义 Agent", "让主 Agent 委派并行任务"], + "highlightsEn": ["Browse available agents", "Create and edit custom agents", "Let the primary agent delegate parallel work"], + "items": [ + { "id": "browse-agents", "titleZh": "查看内置、用户、项目与当前环境可见的 Agent", "titleEn": "Browse built-in, user, project, and currently visible agents", "evidence": ["command:list_visible_subagents", "command:list_subagents", "command:list_manageable_subagents"] }, + { "id": "custom-agent-create", "titleZh": "创建自定义 Agent 并设置名称、说明和角色", "titleEn": "Create custom agents with a name, description, and role", "evidence": ["command:create_custom_agent"] }, + { "id": "custom-agent-manage", "titleZh": "读取、编辑、重新加载或删除自定义 Agent", "titleEn": "Inspect, edit, reload, or delete custom agents", "evidence": ["command:get_custom_agent_detail", "command:update_custom_agent", "command:reload_custom_agents", "command:delete_custom_agent"] }, + { "id": "subagent-manage", "titleZh": "创建、配置、查看和删除可委派的子 Agent", "titleEn": "Create, configure, inspect, and delete delegatable subagents", "evidence": ["command:create_subagent", "command:update_subagent", "command:update_subagent_config", "command:get_subagent_detail", "command:delete_subagent"] }, + { "id": "capability-summary", "titleZh": "查看每个 Agent 的工具、Skills、只读状态和能力摘要", "titleEn": "Inspect each agent's tools, Skills, read-only state, and capability summary", "evidence": ["source:src/web-ui/src/app/scenes/agents/components/AgentCapabilityTooltip.tsx#AgentCapabilityTooltip"] }, + { "id": "tools-skills", "titleZh": "按 Agent 选择工具组、单个工具、Skill 组与 Skills", "titleEn": "Choose tool groups, individual tools, skill groups, and Skills per agent", "evidence": ["command:list_agent_tool_names", "source:src/web-ui/src/app/scenes/agents/components/ToolGroupPicker.tsx#ToolGroupPicker", "source:src/web-ui/src/app/scenes/agents/components/SkillGroupPicker.tsx#SkillGroupPicker"] }, + { "id": "delegation", "titleZh": "让主 Agent 委派并行研究、编码和评审任务并设置超时", "titleEn": "Let the primary agent delegate parallel research, coding, and review work with timeouts", "evidence": ["command:set_subagent_timeout"] } + ], + "stepsZh": ["打开 Agents", "选择现有 Agent 或创建一个角色", "在会话中指定角色,或让主 Agent 自动委派"], + "stepsEn": ["Open Agents", "Choose an existing agent or create a role", "Select the role in a session or let the primary agent delegate"], + "agentExamplesZh": ["打开 Agents,我想看看有哪些专门角色", "帮我进入 Agent 管理页"], + "agentExamplesEn": ["Open Agents so I can see the specialized roles", "Take me to agent management"], + "destination": { "kind": "action", "actionId": "surface.agents.open" }, + "operations": [] + }, + { + "id": "feature.personal-assistants", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "个人助理", + "titleEn": "Personal assistants", + "summaryZh": "在助理空间中创建和管理自己的长期 AI 助理,定义身份与人设、配置默认能力,并从同一处开始会话或安排定时任务。", + "summaryEn": "Create and manage persistent AI assistants, define their identity and persona, configure default capabilities, and start chats or scheduled work from one place.", + "keywordsZh": ["助理", "个人助理", "育苗场", "主助理", "身份", "头像", "人设", "Persona", "默认工具", "默认技能"], + "keywordsEn": ["assistant", "personal assistant", "nursery", "primary assistant", "identity", "avatar", "persona", "default tools", "default skills"], + "highlightsZh": ["创建、设为主助理或删除助理", "编辑身份、头像与 Persona 文档", "配置默认 Skills、内置工具和 MCP 工具"], + "highlightsEn": ["Create, select a primary assistant, or delete assistants", "Edit identity, avatar, and persona documents", "Configure default Skills, built-in tools, and MCP tools"], + "items": [ + { "id": "assistant-gallery", "titleZh": "浏览已有助理、创建新助理并查看每个助理的身份与能力概览", "titleEn": "Browse existing assistants, create a new one, and review each assistant's identity and capability summary", "evidence": ["command:create_assistant_workspace", "source:src/web-ui/src/app/scenes/profile/views/NurseryGallery.tsx#NurseryGallery"] }, + { "id": "primary-delete-reset", "titleZh": "设为主助理、删除非主助理,或将助理工作区重置为默认状态", "titleEn": "Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults", "evidence": ["command:get_primary_assistant_workspace", "command:set_primary_assistant_workspace", "command:delete_assistant_workspace", "command:reset_assistant_workspace"] }, + { "id": "identity-avatar", "titleZh": "编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符", "titleEn": "Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character", "evidence": ["source:src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx#updateIdentityField", "source:src/web-ui/src/app/scenes/profile/views/AssistantAvatarPicker.tsx#ASSISTANT_AVATAR_PRESETS"] }, + { "id": "persona-documents", "titleZh": "读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter", "titleEn": "Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter", "evidence": ["source:src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx#PERSONA_DOC_FILES", "command:read_file_content", "command:write_file_content"] }, + { "id": "default-skills", "titleZh": "为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态", "titleEn": "Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability", "evidence": ["command:get_mode_skill_configs", "command:set_mode_skill_disabled", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#skillRows"] }, + { "id": "default-builtin-tools", "titleZh": "逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态", "titleEn": "Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults", "evidence": ["command:get_all_tools_info", "command:get_agent_profile_config", "command:set_agent_profile_config", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#builtinRows"] }, + { "id": "default-mcp-tools", "titleZh": "按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具", "titleEn": "Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants", "evidence": ["command:get_mcp_servers", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#mcpGroups", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#handleGroupToggleAll"] }, + { "id": "defaults-discovery-reset", "titleZh": "按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值", "titleEn": "Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults", "evidence": ["command:reset_agent_profile_config", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#statusFilter", "source:src/web-ui/src/app/scenes/profile/views/AssistantDefaultsPage.tsx#searchQuery"] }, + { "id": "assistant-sessions", "titleZh": "从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话", "titleEn": "Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page", "evidence": ["source:src/web-ui/src/app/scenes/profile/views/NurseryGallery.tsx#handleNewAssistantSession", "source:src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.tsx#handleSend", "source:src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx#SessionsSection"] }, + { "id": "assistant-schedules", "titleZh": "查看和管理仅属于当前助理工作区的定时会话与自动任务", "titleEn": "Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace", "evidence": ["source:src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx#ScheduledJobsView"] } + ], + "stepsZh": ["打开“助理”", "创建助理或选择现有助理", "编辑身份与人设,配置默认能力,然后开始会话或定时任务"], + "stepsEn": ["Open Assistants", "Create an assistant or choose an existing one", "Edit its identity and persona, configure defaults, then start a chat or scheduled task"], + "agentExamplesZh": ["打开我的个人助理", "带我去育苗场配置助理的默认工具", "我想修改主助理的人设"], + "agentExamplesEn": ["Open my personal assistants", "Take me to the nursery to configure default assistant tools", "I want to edit my primary assistant's persona"], + "destination": { "kind": "scene", "sceneId": "profile" }, + "operations": [] + }, + { + "id": "feature.projects", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "项目与工作区", + "titleEn": "Projects & workspaces", + "summaryZh": "打开本地目录或创建项目,让文件、会话、终端和 Agent 围绕同一工作区协作。", + "summaryEn": "Open a local directory or create a project so files, sessions, terminals, and agents share one workspace.", + "keywordsZh": ["项目", "工作区", "打开文件夹", "新建项目", "切换项目"], + "keywordsEn": ["project", "workspace", "open folder", "new project", "switch project"], + "highlightsZh": ["打开现有目录", "创建新项目", "在多个工作区间切换"], + "highlightsEn": ["Open an existing directory", "Create a new project", "Switch between workspaces"], + "items": [ + { "id": "open-close-switch", "titleZh": "打开、关闭、切换并重新排序多个工作区", "titleEn": "Open, close, switch, and reorder multiple workspaces", "evidence": ["command:open_workspace", "command:close_workspace", "command:set_active_workspace", "command:reorder_opened_workspaces"] }, + { "id": "recent-workspaces", "titleZh": "查看、清理和重新打开最近使用的项目", "titleEn": "Review, clean up, and reopen recently used projects", "evidence": ["command:get_recent_workspaces", "command:remove_recent_workspace", "command:cleanup_invalid_workspaces"] }, + { "id": "workspace-metadata", "titleZh": "扫描并维护工作区名称、信息、关联目录和 Persona 文件", "titleEn": "Scan and maintain workspace names, metadata, related directories, and persona files", "evidence": ["command:scan_workspace_info", "command:update_workspace_info", "command:reset_workspace_persona_files"] }, + { "id": "file-watch", "titleZh": "监听项目文件变化并查看当前监听路径", "titleEn": "Watch project file changes and inspect active watched paths", "evidence": ["command:start_file_watch", "command:stop_file_watch", "command:get_watched_paths"] }, + { "id": "workspace-search", "titleZh": "按文件名、路径或文件内容搜索本地工作区", "titleEn": "Search local workspaces by filename, path, or file content", "evidence": ["command:search_files", "command:search_filenames", "command:search_file_contents"] }, + { "id": "remote-open", "titleZh": "从项目流程打开 SSH 或其他远程工作区", "titleEn": "Open SSH and other remote workspaces from the project flow", "evidence": ["command:open_remote_workspace"] }, + { "id": "project-health", "titleZh": "查看当前工作区、应用状态、健康状态与统计信息", "titleEn": "Inspect the current workspace, app state, health, and statistics", "evidence": ["command:get_current_workspace", "command:get_app_state", "command:get_health_status", "command:get_statistics"] } + ], + "stepsZh": ["选择“打开项目”或“新建项目”", "选择本地目录或配置远程位置", "从侧边栏进入项目文件与会话"], + "stepsEn": ["Choose Open Project or New Project", "Select a local directory or configure a remote location", "Use the sidebar to access files and sessions"], + "agentExamplesZh": ["帮我打开一个项目", "打开新建项目的界面"], + "agentExamplesEn": ["Help me open a project", "Open the new-project flow"], + "destination": { "kind": "action", "actionId": "project.open" }, + "operations": [ + { + "id": "open-project", + "titleZh": "打开项目", + "titleEn": "Open project", + "descriptionZh": "选择并打开一个已有目录。", + "descriptionEn": "Choose and open an existing directory.", + "risk": "ui", + "inputSchema": { "type": "object", "additionalProperties": false }, + "handler": { "kind": "productAction", "actionId": "project.open" } + }, + { + "id": "new-project", + "titleZh": "新建项目", + "titleEn": "Create project", + "descriptionZh": "打开新建项目流程。", + "descriptionEn": "Open the new-project flow.", + "risk": "ui", + "inputSchema": { "type": "object", "additionalProperties": false }, + "handler": { "kind": "productAction", "actionId": "project.new" } + } + ] + }, + { + "id": "feature.files-editor", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "文件与代码编辑", + "titleEn": "Files & code editing", + "summaryZh": "浏览、搜索和编辑项目文件,查看差异、代码符号、诊断与 Agent 产生的改动。", + "summaryEn": "Browse, search, and edit project files while inspecting diffs, symbols, diagnostics, and agent changes.", + "keywordsZh": ["文件", "代码", "编辑器", "搜索文件", "差异", "诊断", "LSP"], + "keywordsEn": ["files", "code", "editor", "file search", "diff", "diagnostics", "LSP"], + "highlightsZh": ["文件树与全文搜索", "代码导航、格式化和诊断", "查看、接受或撤销 Agent 改动"], + "highlightsEn": ["File tree and full-text search", "Code navigation, formatting, and diagnostics", "Review, accept, or revert agent changes"], + "items": [ + { "id": "file-tree", "titleZh": "浏览文件树并创建、重命名、删除或在系统中显示文件和目录", "titleEn": "Browse the file tree and create, rename, delete, or reveal files and directories", "evidence": ["command:explorer_get_file_tree", "command:create_file", "command:create_directory", "command:rename_file", "command:delete_file", "command:delete_directory", "command:reveal_in_explorer"] }, + { "id": "indexed-search", "titleZh": "建立或重建索引,按文件名和全文内容流式搜索", "titleEn": "Build or rebuild an index and stream filename and full-text search results", "evidence": ["command:search_build_index", "command:search_rebuild_index", "command:start_search_filenames_stream", "command:start_search_file_contents_stream"] }, + { "id": "edit-save", "titleZh": "读取、编辑、保存文件并同步编辑器状态", "titleEn": "Read, edit, and save files while synchronizing editor state", "evidence": ["command:read_file_content", "command:write_file_content", "command:get_file_editor_sync_hash"] }, + { "id": "diffs", "titleZh": "查看修改文件、会话、轮次和单次操作的差异与统计", "titleEn": "Inspect diffs and statistics by file, session, turn, or operation", "evidence": ["command:get_all_modified_files", "command:get_file_diff", "command:get_session_file_diff_stats", "command:get_turn_files", "command:get_operation_diff"] }, + { "id": "accept-reject", "titleZh": "按文件、操作或整个会话接受或拒绝 Agent 改动", "titleEn": "Accept or reject agent changes by file, operation, or whole session", "evidence": ["command:accept_file", "command:reject_file", "command:accept_operation", "command:reject_operation", "command:accept_session"] }, + { "id": "snapshots-rollback", "titleZh": "查看文件变更历史和快照,并回滚整个会话或指定轮次", "titleEn": "Review file history and snapshots, then roll back a session or selected turn", "evidence": ["command:get_file_change_history", "command:get_snapshot_sessions", "command:rollback_session", "command:rollback_session_to_turn"] }, + { "id": "lsp-navigation", "titleZh": "使用 Hover、跳转定义、查找引用、文档符号与高亮", "titleEn": "Use hover, go to definition, references, document symbols, and highlights", "evidence": ["command:lsp_get_hover_workspace", "command:lsp_goto_definition_workspace", "command:lsp_find_references_workspace", "command:lsp_get_document_symbols_workspace", "command:lsp_get_document_highlight_workspace"] }, + { "id": "lsp-editing", "titleZh": "使用补全、格式化、重命名、代码操作、内联提示与语义高亮", "titleEn": "Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting", "evidence": ["command:lsp_get_completions_workspace", "command:lsp_format_document_workspace", "command:lsp_rename_workspace", "command:lsp_get_code_actions_workspace", "command:lsp_get_inlay_hints_workspace", "command:lsp_get_semantic_tokens_workspace"] }, + { "id": "lsp-plugins", "titleZh": "检测项目并安装、启动、停止或卸载 LSP 插件", "titleEn": "Detect projects and install, start, stop, or uninstall LSP plugins", "evidence": ["command:lsp_detect_project", "command:lsp_install_plugin", "command:lsp_prestart_server", "command:lsp_stop_server_workspace", "command:lsp_uninstall_plugin"] }, + { "id": "attachments", "titleZh": "粘贴、拖放或上传文件与图片作为会话上下文", "titleEn": "Paste, drop, or upload files and images as session context", "evidence": ["command:get_clipboard_files", "command:paste_files", "command:upload_image_contexts"] } + ], + "stepsZh": ["先打开一个项目", "打开“文件”", "选择文件进行编辑,或搜索内容与符号"], + "stepsEn": ["Open a project first", "Open Files", "Choose a file to edit, or search content and symbols"], + "agentExamplesZh": ["打开项目文件", "带我去文件和代码编辑器"], + "agentExamplesEn": ["Open the project files", "Take me to the file and code editor"], + "destination": { "kind": "action", "actionId": "surface.files.open" }, + "operations": [] + }, + { + "id": "feature.terminal", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "终端", + "titleEn": "Terminal", + "summaryZh": "在当前项目中运行 Shell、查看输出、保留命令历史,并让 Agent 与同一终端环境协作。", + "summaryEn": "Run a shell in the current project, inspect output, keep command history, and share the same terminal context with agents.", + "keywordsZh": ["终端", "命令行", "Shell", "控制台", "运行命令"], + "keywordsEn": ["terminal", "command line", "shell", "console", "run command"], + "highlightsZh": ["创建多个终端", "选择默认 Shell", "查看运行状态和历史"], + "highlightsEn": ["Create multiple terminals", "Choose the default shell", "Inspect running state and history"], + "items": [ + { "id": "multiple-terminals", "titleZh": "创建、列出、切换和关闭多个终端会话", "titleEn": "Create, list, switch, and close multiple terminal sessions", "evidence": ["command:terminal_create", "command:terminal_list", "command:terminal_get", "command:terminal_close"] }, + { "id": "shells", "titleZh": "检测可用 Shell,并为终端选择默认或指定 Shell", "titleEn": "Detect available shells and choose a default or explicit shell", "evidence": ["command:terminal_get_shells", "source:src/web-ui/src/locales/zh-CN/settings/application.json#terminal.controls.autoDetect"] }, + { "id": "working-directory", "titleZh": "在当前项目目录或指定起始目录创建终端", "titleEn": "Create terminals in the current project or a chosen starting directory", "evidence": ["command:terminal_create"] }, + { "id": "command-control", "titleZh": "执行命令、写入输入并发送中断或其他信号", "titleEn": "Execute commands, write input, and send interrupt or other signals", "evidence": ["command:terminal_execute", "command:terminal_write", "command:terminal_send_command", "command:terminal_signal"] }, + { "id": "resize", "titleZh": "随终端面板大小变化同步行列尺寸", "titleEn": "Synchronize terminal rows and columns as the panel resizes", "evidence": ["command:terminal_resize"] }, + { "id": "history-integration", "titleZh": "查看命令历史并检测 Shell Integration 支持", "titleEn": "Review command history and detect shell-integration support", "evidence": ["command:terminal_get_history", "command:terminal_has_shell_integration"] }, + { "id": "shutdown", "titleZh": "确认输出接收并安全关闭单个或全部终端", "titleEn": "Acknowledge output and safely shut down one or all terminals", "evidence": ["command:terminal_ack", "command:terminal_close", "command:terminal_shutdown_all"] } + ], + "stepsZh": ["打开终端", "确认当前目录", "输入命令;需要时新建额外终端"], + "stepsEn": ["Open Terminal", "Confirm the current directory", "Enter a command and create extra terminals as needed"], + "agentExamplesZh": ["打开一个终端", "切到终端界面"], + "agentExamplesEn": ["Open a terminal", "Switch to the terminal"], + "destination": { "kind": "action", "actionId": "surface.terminal.open" }, + "operations": [ + { + "id": "new-terminal", + "titleZh": "新建终端", + "titleEn": "Create terminal", + "descriptionZh": "在当前工作区创建终端。", + "descriptionEn": "Create a terminal in the current workspace.", + "risk": "ui", + "inputSchema": { "type": "object", "additionalProperties": false }, + "handler": { "kind": "productAction", "actionId": "surface.terminal.open" } + } + ] + }, + { + "id": "feature.git", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "Git 版本控制", + "titleEn": "Git version control", + "summaryZh": "查看改动、分支和提交,完成暂存、提交、合并、Cherry-pick 与 Worktree 工作流。", + "summaryEn": "Inspect changes, branches, and commits; stage, commit, merge, cherry-pick, and work with Git worktrees.", + "keywordsZh": ["Git", "版本控制", "分支", "提交", "暂存", "合并", "Worktree"], + "keywordsEn": ["git", "source control", "branch", "commit", "stage", "merge", "worktree"], + "highlightsZh": ["查看工作区改动", "管理分支与提交", "使用 Worktree 隔离并行任务"], + "highlightsEn": ["Inspect workspace changes", "Manage branches and commits", "Use worktrees to isolate parallel work"], + "items": [ + { "id": "status-diff", "titleZh": "查看仓库状态、修改文件和逐文件 Diff", "titleEn": "Inspect repository status, changed files, and per-file diffs", "evidence": ["command:git_get_status", "command:git_get_changed_files", "command:git_get_diff"] }, + { "id": "stage-reset", "titleZh": "暂存文件、取消暂存并重置到指定提交", "titleEn": "Stage files, unstage changes, and reset to a selected commit", "evidence": ["command:git_add_files", "command:git_reset_files", "command:git_reset_to_commit"] }, + { "id": "commit", "titleZh": "预览或生成提交信息并创建提交", "titleEn": "Preview or generate a commit message and create the commit", "evidence": ["command:preview_commit_message", "command:generate_commit_message", "command:git_commit"] }, + { "id": "sync", "titleZh": "从远端 Pull 并向远端 Push", "titleEn": "Pull from and push to remotes", "evidence": ["command:git_pull", "command:git_push"] }, + { "id": "branches", "titleZh": "查看、创建、切换和删除本地分支", "titleEn": "Browse, create, check out, and delete local branches", "evidence": ["command:git_get_branches", "command:git_create_branch", "command:git_checkout_branch", "command:git_delete_branch"] }, + { "id": "graph-history", "titleZh": "浏览提交图谱与仓库历史并保存最近访问记录", "titleEn": "Browse the commit graph and repository history, including recent-history persistence", "evidence": ["command:git_get_graph", "command:git_get_commits", "command:load_git_repo_history", "command:save_git_repo_history"] }, + { "id": "revision-content", "titleZh": "解析 Revision 并查看任意提交中的文件内容", "titleEn": "Resolve revisions and inspect file content from any commit", "evidence": ["command:git_resolve_revision", "command:git_get_file_content"] }, + { "id": "cherry-pick", "titleZh": "执行、继续或中止 Cherry-pick", "titleEn": "Start, continue, or abort a cherry-pick", "evidence": ["command:git_cherry_pick", "command:git_cherry_pick_continue", "command:git_cherry_pick_abort"] }, + { "id": "trust-worktrees", "titleZh": "管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除", "titleEn": "Manage repository trust and create, bind, promote, recreate, or remove worktrees", "evidence": ["command:git_get_repository_trust", "command:git_trust_repository", "command:worktree_create", "command:worktree_bind_session", "command:worktree_promote", "command:worktree_recreate", "command:worktree_remove"] } + ], + "stepsZh": ["打开 Git", "选择改动或分支", "执行暂存、提交或分支操作"], + "stepsEn": ["Open Git", "Choose changes or a branch", "Stage, commit, or perform a branch operation"], + "agentExamplesZh": ["打开 Git 面板", "带我查看当前代码改动"], + "agentExamplesEn": ["Open the Git panel", "Show me the current code changes"], + "destination": { "kind": "scene", "sceneId": "git" }, + "operations": [] + }, + { + "id": "feature.code-review", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "代码评审与 Pull Request", + "titleEn": "Code review & pull requests", + "summaryZh": "阅读改动与 PR 上下文,查看 CI 日志,生成提交信息,并组织深度代码评审。", + "summaryEn": "Review changes and pull-request context, inspect CI logs, generate commit messages, and run deeper code reviews.", + "keywordsZh": ["代码评审", "PR", "Pull Request", "CI 日志", "提交信息", "Deep Review"], + "keywordsEn": ["code review", "PR", "pull request", "CI log", "commit message", "deep review"], + "highlightsZh": ["查看 PR、Issue 和 CI 上下文", "生成提交信息", "针对改动发起深度评审"], + "highlightsEn": ["Inspect PR, issue, and CI context", "Generate commit messages", "Run deep reviews against changes"], + "items": [ + { "id": "workspace-context", "titleZh": "读取仓库、分支、工作区快照和评审目标", "titleEn": "Load repository, branch, workspace snapshot, and review-target context", "evidence": ["command:review_platform_get_workspace_context", "command:review_platform_get_workspace_snapshot", "command:review_platform_get_pull_request_review_target"] }, + { "id": "pull-request", "titleZh": "查看 Pull Request 详情、分页内容与关联改动", "titleEn": "Inspect pull-request details, paged content, and related changes", "evidence": ["command:review_platform_get_pull_request_detail", "command:review_platform_get_pull_request_detail_page"] }, + { "id": "ci-logs", "titleZh": "读取 Pull Request 的 CI 运行日志", "titleEn": "Read CI run logs for a pull request", "evidence": ["command:review_platform_get_pull_request_ci_log"] }, + { "id": "issues", "titleZh": "读取关联 Issue 的标题、描述与上下文", "titleEn": "Read the title, body, and context of linked issues", "evidence": ["command:review_platform_get_issue"] }, + { "id": "authentication", "titleZh": "保存或清除评审平台访问令牌", "titleEn": "Store or clear review-platform access tokens", "evidence": ["command:review_platform_update_auth_token", "command:review_platform_clear_auth_token"] }, + { "id": "commit-message", "titleZh": "预览、生成或快速采用提交信息", "titleEn": "Preview, generate, or quickly apply a commit message", "evidence": ["command:preview_commit_message", "command:generate_commit_message", "command:quick_commit_message"] }, + { "id": "deep-review", "titleZh": "针对工作区、提交或 PR 发起 Deep Review 并控制评审队列", "titleEn": "Run Deep Review against a workspace, commit, or pull request and control its queue", "evidence": ["command:control_deep_review_queue", "source:src/web-ui/src/flow_chat/deep-review/launch/DeepReviewService.ts#DeepReviewService"] } + ], + "stepsZh": ["打开项目文件或 Git", "选择改动或评审目标", "在会话中请求评审或打开对应详情"], + "stepsEn": ["Open project files or Git", "Choose a change or review target", "Ask for a review in the session or open its details"], + "agentExamplesZh": ["打开文件面板,我要评审当前改动", "带我查看 Pull Request 相关能力"], + "agentExamplesEn": ["Open Files so I can review the current changes", "Take me to the pull-request workflow"], + "destination": { "kind": "action", "actionId": "surface.files.open" }, + "operations": [] + }, + { + "id": "feature.browser", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "内置浏览器", + "titleEn": "Built-in browser", + "summaryZh": "在 BitFun 内打开网页和本地服务;Agent 可直接读取页面、选择元素并点击、填写、滚动或截图。", + "summaryEn": "Open webpages and local services inside BitFun, where an agent can inspect the page and select, click, fill, scroll, or capture elements directly.", + "keywordsZh": ["浏览器", "网页", "URL", "本地预览", "Webview", "Agent 控制浏览器", "网页自动化", "元素选择", "点击网页", "填写表单"], + "keywordsEn": ["browser", "web", "URL", "local preview", "webview", "agent browser control", "web automation", "element selection", "click page", "fill form"], + "highlightsZh": ["打开网页和本地开发地址", "Agent 读取并操作内置网页", "与外部 CDP 浏览器共用动作契约", "在会话旁并排查看页面"], + "highlightsEn": ["Open webpages and local development URLs", "Let an agent inspect and operate the built-in page", "Share one action contract with external CDP browsers", "Keep the page beside a session"], + "items": [ + { "id": "open-urls", "titleZh": "输入完整网址、本地域名或开发服务端口并在 BitFun 内打开", "titleEn": "Open full URLs, local hostnames, or development-service ports inside BitFun", "evidence": ["command:browser_webview_create", "command:browser_webview_navigate"] }, + { "id": "history-navigation", "titleZh": "使用后退、前进和地址栏浏览页面历史", "titleEn": "Navigate page history with Back, Forward, and the address bar", "evidence": ["source:src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts#history.back()", "source:src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts#history.forward()"] }, + { "id": "reload-status", "titleZh": "刷新页面,并同步当前 URL、加载状态与错误提示", "titleEn": "Reload pages and synchronize the current URL, loading state, and errors", "evidence": ["command:browser_webview_reload", "command:browser_get_url", "source:src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts#BROWSER_WEBVIEW_PAGE_LOAD_EVENT"] }, + { "id": "scene-and-panel", "titleZh": "既可作为独立浏览器场景,也可在会话旁的辅助面板中打开", "titleEn": "Use the browser as a standalone scene or an auxiliary panel beside a session", "evidence": ["source:src/web-ui/src/app/scenes/browser/BrowserScene.tsx#BrowserScene", "source:src/web-ui/src/app/scenes/browser/BrowserPanel.tsx#BrowserPanel"] }, + { "id": "element-picker", "titleZh": "启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class", "titleEn": "Start the element picker to highlight hovered elements and show tag, ID, and class details", "evidence": ["source:src/web-ui/src/app/scenes/browser/BrowserPanel.tsx#handleInspector", "source:src/web-ui/src/app/scenes/browser/browserInspectorScript.ts#Adds a semi-transparent blue highlight overlay"] }, + { "id": "element-context", "titleZh": "点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文", "titleEn": "Click an element to capture its CSS path, attributes, text, and HTML into the current session context", "evidence": ["source:src/web-ui/src/app/scenes/browser/browserInspectorScript.ts#On click, captures: tagName, CSS path, attributes, textContent, outerHTML", "source:src/web-ui/src/app/scenes/browser/BrowserPanel.tsx#insert-context-tag"] }, + { "id": "element-picker-cancel", "titleZh": "再次点击选择按钮或按 Esc 取消元素选择并清理高亮", "titleEn": "Click the picker again or press Escape to cancel selection and remove overlays", "evidence": ["source:src/web-ui/src/app/scenes/browser/browserInspectorScript.ts#Pressing Escape cancels inspection", "source:src/web-ui/src/app/scenes/browser/BrowserPanel.tsx#stopInspector"] }, + { "id": "agent-page-automation", "titleZh": "让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图", "titleEn": "Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page", "evidence": ["source:src/crates/assembly/core/src/agentic/tools/browser_control/actions.rs#pub struct BrowserActions", "source:src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs#target: \"builtin\""] }, + { "id": "shared-browser-action-contract", "titleZh": "内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约", "titleEn": "Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers", "evidence": ["source:src/crates/assembly/core/src/agentic/tools/browser_control/automation_client.rs#pub trait BrowserAutomationClient", "source:src/apps/desktop/src/builtin_browser_host.rs#impl BuiltInBrowserHost"] }, + { "id": "browser-target-selection", "titleZh": "通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面", "titleEn": "Choose the built-in or external browser with target and locate a page by session_id, URL, or title", "evidence": ["source:src/crates/assembly/core/src/agentic/tools/implementations/control_hub_tool.rs#fn browser_target_kind"] }, + { "id": "embedded-webview", "titleZh": "桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接", "titleEn": "Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place", "evidence": ["command:browser_webview_set_bounds", "source:src/web-ui/src/app/scenes/browser/BrowserPanel.tsx#sandbox=", "source:src/web-ui/src/app/scenes/browser/browserInspectorScript.ts#BLANK_TARGET_INTERCEPT_SCRIPT"] } + ], + "stepsZh": ["打开浏览器并输入网址或本地端口", "直接告诉 Agent 要在页面上完成什么", "Agent 先读取页面,再用元素引用执行操作"], + "stepsEn": ["Open Browser and enter a URL or local port", "Tell the agent what to accomplish on the page", "The agent inspects the page, then acts through element refs"], + "agentControl": { + "tool": "ControlHub", + "workflowZh": ["用 browser.open_builtin 打开网址并取得内置页面的 session_id", "对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约", "页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external"], + "workflowEn": ["Open the URL with browser.open_builtin and keep the returned built-in session_id", "Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract", "Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection"] + }, + "agentExamplesZh": ["在内置浏览器打开这个网址,然后找到登录按钮", "读取当前内置网页并填写这个表单", "用内置浏览器点开搜索结果并总结页面"], + "agentExamplesEn": ["Open this URL in the built-in browser and find the sign-in button", "Inspect the current built-in page and fill this form", "Use the built-in browser to open the search result and summarize the page"], + "destination": { "kind": "action", "actionId": "surface.browser.open" }, + "operations": [] + }, + { + "id": "feature.computer-use", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "浏览器与桌面控制", + "titleEn": "Browser & desktop control", + "summaryZh": "授权 Agent 操作浏览器或本机界面,并明确管理辅助功能、屏幕录制与浏览器连接。", + "summaryEn": "Allow agents to operate a browser or local UI while explicitly managing accessibility, screen-recording, and browser connection access.", + "keywordsZh": ["Computer Use", "桌面控制", "浏览器控制", "CDP", "辅助功能", "屏幕录制"], + "keywordsEn": ["computer use", "desktop control", "browser control", "CDP", "accessibility", "screen recording"], + "highlightsZh": ["启用或停用 Computer Use", "连接受支持的浏览器", "检查并打开系统权限设置"], + "highlightsEn": ["Enable or disable Computer Use", "Connect a supported browser", "Inspect and open OS permission settings"], + "items": [ + { "id": "status", "titleZh": "检查 Computer Use 可用性、辅助功能和屏幕录制授权状态", "titleEn": "Check Computer Use availability plus accessibility and screen-recording permission status", "evidence": ["command:computer_use_get_status"] }, + { "id": "request-permissions", "titleZh": "请求桌面控制所需的系统权限", "titleEn": "Request the operating-system permissions required for desktop control", "evidence": ["command:computer_use_request_permissions"] }, + { "id": "system-settings", "titleZh": "直接打开对应的系统隐私与安全设置", "titleEn": "Open the matching operating-system privacy and security settings", "evidence": ["command:computer_use_open_system_settings"] }, + { "id": "browser-discovery", "titleZh": "发现受支持的浏览器并查看当前 CDP 连接状态", "titleEn": "Discover supported browsers and inspect the current CDP connection state", "evidence": ["command:browser_control_list_browsers", "command:browser_control_get_status"] }, + { "id": "launch-connect", "titleZh": "启动浏览器控制或连接已经开放 CDP 的浏览器", "titleEn": "Launch browser control or connect to a browser that already exposes CDP", "evidence": ["command:browser_control_launch"] }, + { "id": "default-cdp", "titleZh": "启用默认 CDP 配置并按需要重启浏览器", "titleEn": "Enable the default CDP setup and restart the browser when required", "evidence": ["command:browser_control_enable_default_cdp", "command:browser_control_restart_with_cdp"] }, + { "id": "agent-actions", "titleZh": "授权后让 Agent 截图、点击、输入、滚动并读取可见界面", "titleEn": "After authorization, let agents capture, click, type, scroll, and inspect the visible interface", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#computerUse.sectionDescription"] } + ], + "stepsZh": ["打开执行控制设置", "启用需要的能力", "按提示授予系统权限或连接浏览器"], + "stepsEn": ["Open Execution Control settings", "Enable the required capability", "Grant OS access or connect a browser when prompted"], + "agentExamplesZh": ["打开桌面控制设置", "带我配置浏览器控制"], + "agentExamplesEn": ["Open desktop-control settings", "Take me to browser-control setup"], + "destination": { "kind": "settings", "pageId": "tools.execution" }, + "operations": [] + }, + { + "id": "feature.skills", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Skills 技能", + "titleEn": "Skills", + "summaryZh": "为 Agent 安装和管理可复用的专业工作流,并控制哪些模式可以使用它们。", + "summaryEn": "Install and manage reusable expert workflows for agents, and control which modes can use them.", + "keywordsZh": ["Skill", "技能", "工作流", "技能市场", "安装技能"], + "keywordsEn": ["skill", "workflow", "skill market", "install skill", "agent capability"], + "highlightsZh": ["浏览与搜索 Skills", "安装、更新或移除 Skill", "按模式启用或停用"], + "highlightsEn": ["Browse and search Skills", "Install, update, or remove a Skill", "Enable or disable by mode"], + "items": [ + { "id": "installed-catalog", "titleZh": "统一查看用户级、项目级、本地和远程来源的已安装 Skills", "titleEn": "Browse installed Skills from user, project, local, and remote sources in one catalog", "evidence": ["command:get_skill_configs"] }, + { "id": "market", "titleZh": "浏览、搜索和刷新 Skill 市场", "titleEn": "Browse, search, and refresh the Skill market", "evidence": ["command:list_skill_market", "command:search_skill_market"] }, + { "id": "market-install", "titleZh": "把市场 Skill 下载到用户级或当前项目", "titleEn": "Download a market Skill for the user or current project", "evidence": ["command:download_skill_market"] }, + { "id": "local-add", "titleZh": "校验本地 Skill 路径并添加到用户级或项目级", "titleEn": "Validate a local Skill path and add it at user or project scope", "evidence": ["command:validate_skill_path", "command:add_skill"] }, + { "id": "remove", "titleZh": "删除已安装的用户级或项目级 Skill", "titleEn": "Remove an installed user-level or project-level Skill", "evidence": ["command:delete_skill"] }, + { "id": "global-enable", "titleZh": "在全局范围启用或停用单个 Skill", "titleEn": "Enable or disable an individual Skill globally", "evidence": ["command:get_global_skill_settings", "command:set_global_skill_disabled"] }, + { "id": "mode-selection", "titleZh": "按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择", "titleEn": "Choose Skills and skill groups per agent mode and restore defaults", "evidence": ["command:get_mode_skill_configs", "command:replace_mode_skill_selection", "command:set_mode_skill_disabled", "command:reset_mode_skill_selection"] }, + { "id": "shadowing", "titleZh": "识别同名 Skill 的用户级与项目级遮蔽优先级", "titleEn": "Understand user-versus-project shadowing precedence for same-named Skills", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/skills.json#list.item.shadowedDetail"] } + ], + "stepsZh": ["打开 Skills", "搜索需要的工作流", "安装后在会话中调用"], + "stepsEn": ["Open Skills", "Search for the workflow you need", "Install it and invoke it from a session"], + "agentExamplesZh": ["打开 Skills", "带我去技能管理"], + "agentExamplesEn": ["Open Skills", "Take me to skill management"], + "destination": { "kind": "action", "actionId": "surface.skills.open" }, + "operations": [] + }, + { + "id": "feature.miniapps", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Mini Apps 小应用", + "titleEn": "Mini Apps", + "summaryZh": "在 BitFun 内安装、创建和运行轻量应用,让界面、数据与 Agent 工作流组合在一起。", + "summaryEn": "Install, create, and run lightweight apps inside BitFun, combining UI, data, and agent workflows.", + "keywordsZh": ["Mini App", "小应用", "应用市场", "创建应用", "运行应用"], + "keywordsEn": ["mini app", "app market", "create app", "run app", "embedded app"], + "highlightsZh": ["浏览 Mini App 市场", "安装或创建 Mini App", "在独立场景中运行并与 Agent 对话"], + "highlightsEn": ["Browse the Mini App market", "Install or create a Mini App", "Run it in its own scene and chat with its agent"], + "items": [ + { "id": "gallery-lifecycle", "titleZh": "查看、搜索、创建、导入、编辑和删除 Mini App", "titleEn": "Browse, search, create, import, edit, and delete Mini Apps", "evidence": ["command:list_miniapps", "command:create_miniapp", "command:miniapp_import_from_path", "command:update_miniapp", "command:delete_miniapp"] }, + { "id": "market", "titleZh": "浏览市场、查看详情并安装或更新发布版本", "titleEn": "Browse the market, inspect listings, and install or update releases", "evidence": ["command:miniapp_market_browse", "command:miniapp_market_get_listing", "command:miniapp_market_install", "command:miniapp_market_installed_status"] }, + { "id": "market-account", "titleZh": "登录市场账户并收藏、评分和查看已安装来源", "titleEn": "Sign in to the market, favorite and rate apps, and inspect installed origins", "evidence": ["command:miniapp_market_auth_start", "command:miniapp_market_auth_poll", "command:miniapp_market_set_favorite", "command:miniapp_market_set_rating", "command:miniapp_market_installed_origins"] }, + { "id": "permissions", "titleZh": "按路径或工作区授予权限,并在定制前审查权限差异", "titleEn": "Grant path or workspace access and review permission changes before customization", "evidence": ["command:grant_miniapp_path", "command:grant_miniapp_workspace", "command:miniapp_permission_diff_for_draft", "command:miniapp_set_draft_permissions"] }, + { "id": "runtime", "titleZh": "运行 Mini App Host 与 Worker,查看状态并停止后台 Worker", "titleEn": "Run Mini App host and worker calls, inspect status, and stop background workers", "evidence": ["command:miniapp_host_call", "command:miniapp_worker_call", "command:miniapp_runtime_status", "command:miniapp_worker_list_running", "command:miniapp_worker_stop"] }, + { "id": "storage", "titleZh": "为正式应用和定制草稿分别读取与保存持久状态", "titleEn": "Read and save persistent state separately for installed apps and customization drafts", "evidence": ["command:get_miniapp_storage", "command:set_miniapp_storage", "command:get_miniapp_draft_storage", "command:set_miniapp_draft_storage"] }, + { "id": "agent-ai", "titleZh": "在 Mini App 中调用模型补全、聊天和专属 Agent 会话", "titleEn": "Use model completion, chat, and dedicated agent sessions inside Mini Apps", "evidence": ["command:miniapp_ai_complete", "command:miniapp_ai_chat", "command:miniapp_agent_ensure_session", "command:miniapp_agent_run"] }, + { "id": "customization", "titleZh": "创建定制草稿、实时预览,并应用、同步或丢弃修改", "titleEn": "Create customization drafts, preview them live, and apply, sync, or discard changes", "evidence": ["command:miniapp_create_draft", "command:miniapp_get_draft", "command:miniapp_apply_draft", "command:miniapp_sync_draft_from_fs", "command:miniapp_discard_draft"] }, + { "id": "versions", "titleZh": "查看版本历史并回滚到旧版本", "titleEn": "Inspect version history and roll back to an earlier release", "evidence": ["command:get_miniapp_versions", "command:rollback_miniapp"] }, + { "id": "publishing", "titleZh": "提交、撤回和审查市场发布,并可渲染幻灯片页面", "titleEn": "Submit, withdraw, and review market releases, and render slide pages", "evidence": ["command:miniapp_market_submit_installed", "command:miniapp_market_withdraw_submission", "command:miniapp_market_list_submissions", "command:miniapp_render_slide_page"] } + ], + "stepsZh": ["打开 Mini Apps", "选择市场、已安装或创建", "打开应用并按页面提示使用"], + "stepsEn": ["Open Mini Apps", "Choose Market, Installed, or Create", "Launch the app and follow its interface"], + "agentExamplesZh": ["打开 Mini Apps", "带我去小应用市场"], + "agentExamplesEn": ["Open Mini Apps", "Take me to the Mini App market"], + "destination": { "kind": "action", "actionId": "surface.miniapps.open" }, + "operations": [] + }, + { + "id": "feature.canvas", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Canvas 与交互产物", + "titleEn": "Canvas & interactive artifacts", + "summaryZh": "在会话旁展示和保存 Agent 生成的可视化、交互页面与结构化产物。", + "summaryEn": "Display and save visualizations, interactive pages, and structured artifacts generated beside a session.", + "keywordsZh": ["Canvas", "画布", "可视化", "交互产物", "Artifact"], + "keywordsEn": ["canvas", "visualization", "interactive artifact", "artifact", "preview"], + "highlightsZh": ["在会话中打开交互内容", "保留画布状态", "在面板中查看运行错误"], + "highlightsEn": ["Open interactive content from a session", "Persist canvas state", "Inspect runtime errors in the panel"], + "items": [ + { "id": "artifact-open", "titleZh": "从会话工具结果加载并打开持久化 Canvas 产物", "titleEn": "Load and open persistent Canvas artifacts from session tool results", "evidence": ["command:load_canvas_artifact"] }, + { "id": "html-react", "titleZh": "渲染 HTML 或 React 交互界面、图表和可视化", "titleEn": "Render HTML or React interfaces, charts, and interactive visualizations", "evidence": ["source:src/web-ui/src/tools/bitfun-canvas/reactRuntime.ts#runtime: 'react'", "source:src/web-ui/src/tools/bitfun-canvas/BitfunCanvasPanel.tsx#renderedHtml"] }, + { "id": "state", "titleZh": "在重新打开或刷新 Canvas 时加载和保存交互状态", "titleEn": "Load and save interactive state when a Canvas is reopened or refreshed", "evidence": ["command:load_canvas_state", "command:save_canvas_state"] }, + { "id": "source-inspection", "titleZh": "查看 Canvas 源码、编译版本和最后可用版本", "titleEn": "Inspect Canvas source, compiled revisions, and the last known good revision", "evidence": ["source:src/web-ui/src/tools/bitfun-canvas/BitfunCanvasPanel.tsx#lastKnownGoodRevision"] }, + { "id": "element-context", "titleZh": "选择 Canvas 内的元素并把元素引用加入会话上下文", "titleEn": "Select an element inside Canvas and add its reference to session context", "evidence": ["source:src/web-ui/src/tools/bitfun-canvas/BitfunCanvasPanel.tsx#createCanvasElementContext"] }, + { "id": "runtime-errors", "titleZh": "捕获运行错误、上报诊断并请求 Agent 自动修复", "titleEn": "Capture runtime errors, report diagnostics, and ask the agent to repair them", "evidence": ["command:report_canvas_runtime_error", "source:src/web-ui/src/tools/bitfun-canvas/BitfunCanvasPanel.tsx#canvas-runtime-auto-repair"] }, + { "id": "export-html", "titleZh": "把当前 Canvas 导出为可独立打开的 HTML 文件", "titleEn": "Export the current Canvas as a standalone HTML file", "evidence": ["source:src/web-ui/src/tools/bitfun-canvas/canvasHtmlExportService.ts#export async function exportCanvasHtml"] } + ], + "stepsZh": ["打开一个 AI 会话", "让 Agent 创建可视化或交互工具", "从工具结果打开 Canvas"], + "stepsEn": ["Open an AI session", "Ask the agent for a visualization or interactive tool", "Open the Canvas from the tool result"], + "agentExamplesZh": ["打开 AI 助手,我想做一个交互可视化", "创建一个可交互的 Canvas"], + "agentExamplesEn": ["Open the AI assistant; I want an interactive visualization", "Create an interactive Canvas"], + "destination": { "kind": "scene", "sceneId": "session" }, + "operations": [] + }, + { + "id": "feature.tasks-automation", + "kind": "feature", + "categoryId": "automation", + "titleZh": "任务板与定时任务", + "titleEn": "Task board & scheduled jobs", + "summaryZh": "集中查看待办事项,并让任务在指定时间或目标主机上持续运行。", + "summaryEn": "Track work in one task board and let scheduled jobs run at a chosen time or host.", + "keywordsZh": ["任务板", "待办", "Todo", "定时任务", "计划任务", "Cron"], + "keywordsEn": ["task board", "todo", "scheduled job", "automation", "cron", "recurring task"], + "highlightsZh": ["查看和整理待办", "创建一次性或重复任务", "为本地或远程工作区安排执行"], + "highlightsEn": ["Review and organize todos", "Create one-time or recurring jobs", "Schedule work for local or remote workspaces"], + "items": [ + { "id": "board-views", "titleZh": "按待处理、日历和已停用视图浏览任务", "titleEn": "Browse tasks in Pending, Calendar, and Inactive views", "evidence": ["source:src/web-ui/src/app/scenes/todos/TodosScene.tsx#TodoCalendar"] }, + { "id": "create-edit", "titleZh": "创建、编辑、启用、停用和删除定时任务", "titleEn": "Create, edit, enable, disable, and delete scheduled jobs", "evidence": ["command:create_cron_job", "command:update_cron_job", "command:delete_cron_job"] }, + { "id": "schedule-types", "titleZh": "设置一次性、每日、每周或自定义 Cron 时间表", "titleEn": "Choose one-time, daily, weekly, or custom cron schedules", "evidence": ["source:src/web-ui/src/app/scenes/todos/components/TodoEditor.tsx#schedule"] }, + { "id": "calendar-occurrences", "titleZh": "在日历中预览任务的下一次与后续运行时间", "titleEn": "Preview the next and future job occurrences on a calendar", "evidence": ["source:src/web-ui/src/app/scenes/todos/todoOccurrences.ts#occurrence"] }, + { "id": "agent-workspace", "titleZh": "为任务选择 Agent、模型、工作模式和工作区", "titleEn": "Choose the agent, model, work mode, and workspace for a job", "evidence": ["source:src/web-ui/src/app/scenes/todos/components/TodoEditor.tsx#agent"] }, + { "id": "local-remote-target", "titleZh": "把任务安排在当前主机或已连接的远程目标上运行", "titleEn": "Schedule jobs to run on the current host or a connected remote target", "evidence": ["source:src/web-ui/src/app/scenes/todos/components/TodoEditor.tsx#target"] }, + { "id": "host-readiness", "titleZh": "查看任务列表并等待桌面 Host 就绪后可靠执行", "titleEn": "List jobs and wait for desktop-host readiness before reliable execution", "evidence": ["command:list_cron_jobs", "command:notify_cron_host_ready"] } + ], + "stepsZh": ["打开任务板", "选择待办或定时任务", "创建任务并确认运行目标与时间"], + "stepsEn": ["Open the Task Board", "Choose todos or scheduled jobs", "Create the job and confirm its target and timing"], + "agentExamplesZh": ["打开任务板", "带我去看定时任务"], + "agentExamplesEn": ["Open the task board", "Take me to scheduled jobs"], + "destination": { "kind": "action", "actionId": "surface.todos.open" }, + "operations": [] + }, + { + "id": "feature.insights", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Insights 工作洞察", + "titleEn": "Insights", + "summaryZh": "把会话和项目活动汇总成可读的洞察,帮助回顾工作方式、用量和进展。", + "summaryEn": "Turn session and project activity into readable insights about working patterns, usage, and progress.", + "keywordsZh": ["洞察", "分析", "统计", "工作报告", "用量"], + "keywordsEn": ["insights", "analytics", "statistics", "work report", "usage"], + "highlightsZh": ["生成工作洞察", "查看最新报告", "结合 Token 用量理解成本"], + "highlightsEn": ["Generate work insights", "Read the latest report", "Relate activity to token usage"], + "items": [ + { "id": "availability", "titleZh": "检查当前账户与会话是否已有可分析的洞察数据", "titleEn": "Check whether the current account and sessions contain analyzable insight data", "evidence": ["command:has_insights_data"] }, + { "id": "generate", "titleZh": "按所选日期范围和模型生成工作洞察报告", "titleEn": "Generate a work-insights report for a selected date range and model", "evidence": ["command:generate_insights"] }, + { "id": "cancel", "titleZh": "取消正在运行的洞察生成任务", "titleEn": "Cancel an in-progress insights generation job", "evidence": ["command:cancel_insights_generation"] }, + { "id": "latest-report", "titleZh": "查看最新报告或加载指定的历史报告", "titleEn": "Open the latest report or load a selected historical report", "evidence": ["command:get_latest_insights", "command:load_insights_report"] }, + { "id": "usage-statistics", "titleZh": "把工作活动与模型、Token 和缓存用量统计关联起来", "titleEn": "Relate work activity to model, token, and cache-usage statistics", "evidence": ["command:get_token_usage_statistics"] }, + { "id": "patterns", "titleZh": "回顾项目分布、工作时段、任务类型和协作习惯", "titleEn": "Review project distribution, working hours, task types, and collaboration patterns", "evidence": ["source:src/web-ui/src/app/scenes/my-agent/InsightsScene.tsx#InsightsScene"] } + ], + "stepsZh": ["打开 Insights", "选择可用的数据范围", "生成或查看最新报告"], + "stepsEn": ["Open Insights", "Choose the available data scope", "Generate or read the latest report"], + "agentExamplesZh": ["打开 Insights", "带我查看工作洞察"], + "agentExamplesEn": ["Open Insights", "Show me my work insights"], + "destination": { "kind": "action", "actionId": "surface.insights.open" }, + "operations": [] + }, + { + "id": "feature.ecosystem-compatibility", + "kind": "feature", + "categoryId": "automation", + "titleZh": "外部 AI 生态兼容", + "titleEn": "External AI ecosystem compatibility", + "summaryZh": "发现并迁移 OpenCode、Claude Code、Codex 等外部 AI 工具的配置、命令、Hooks 与 MCP 资源。", + "summaryEn": "Discover and migrate configuration, commands, hooks, and MCP resources from OpenCode, Claude Code, Codex, and other AI tools.", + "keywordsZh": ["生态兼容", "外部 AI", "迁移配置", "OpenCode", "Claude Code", "Codex", "导入"], + "keywordsEn": ["ecosystem compatibility", "external AI", "configuration migration", "OpenCode", "Claude Code", "Codex", "import"], + "highlightsZh": ["扫描外部 AI 应用", "预览冲突与迁移计划", "按项导入提示词、Hooks、Agent 与 MCP"], + "highlightsEn": ["Scan external AI applications", "Preview conflicts and migration plans", "Import prompts, hooks, agents, and MCP selectively"], + "items": [ + { "id": "source-discovery", "titleZh": "发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容", "titleEn": "Discover OpenCode, Claude Code, Codex, and other external AI sources and content", "evidence": ["command:get_external_ecosystem_awareness_command", "command:get_external_source_snapshot"] }, + { "id": "source-policy", "titleZh": "按来源启用或停用集成,并选择管理、预览或只读策略", "titleEn": "Enable or disable each source and choose managed, preview, or read-only policy", "evidence": ["command:set_external_source_enabled_command", "command:update_external_integration_policy_command"] }, + { "id": "prompts-commands", "titleZh": "展开外部 Prompt/Command 内容并处理与原生命令的冲突", "titleEn": "Expand external prompt/command content and resolve conflicts with native commands", "evidence": ["command:expand_external_prompt_command_command", "command:get_native_prompt_command_conflicts_command", "command:set_native_prompt_command_conflict_choice_command"] }, + { "id": "subagents", "titleZh": "导入或启用外部 Agent,处理同名冲突并绑定模型", "titleEn": "Import or enable external agents, resolve naming conflicts, and bind models", "evidence": ["command:choose_external_subagent_conflict_command", "command:set_external_subagent_activation_command", "command:set_external_subagent_model_binding_command", "command:set_external_subagents_enabled_command"] }, + { "id": "mcp-import", "titleZh": "预览 MCP 导入计划,逐个处理服务器冲突并应用", "titleEn": "Preview MCP import plans, resolve server conflicts individually, and apply them", "evidence": ["command:plan_external_mcp_import_command", "command:choose_external_mcp_conflict_command", "command:set_external_mcp_server_decision_command", "command:apply_external_mcp_import_command"] }, + { "id": "tool-targets", "titleZh": "选择外部工具目标、解决冲突并控制是否启用", "titleEn": "Choose external tool targets, resolve conflicts, and control activation", "evidence": ["command:set_external_tool_target_decision_command", "command:set_external_tool_conflict_choice_command", "command:set_external_tool_targets_enabled_command"] }, + { "id": "hooks", "titleZh": "查看外部 Hooks 目录、规划导入、修改选择并应用", "titleEn": "Inspect external hook catalogs, plan imports, edit selections, and apply", "evidence": ["command:get_external_hook_catalog", "command:plan_external_hook_import_command", "command:mutate_external_hook_import_command", "command:apply_external_hook_import_command"] }, + { "id": "security-review", "titleZh": "在迁移前查看冲突、安全影响和来源控制快照", "titleEn": "Review conflicts, security impact, and source-control snapshots before migration", "evidence": ["command:get_external_source_control_snapshot", "command:apply_external_source_control_action_command", "command:acknowledge_external_ecosystems_command"] }, + { "id": "reveal-source", "titleZh": "在文件管理器或远程环境中定位外部配置来源", "titleEn": "Reveal external configuration sources in the file manager or remote environment", "evidence": ["command:reveal_external_source_location", "command:get_workspace_reference_snapshot"] } + ], + "stepsZh": ["打开“生态兼容”", "选择来源并查看扫描结果", "确认计划后导入需要的内容"], + "stepsEn": ["Open Ecosystem Compatibility", "Choose a source and review the scan", "Confirm the plan and import selected content"], + "agentExamplesZh": ["打开外部 AI 生态兼容", "我想迁移 Claude Code 的配置"], + "agentExamplesEn": ["Open external AI ecosystem compatibility", "I want to migrate my Claude Code configuration"], + "destination": { "kind": "action", "actionId": "surface.ecosystemCompatibility.open" }, + "operations": [] + }, + { + "id": "feature.remote-workspaces", + "kind": "feature", + "categoryId": "connect", + "titleZh": "远程工作区", + "titleEn": "Remote workspaces", + "summaryZh": "通过 SSH 或容器在远程主机上打开项目,让文件、搜索、终端和 Agent 都在目标环境执行。", + "summaryEn": "Open projects over SSH or in containers so files, search, terminal, and agents all execute in the target environment.", + "keywordsZh": ["远程工作区", "SSH", "远程项目", "容器", "跳板机", "远程开发"], + "keywordsEn": ["remote workspace", "SSH", "remote project", "container", "jump host", "remote development"], + "highlightsZh": ["保存 SSH 连接配置", "上传下载与远程文件操作", "在远程环境运行终端和 Agent"], + "highlightsEn": ["Save SSH connection profiles", "Transfer and edit remote files", "Run terminals and agents in the remote environment"], + "items": [ + { "id": "ssh-profiles", "titleZh": "保存、列出、测试和删除 SSH 连接配置", "titleEn": "Save, list, test, and delete SSH connection profiles", "evidence": ["command:ssh_save_connection", "command:ssh_list_saved_connections", "command:ssh_test_connection", "command:ssh_delete_connection"] }, + { "id": "ssh-auth", "titleZh": "使用密码、私钥、证书、SSH Config Host 与跳板机连接", "titleEn": "Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts", "evidence": ["command:ssh_get_config", "command:ssh_has_stored_password", "command:ssh_list_config_hosts", "command:ssh_connect"] }, + { "id": "docker", "titleZh": "发现远程 Docker 容器并把容器作为工作环境", "titleEn": "Discover remote Docker containers and use a container as the work environment", "evidence": ["command:ssh_list_docker_containers"] }, + { "id": "remote-open", "titleZh": "打开、关闭和移除远程工作区,并读取服务器信息", "titleEn": "Open, close, and remove remote workspaces, and inspect server information", "evidence": ["command:remote_open_workspace", "command:remote_close_workspace", "command:remote_remove_workspace", "command:ssh_get_server_info"] }, + { "id": "remote-files", "titleZh": "浏览、读取、写入、创建、重命名和删除远程文件与目录", "titleEn": "Browse, read, write, create, rename, and remove remote files and directories", "evidence": ["command:remote_get_tree", "command:remote_read_file", "command:remote_write_file", "command:remote_create_dir", "command:remote_rename", "command:remote_remove"] }, + { "id": "transfer", "titleZh": "上传本地文件、下载远程文件并取消进行中的传输", "titleEn": "Upload local files, download remote files, and cancel active transfers", "evidence": ["command:remote_upload_from_local_path", "command:remote_download_to_local_path", "command:cancel_transfer"] }, + { "id": "remote-execution", "titleZh": "在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面", "titleEn": "Execute commands on the target so terminals, search, and agents use the remote data plane", "evidence": ["command:remote_execute", "command:remote_get_workspace_info"] }, + { "id": "port-forwarding", "titleZh": "发现远程监听端口并启动、查看或停止端口转发", "titleEn": "Discover remote listening ports and start, inspect, or stop port forwarding", "evidence": ["command:ssh_list_remote_listening_ports", "command:ssh_start_port_forward", "command:ssh_list_port_forwards", "command:ssh_stop_port_forward"] }, + { "id": "connection-lifecycle", "titleZh": "查看连接状态并断开单个或全部 SSH 会话", "titleEn": "Inspect connection status and disconnect one or all SSH sessions", "evidence": ["command:ssh_is_connected", "command:ssh_disconnect", "command:ssh_disconnect_all"] } + ], + "stepsZh": ["打开新建项目", "选择远程连接方式", "配置主机并测试连接后打开工作区"], + "stepsEn": ["Open New Project", "Choose a remote connection type", "Configure and test the host, then open the workspace"], + "agentExamplesZh": ["打开远程项目配置", "我想连接一个 SSH 工作区"], + "agentExamplesEn": ["Open remote-project setup", "I want to connect to an SSH workspace"], + "destination": { "kind": "action", "actionId": "project.new" }, + "operations": [] + }, + { + "id": "feature.remote-connect", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Remote Connect 与多设备", + "titleEn": "Remote Connect & devices", + "summaryZh": "从手机、Bot 或另一台 BitFun 设备连接当前主机,远程查看会话、回答权限并继续工作。", + "summaryEn": "Connect to this host from mobile, a bot, or another BitFun device to inspect sessions, answer permissions, and continue work remotely.", + "keywordsZh": ["Remote Connect", "远程控制", "手机", "飞书", "Telegram", "微信", "多设备", "Peer Device", "账户同步"], + "keywordsEn": ["remote connect", "remote control", "mobile", "Feishu", "Telegram", "WeChat", "multi-device", "peer device", "account sync"], + "highlightsZh": ["通过局域网、Ngrok 或自建 Relay 连接", "接入飞书、Telegram 或微信 Bot", "登录账户、同步会话并进入 Peer Device Mode"], + "highlightsEn": ["Connect through LAN, Ngrok, or a self-hosted relay", "Use Feishu, Telegram, or WeChat bots", "Sign in, sync sessions, and enter Peer Device Mode"], + "items": [ + { "id": "connection-methods", "titleZh": "选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器", "titleEn": "Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server", "evidence": ["command:remote_connect_get_methods", "command:remote_connect_configure_custom_server"] }, + { "id": "start-stop-status", "titleZh": "启动、停止 Remote Connect 并查看实时连接状态和设备信息", "titleEn": "Start or stop Remote Connect and inspect live status and device information", "evidence": ["command:remote_connect_start", "command:remote_connect_stop", "command:remote_connect_status", "command:remote_connect_get_device_info"] }, + { "id": "network", "titleZh": "查看局域网 IP、网络信息与可分享的连接配置", "titleEn": "Inspect LAN IP, network details, and shareable connection configuration", "evidence": ["command:remote_connect_get_lan_ip", "command:remote_connect_get_lan_network_info", "command:remote_connect_get_form_state"] }, + { "id": "bots", "titleZh": "配置飞书、Telegram、微信等 Bot 并单独停止 Bot", "titleEn": "Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently", "evidence": ["command:remote_connect_configure_bot", "command:remote_connect_stop_bot", "command:remote_connect_weixin_qr_start", "command:remote_connect_weixin_qr_poll"] }, + { "id": "relay-wizard", "titleZh": "通过向导预检、安装 Docker、部署、注册并验证自建 Relay", "titleEn": "Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard", "evidence": ["command:relay_deploy_preflight", "command:relay_deploy_install_docker", "command:relay_deploy_start", "command:relay_deploy_register", "command:relay_deploy_verify"] }, + { "id": "account", "titleZh": "登录、退出并查看账户状态和凭据提示", "titleEn": "Sign in, sign out, and inspect account status and credential hints", "evidence": ["command:account_login", "command:account_finalize_login", "command:account_logout", "command:account_status", "command:account_get_credential_hint"] }, + { "id": "devices", "titleZh": "列出、连接、查看在线状态和删除同账户设备", "titleEn": "List, connect, inspect online status, and remove same-account devices", "evidence": ["command:account_list_devices", "command:account_connect_devices", "command:account_online_devices", "command:account_delete_device"] }, + { "id": "session-sync", "titleZh": "同步、导出、导入、删除或发送会话到另一台设备", "titleEn": "Sync, export, import, delete, or send sessions to another device", "evidence": ["command:account_sync_session", "command:account_export_local_session", "command:account_import_remote_sessions", "command:account_delete_synced_session", "command:account_send_session_to_device"] }, + { "id": "settings-sync", "titleZh": "在设备间自动或手动同步 BitFun 设置", "titleEn": "Synchronize BitFun settings across devices automatically or on demand", "evidence": ["command:account_sync_settings", "command:account_fetch_settings", "command:account_auto_sync"] }, + { "id": "peer-device", "titleZh": "进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面", "titleEn": "Enter Peer Device Mode and use another BitFun device as the command and event data plane", "evidence": ["command:peer_control_attach", "command:peer_control_detach", "command:peer_controller_set_active", "command:peer_mode_ping"] } + ], + "stepsZh": ["打开 Remote Connect", "选择网络、Bot 或账户", "按向导连接并确认安全提示"], + "stepsEn": ["Open Remote Connect", "Choose Network, Bot, or Account", "Follow the connection flow and review its security notice"], + "agentExamplesZh": ["打开 Remote Connect", "我想配置手机远程控制", "带我管理已连接设备"], + "agentExamplesEn": ["Open Remote Connect", "I want to configure mobile remote control", "Take me to connected-device management"], + "destination": { "kind": "event", "eventName": "bitfun:open-remote-connect" }, + "operations": [] + }, + { + "id": "feature.detached-dispatch", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Detached Dispatch 远程派发", + "titleEn": "Detached Dispatch", + "summaryZh": "把可持续运行的任务派发到另一台 BitFun 主机;控制端可以断开,目标主机继续执行并保留记录。", + "summaryEn": "Dispatch durable work to another BitFun host; the controller may disconnect while the target continues and keeps the record.", + "keywordsZh": ["派发任务", "Detached Dispatch", "远程执行", "目标主机", "离线任务"], + "keywordsEn": ["detached dispatch", "dispatch task", "remote execution", "target host", "offline job"], + "highlightsZh": ["发现与探测目标主机", "派发、继续或取消任务", "断线后重新加载事件与执行记录"], + "highlightsEn": ["Discover and probe target hosts", "Dispatch, continue, or cancel jobs", "Reload events and execution history after reconnecting"], + "items": [ + { "id": "targets", "titleZh": "列出可派发目标并探测版本、连接和运行能力", "titleEn": "List dispatch targets and probe their version, connectivity, and runtime capabilities", "evidence": ["command:dispatch_list_targets", "command:dispatch_probe_target"] }, + { "id": "provision", "titleZh": "为目标主机配置运行环境并安装或更新 BitFun CLI", "titleEn": "Provision the target runtime and install or update the BitFun CLI", "evidence": ["command:dispatch_provision_target", "command:dispatch_install_cli_start", "command:dispatch_install_cli_poll", "command:dispatch_install_cli_cancel"] }, + { "id": "model-sync", "titleZh": "在提交任务前同步目标所需的模型配置", "titleEn": "Synchronize required model configuration before submitting a job", "evidence": ["command:dispatch_sync_model_config"] }, + { "id": "submit", "titleZh": "把包含工作区、会话、模型和权限策略的持久任务提交到目标", "titleEn": "Submit a durable job with workspace, session, model, and permission policy to the target", "evidence": ["command:dispatch_submit"] }, + { "id": "status-list", "titleZh": "列出派发任务并查询运行状态、结果和错误", "titleEn": "List dispatched jobs and query their status, result, and errors", "evidence": ["command:dispatch_list_jobs", "command:dispatch_status", "command:dispatch_query"] }, + { "id": "transcript", "titleZh": "保存、追加和重新加载可断线恢复的执行记录", "titleEn": "Save, append, and reload reconnectable execution transcripts", "evidence": ["command:dispatch_save_transcript", "command:dispatch_append", "command:dispatch_load_transcript"] }, + { "id": "permission-continuation", "titleZh": "远程回答权限请求,并继续或取消目标端任务", "titleEn": "Answer permission requests remotely and continue or cancel target-side work", "evidence": ["command:dispatch_answer", "command:dispatch_continue", "command:dispatch_cancel"] }, + { "id": "result-sync", "titleZh": "将目标端结果同步回控制端,而不把控制端当作远程文件系统代理", "titleEn": "Synchronize target-side results back without treating the controller as a remote-filesystem proxy", "evidence": ["command:dispatch_sync_result"] } + ], + "stepsZh": ["先在 Remote Connect 中登录并连接设备", "从会话的派发入口选择目标", "提交任务后在任务状态中跟踪"], + "stepsEn": ["Sign in and connect devices through Remote Connect", "Choose a target from the session dispatch flow", "Submit the work and follow its job status"], + "agentExamplesZh": ["打开设备管理,我想把任务派发到另一台机器", "带我配置远程任务派发"], + "agentExamplesEn": ["Open device management so I can dispatch work to another machine", "Take me to remote task dispatch setup"], + "destination": { "kind": "event", "eventName": "bitfun:open-remote-connect", "detail": { "group": "account" } }, + "operations": [] + }, + { + "id": "feature.pages", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Pages 发布", + "titleEn": "Pages publishing", + "summaryZh": "保存页面版本并发布到公开或私有地址,管理标题、可见性、历史版本和分享链接。", + "summaryEn": "Save page versions and publish them to public or private URLs while managing titles, visibility, history, and share links.", + "keywordsZh": ["Pages", "发布网页", "页面托管", "分享链接", "版本", "部署"], + "keywordsEn": ["pages", "publish website", "page hosting", "share link", "version", "deploy"], + "highlightsZh": ["保存页面版本", "发布、取消发布或删除页面", "更新标题和访问可见性"], + "highlightsEn": ["Save page versions", "Publish, unpublish, or delete pages", "Update titles and access visibility"], + "items": [ + { "id": "pages-list", "titleZh": "查看账户下的 Pages 与每个页面的当前发布状态", "titleEn": "List account Pages and inspect each page's current publishing state", "evidence": ["command:page_list"] }, + { "id": "immutable-versions", "titleZh": "保存不可变页面版本并浏览版本历史", "titleEn": "Save immutable page versions and browse version history", "evidence": ["command:page_save_version", "command:page_list_versions"] }, + { "id": "publish", "titleZh": "发布或重新部署选中的页面版本", "titleEn": "Publish or redeploy a selected page version", "evidence": ["command:page_publish", "command:page_deploy"] }, + { "id": "visibility", "titleZh": "更新标题、公开/私有可见性和访问设置", "titleEn": "Update titles, public/private visibility, and access settings", "evidence": ["command:page_update"] }, + { "id": "share-open", "titleZh": "创建可打开和分享的页面链接", "titleEn": "Create an openable, shareable link for a page", "evidence": ["command:page_create_open_link"] }, + { "id": "unpublish", "titleZh": "取消发布页面,同时保留可再次发布的版本", "titleEn": "Unpublish a page while retaining versions for later publication", "evidence": ["command:page_unpublish"] }, + { "id": "delete", "titleZh": "删除单个版本或整个 Page", "titleEn": "Delete an individual version or an entire Page", "evidence": ["command:page_delete_version", "command:page_delete"] } + ], + "stepsZh": ["登录 BitFun 账户", "打开 Pages", "选择页面并确认发布与可见性"], + "stepsEn": ["Sign in to a BitFun account", "Open Pages", "Choose a page and confirm publishing and visibility"], + "agentExamplesZh": ["打开 Pages", "带我管理已发布的页面"], + "agentExamplesEn": ["Open Pages", "Take me to my published pages"], + "destination": { "kind": "scene", "sceneId": "pages" }, + "operations": [] + }, + { + "id": "feature.voice-input", + "kind": "feature", + "categoryId": "application", + "titleZh": "语音输入", + "titleEn": "Voice input", + "summaryZh": "在聊天输入框中录音并转成文字,可选择本地模型、语言、麦克风与最长录音时间。", + "summaryEn": "Record speech in the chat composer and transcribe it to text, with control over local models, language, microphone, and duration.", + "keywordsZh": ["语音输入", "录音", "转写", "麦克风", "语音模型", "听写"], + "keywordsEn": ["voice input", "recording", "transcription", "microphone", "speech model", "dictation"], + "highlightsZh": ["下载和校验本地语音模型", "选择识别语言与麦克风", "在发送前编辑转写文本"], + "highlightsEn": ["Download and verify local speech models", "Choose a recognition language and microphone", "Edit transcribed text before sending"], + "items": [ + { "id": "composer-recording", "titleZh": "从聊天输入框开始、结束或取消一次录音", "titleEn": "Start, finish, or cancel a recording from the chat composer", "evidence": ["command:speech_start_input_session", "command:speech_finish_input_session", "command:speech_cancel_input_session"] }, + { "id": "stream-audio", "titleZh": "录音过程中分块传输音频并显示识别进度", "titleEn": "Stream audio chunks during recording and show recognition progress", "evidence": ["command:speech_append_audio_chunk"] }, + { "id": "local-models", "titleZh": "查看本地语音模型及安装、下载、验证、修复和删除状态", "titleEn": "Browse local speech models and their install, download, verify, repair, and delete states", "evidence": ["command:speech_list_models", "command:speech_download_model", "command:speech_verify_model", "command:speech_delete_model"] }, + { "id": "cancel-download", "titleZh": "取消正在进行的语音模型下载", "titleEn": "Cancel an in-progress speech-model download", "evidence": ["command:speech_cancel_model_download"] }, + { "id": "language-microphone", "titleZh": "选择自动检测或指定识别语言,并选择系统麦克风", "titleEn": "Use automatic language detection or choose a language and system microphone", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#composer.language.label", "source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#diagnostics.microphone.label"] }, + { "id": "diagnostic-test", "titleZh": "在设置页进行麦克风与语音识别测试并查看耗时和错误", "titleEn": "Test the microphone and speech recognition in Settings, including timing and errors", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#diagnostics.recognition.start"] }, + { "id": "edit-transcript", "titleZh": "把转写结果放回输入框,在发送前继续编辑", "titleEn": "Return the transcript to the composer for editing before sending", "evidence": ["command:speech_finish_input_session", "source:src/web-ui/src/flow_chat/components/voice/useComposerVoiceInput.ts#result.text.trim()"] } + ], + "stepsZh": ["打开输入设置的“语音”页", "启用语音并准备模型", "在聊天输入框点击麦克风开始录音"], + "stepsEn": ["Open the Voice input settings view", "Enable voice and prepare a model", "Use the microphone button in the chat composer"], + "agentExamplesZh": ["打开语音输入设置", "帮我配置听写功能"], + "agentExamplesEn": ["Open voice-input settings", "Help me configure dictation"], + "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, + "operations": [] + }, + { + "id": "feature.desktop-pet", + "kind": "feature", + "categoryId": "application", + "titleZh": "Agent 桌面伙伴", + "titleEn": "Agent desktop companion", + "summaryZh": "在输入框或桌面上显示 Agent 伙伴,并选择、导入或管理 Petdex 角色包。", + "summaryEn": "Show an agent companion in the composer or on the desktop, and choose, import, or manage Petdex character packs.", + "keywordsZh": ["桌面宠物", "Agent 伙伴", "Petdex", "像素宠物", "角色包"], + "keywordsEn": ["desktop pet", "agent companion", "Petdex", "pixel pet", "character pack"], + "highlightsZh": ["在桌面或输入框显示伙伴", "选择预设角色", "导入和删除 Petdex 包"], + "highlightsEn": ["Show the companion on desktop or in the composer", "Choose a preset character", "Import and remove Petdex packs"], + "items": [ + { "id": "enable", "titleZh": "整体启用或停用 Agent 桌面伙伴", "titleEn": "Enable or disable the agent desktop companion globally", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.enable"] }, + { "id": "display-modes", "titleZh": "选择在聊天输入框、独立桌面窗口或两处显示", "titleEn": "Show the companion in the chat composer, a desktop window, or both", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.displayModeLabel"] }, + { "id": "presets", "titleZh": "查看并切换内置 Petdex 角色预设", "titleEn": "Browse and switch among built-in Petdex character presets", "evidence": ["command:list_agent_companion_pets"] }, + { "id": "petdex-import", "titleZh": "从本地 Petdex 包导入新的角色与动画", "titleEn": "Import new characters and animations from a local Petdex package", "evidence": ["command:import_agent_companion_pet_package"] }, + { "id": "petdex-delete", "titleZh": "删除已导入的 Petdex 包并回退到可用角色", "titleEn": "Delete an imported Petdex package and fall back to an available character", "evidence": ["command:delete_agent_companion_pet_package"] }, + { "id": "desktop-window", "titleZh": "显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口", "titleEn": "Show, hide, and resize the desktop companion window, and return to the main window", "evidence": ["command:show_agent_companion_desktop_pet", "command:hide_agent_companion_desktop_pet", "command:resize_agent_companion_desktop_pet", "command:show_main_window"] } + ], + "stepsZh": ["打开桌面伙伴设置", "启用伙伴并选择显示位置", "选择预设或导入 Petdex 包"], + "stepsEn": ["Open Companion settings", "Enable it and choose where it appears", "Choose a preset or import a Petdex pack"], + "agentExamplesZh": ["打开桌面宠物设置", "带我配置 Agent 伙伴"], + "agentExamplesEn": ["Open desktop-pet settings", "Take me to agent-companion setup"], + "destination": { "kind": "settings", "pageId": "application.pet" }, + "operations": [] + }, + { + "id": "setting.application.general", + "kind": "setting", + "categoryId": "application", + "titleZh": "常规设置", + "titleEn": "General settings", + "summaryZh": "管理启动、更新、关闭行为、通知与睡眠保持等应用级偏好。", + "summaryEn": "Manage app-level preferences for startup, updates, close behavior, notifications, and sleep prevention.", + "keywordsZh": ["常规设置", "开机启动", "自动更新", "通知", "关闭按钮", "阻止睡眠"], + "keywordsEn": ["general settings", "launch at login", "auto update", "notifications", "close button", "prevent sleep"], + "highlightsZh": ["开机启动与自动更新", "窗口关闭和托盘行为", "任务完成、权限请求与启动提示通知"], + "highlightsEn": ["Launch-at-login and automatic updates", "Window close and tray behavior", "Completion, permission, and startup-tip notifications"], + "items": [ + { "id": "automatic-updates", "titleZh": "启用或停用自动检查更新", "titleEn": "Enable or disable automatic update checks", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#autoUpdate.toggleLabel", "command:check_for_updates"] }, + { "id": "manual-update", "titleZh": "手动检查、下载并安装可用更新,然后按需重启", "titleEn": "Check for, download, and install an available update manually, then restart when needed", "evidence": ["command:check_for_updates", "command:install_update", "command:restart_app"] }, + { "id": "launch-at-login", "titleZh": "控制 BitFun 是否在登录系统后自动启动", "titleEn": "Choose whether BitFun launches automatically after system sign-in", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#launchAtLogin.toggleLabel"] }, + { "id": "prevent-sleep", "titleZh": "在长任务运行时阻止电脑自动睡眠", "titleEn": "Prevent the computer from sleeping while long-running work is active", "evidence": ["command:get_prevent_sleep_enabled", "command:set_prevent_sleep_enabled"] }, + { "id": "close-behavior", "titleZh": "选择关闭主窗口时退出、最小化到托盘或每次询问", "titleEn": "Choose whether closing the main window quits, minimizes to tray, or asks each time", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#windowBehavior.closeButtonLabel", "command:minimize_to_tray", "command:quit_app"] }, + { "id": "notifications", "titleZh": "分别控制任务完成、权限请求和启动提示通知", "titleEn": "Control completion, permission-request, and startup-tip notifications independently", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#notifications.dialogCompletion.label", "source:src/web-ui/src/locales/zh-CN/settings/application.json#notifications.permissionRequest.label", "command:send_system_notification"] }, + { "id": "announcements", "titleZh": "查看、标记已读、忽略或永久隐藏产品公告与提示", "titleEn": "Review, mark seen, dismiss, or permanently hide product announcements and tips", "evidence": ["command:get_pending_announcements", "command:mark_announcement_seen", "command:dismiss_announcement", "command:never_show_announcement"] } + ], + "stepsZh": ["打开设置", "进入“应用 > 常规”", "修改开关;变更会自动保存"], + "stepsEn": ["Open Settings", "Go to Application > General", "Change a control; updates are saved automatically"], + "agentExamplesZh": ["关闭自动更新", "以后关闭窗口时最小化到托盘", "打开常规设置"], + "agentExamplesEn": ["Turn off automatic updates", "Minimize to tray when I close the window", "Open General settings"], + "destination": { "kind": "settings", "pageId": "application.general" }, + "operations": [], + "options": [ + { + "id": "auto-update", + "titleZh": "自动检查更新", + "titleEn": "Automatic updates", + "descriptionZh": "启动后自动检查可用更新。", + "descriptionEn": "Check for available updates automatically after startup.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "app.auto_update" } + }, + { + "id": "close-button-behavior", + "titleZh": "关闭按钮行为", + "titleEn": "Close button behavior", + "descriptionZh": "选择退出应用或最小化到托盘。", + "descriptionEn": "Choose whether closing quits the app or minimizes it to the tray.", + "valueSchema": { "type": "string", "enum": ["ask", "minimize_to_tray", "quit"] }, + "handler": { "kind": "config", "path": "app.close_button_behavior" } + }, + { + "id": "completion-notification", + "titleZh": "任务完成通知", + "titleEn": "Completion notifications", + "descriptionZh": "会话任务完成时发送系统通知。", + "descriptionEn": "Send an OS notification when session work completes.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "app.notifications.dialog_completion_notify" } + }, + { + "id": "permission-notification", + "titleZh": "权限请求通知", + "titleEn": "Permission request notifications", + "descriptionZh": "Agent 等待权限确认时发送系统通知。", + "descriptionEn": "Send an OS notification when an agent waits for permission.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "app.notifications.permission_request_notify" } + }, + { + "id": "startup-tips", + "titleZh": "启动提示", + "titleEn": "Startup tips", + "descriptionZh": "启动后显示功能提示。", + "descriptionEn": "Show product tips after startup.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "app.notifications.enable_startup_tips" } + } + ] + }, + { + "id": "setting.application.appearance", + "kind": "setting", + "categoryId": "application", + "titleZh": "外观与语言", + "titleEn": "Appearance & language", + "summaryZh": "切换主题与语言,调整字体和动效,并安装或导入外观包。", + "summaryEn": "Switch themes and languages, tune typography and motion, and install or import appearance packs.", + "keywordsZh": ["外观", "主题", "深色模式", "浅色模式", "语言", "字体", "动效", "皮肤"], + "keywordsEn": ["appearance", "theme", "dark mode", "light mode", "language", "font", "motion", "skin"], + "highlightsZh": ["系统、深色与浅色主题", "界面语言与字号", "鼠标光效、动效和外观包"], + "highlightsEn": ["System, dark, and light themes", "UI language and font size", "Mouse glow, motion, and appearance packs"], + "items": [ + { "id": "built-in-appearance", "titleZh": "选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观", "titleEn": "Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#appearance.presets.bitfun-tokyo-night.name"] }, + { "id": "language", "titleZh": "切换简体中文、繁体中文、英文等受支持界面语言", "titleEn": "Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages", "evidence": ["command:i18n_get_supported_languages", "command:i18n_set_language", "command:i18n_set_config"] }, + { "id": "ui-font-size", "titleZh": "分别调整整个界面与聊天区字号,并支持自定义像素值", "titleEn": "Adjust global UI and chat font sizes independently, including custom pixel values", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#appearance.fontSize.uiSizeLabel", "source:src/web-ui/src/locales/zh-CN/settings/application.json#appearance.fontSize.flowChatLabel"] }, + { "id": "visual-effects", "titleZh": "控制鼠标光效,并让动态背景尊重系统的减少动效偏好", "titleEn": "Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/appearance.json#effects.mouseGlow.label", "source:src/web-ui/src/infrastructure/appearance/runtime/AppearanceBackgroundMedia.tsx#prefers-reduced-motion: reduce"] }, + { "id": "local-packages", "titleZh": "导入、预览、应用、导出和删除本地外观包", "titleEn": "Import, preview, apply, export, and delete local appearance packages", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/appearance.json#package.import", "source:src/web-ui/src/locales/zh-CN/settings/appearance.json#package.export", "source:src/web-ui/src/locales/zh-CN/settings/appearance.json#package.delete"] }, + { "id": "appearance-market", "titleZh": "浏览、搜索、筛选并安装或更新 Skin 市场外观", "titleEn": "Browse, search, filter, install, and update appearances from the Skin market", "evidence": ["command:appearance_market_browse", "command:appearance_market_download_release"] }, + { "id": "market-submissions", "titleZh": "提交、查看和撤回自己的外观市场投稿", "titleEn": "Submit, review, and withdraw your appearance-market submissions", "evidence": ["command:appearance_market_submit_package", "command:appearance_market_list_submissions", "command:appearance_market_withdraw_submission"] }, + { "id": "market-review", "titleZh": "在具备权限时查看并批准或拒绝外观投稿", "titleEn": "When authorized, inspect and approve or reject appearance submissions", "evidence": ["command:appearance_market_list_review_submissions", "command:appearance_market_get_review_submission", "command:appearance_market_review_submission"] } + ], + "stepsZh": ["打开设置", "进入“应用 > 外观”", "选择主题、语言或外观效果"], + "stepsEn": ["Open Settings", "Go to Application > Appearance", "Choose a theme, language, or visual effect"], + "agentExamplesZh": ["切换成深色主题", "把界面语言改成英文", "打开外观设置"], + "agentExamplesEn": ["Switch to the dark theme", "Change the interface language to English", "Open Appearance settings"], + "destination": { "kind": "settings", "pageId": "application.appearance" }, + "operations": [], + "options": [ + { + "id": "theme", + "titleZh": "主题", + "titleEn": "Theme", + "descriptionZh": "使用系统、BitFun 深色或 BitFun 浅色外观。", + "descriptionEn": "Use the system, BitFun dark, or BitFun light appearance.", + "valueSchema": { "type": "string", "enum": ["system", "bitfun-dark", "bitfun-light"] }, + "handler": { "kind": "appearanceSelection" } + }, + { + "id": "language", + "titleZh": "界面语言", + "titleEn": "Interface language", + "descriptionZh": "设置 BitFun 的界面语言。", + "descriptionEn": "Set the BitFun interface language.", + "valueSchema": { "type": "string", "enum": ["en-US", "zh-CN", "zh-TW"] }, + "handler": { "kind": "language" } + } + ] + }, + { + "id": "setting.application.pet", + "kind": "setting", + "categoryId": "application", + "titleZh": "桌面伙伴设置", + "titleEn": "Companion settings", + "summaryZh": "启用 Agent 伙伴、选择显示位置,并管理当前角色。", + "summaryEn": "Enable the agent companion, choose where it appears, and manage the active character.", + "keywordsZh": ["桌面伙伴设置", "桌面宠物", "显示位置", "Petdex"], + "keywordsEn": ["companion settings", "desktop pet", "display location", "Petdex"], + "highlightsZh": ["启用或停用伙伴", "桌面与输入框显示模式", "角色选择与 Petdex 导入"], + "highlightsEn": ["Enable or disable the companion", "Desktop and composer display modes", "Character selection and Petdex import"], + "items": [ + { "id": "enabled", "titleZh": "整体启用或停用 Agent 伙伴", "titleEn": "Enable or disable the agent companion", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.enable"] }, + { "id": "composer-display", "titleZh": "控制伙伴是否显示在聊天输入框旁", "titleEn": "Choose whether the companion appears beside the chat composer", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.displayInput"] }, + { "id": "desktop-display", "titleZh": "控制伙伴是否显示为独立桌面窗口", "titleEn": "Choose whether the companion appears as a standalone desktop window", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.displayDesktop"] }, + { "id": "preset-selection", "titleZh": "从内置与已导入角色中选择当前伙伴", "titleEn": "Choose the active companion from built-in and imported characters", "evidence": ["command:list_agent_companion_pets", "source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.petLabel"] }, + { "id": "import", "titleZh": "导入本地 Petdex 角色包", "titleEn": "Import a local Petdex character package", "evidence": ["command:import_agent_companion_pet_package"] }, + { "id": "delete-refresh", "titleZh": "刷新角色列表并删除不再需要的导入包", "titleEn": "Refresh the character list and delete imported packages you no longer need", "evidence": ["command:delete_agent_companion_pet_package", "source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.pet.refresh"] } + ], + "stepsZh": ["打开设置", "进入“应用 > 桌面伙伴”", "选择开关、位置和角色"], + "stepsEn": ["Open Settings", "Go to Application > Companion", "Choose its state, location, and character"], + "agentExamplesZh": ["关闭桌面伙伴", "把 Agent 伙伴放到输入框里"], + "agentExamplesEn": ["Turn off the desktop companion", "Put the agent companion in the composer"], + "destination": { "kind": "settings", "pageId": "application.pet" }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用桌面伙伴", + "titleEn": "Enable companion", + "descriptionZh": "显示或隐藏 Agent 伙伴。", + "descriptionEn": "Show or hide the agent companion.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["enable_agent_companion"] } + }, + { + "id": "display-mode", + "titleZh": "显示位置", + "titleEn": "Display location", + "descriptionZh": "在桌面或聊天输入框中显示。", + "descriptionEn": "Show on the desktop or in the chat composer.", + "valueSchema": { "type": "string", "enum": ["desktop", "input"] }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["agent_companion_display_mode"] } + } + ] + }, + { + "id": "setting.application.input", + "kind": "setting", + "categoryId": "application", + "titleZh": "输入与快捷键", + "titleEn": "Input & shortcuts", + "summaryZh": "配置语音输入、麦克风、识别语言以及键盘快捷键。", + "summaryEn": "Configure voice input, microphone, recognition language, and keyboard shortcuts.", + "keywordsZh": ["输入设置", "语音", "麦克风", "快捷键", "热键", "键位"], + "keywordsEn": ["input settings", "voice", "microphone", "shortcut", "hotkey", "keybinding"], + "highlightsZh": ["语音输入与本地模型", "识别语言和最长录音时间", "应用与编辑器快捷键"], + "highlightsEn": ["Voice input and local models", "Recognition language and maximum recording time", "App and editor shortcuts"], + "items": [ + { "id": "voice-enabled", "titleZh": "在聊天输入框启用或停用语音输入", "titleEn": "Enable or disable voice input in the chat composer", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#composer.enabled.label"] }, + { "id": "language", "titleZh": "选择自动检测或中文、粤语、英文、日文等识别语言", "titleEn": "Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#composer.language.label"] }, + { "id": "microphone-test", "titleZh": "选择麦克风并执行语音识别测试", "titleEn": "Choose a microphone and run a speech-recognition test", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#diagnostics.microphone.label", "source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#diagnostics.recognition.start"] }, + { "id": "local-models", "titleZh": "下载、选择、验证、修复或删除本地语音模型", "titleEn": "Download, select, verify, repair, or delete local speech models", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, "evidence": ["command:speech_download_model", "command:speech_verify_model", "command:speech_delete_model", "source:src/web-ui/src/locales/zh-CN/settings/voice-input.json#model.repair"] }, + { "id": "recording-limit", "titleZh": "设置单次语音输入的最长录音时间", "titleEn": "Set the maximum duration of one voice-input recording", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "voice" }, "evidence": ["source:src/web-ui/src/infrastructure/config/types/index.ts#max_recording_seconds"] }, + { "id": "shortcut-browser", "titleZh": "搜索和查看全部应用、场景、编辑器与终端快捷键", "titleEn": "Search and browse all app, scene, editor, and terminal shortcuts", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "shortcuts" }, "evidence": ["source:src/web-ui/src/app/scenes/settings/components/KeyboardShortcutsTab.tsx#lists every known shortcut"] }, + { "id": "shortcut-remap", "titleZh": "录制新快捷键、检测冲突、恢复单项或重置全部自定义键位", "titleEn": "Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings", "destination": { "kind": "settings", "pageId": "application.input", "viewId": "shortcuts" }, "evidence": ["source:src/web-ui/src/app/scenes/settings/components/KeyboardShortcutsTab.tsx#checkConflicts", "source:src/web-ui/src/app/scenes/settings/components/KeyboardShortcutsTab.tsx#buildStoredKeybindings({})"] } + ], + "stepsZh": ["打开设置", "进入“应用 > 输入”", "切换“语音”或“快捷键”视图"], + "stepsEn": ["Open Settings", "Go to Application > Input", "Switch between Voice and Shortcuts"], + "agentExamplesZh": ["打开快捷键设置", "把语音输入的默认语言设为中文"], + "agentExamplesEn": ["Open keyboard-shortcut settings", "Set the voice-input language to Chinese"], + "destination": { "kind": "settings", "pageId": "application.input" }, + "operations": [], + "options": [ + { + "id": "voice-enabled", + "titleZh": "启用语音输入", + "titleEn": "Enable voice input", + "descriptionZh": "在聊天输入框显示并启用录音入口。", + "descriptionEn": "Show and enable recording in the chat composer.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["voice_input.enabled"] } + }, + { + "id": "voice-language", + "titleZh": "默认识别语言", + "titleEn": "Default recognition language", + "descriptionZh": "选择自动检测、中文、英文、日文或粤语。", + "descriptionEn": "Choose automatic detection, Chinese, English, Japanese, or Cantonese.", + "valueSchema": { "type": "string", "enum": ["auto", "zh", "en", "ja", "yue"] }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["voice_input.default_language"] } + }, + { + "id": "max-recording-seconds", + "titleZh": "最长录音时间", + "titleEn": "Maximum recording duration", + "descriptionZh": "单次语音输入允许的最长秒数。", + "descriptionEn": "Maximum seconds allowed for one voice input.", + "valueSchema": { "type": "integer", "minimum": 10, "maximum": 600 }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["voice_input.max_recording_seconds"] } + } + ] + }, + { + "id": "setting.application.development", + "kind": "setting", + "categoryId": "application", + "titleZh": "终端与编辑器设置", + "titleEn": "Terminal & editor settings", + "summaryZh": "选择默认 Shell,并调整代码编辑器的字体、缩进、换行、格式化与 Minimap。", + "summaryEn": "Choose the default shell and tune editor font, indentation, wrapping, formatting, and minimap behavior.", + "keywordsZh": ["开发设置", "默认 Shell", "编辑器", "字体大小", "缩进", "自动换行", "Minimap"], + "keywordsEn": ["development settings", "default shell", "editor", "font size", "indentation", "word wrap", "minimap"], + "highlightsZh": ["默认终端 Shell", "编辑器字号与缩进", "自动换行、格式化和 Minimap"], + "highlightsEn": ["Default terminal shell", "Editor font size and indentation", "Word wrapping, formatting, and minimap"], + "items": [ + { "id": "default-shell", "titleZh": "自动检测并选择默认终端 Shell", "titleEn": "Automatically detect and choose the default terminal shell", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "terminal" }, "evidence": ["command:terminal_get_shells", "source:src/web-ui/src/locales/zh-CN/settings/application.json#terminal.sections.defaultTerminal"] }, + { "id": "terminal-position", "titleZh": "把终端面板放在右侧或底部", "titleEn": "Place the terminal panel on the right or at the bottom", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "terminal" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#terminal.panelPosition.label"] }, + { "id": "editor-appearance", "titleZh": "设置编辑器字体、字重、字号、行高与光标样式", "titleEn": "Configure editor font, weight, size, line height, and cursor style", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "editor" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/editor.json#appearance.fontSize", "source:src/web-ui/src/locales/zh-CN/settings/editor.json#appearance.cursorStyle"] }, + { "id": "indent-wrap", "titleZh": "设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动", "titleEn": "Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "editor" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/editor.json#behavior.tabSize", "source:src/web-ui/src/locales/zh-CN/settings/editor.json#behavior.wordWrap"] }, + { "id": "editor-display", "titleZh": "控制 Minimap、空白字符、当前行高亮和滚动边界", "titleEn": "Control the minimap, whitespace rendering, current-line highlight, and scroll bounds", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "editor" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/editor.json#display.minimap", "source:src/web-ui/src/locales/zh-CN/settings/editor.json#display.whitespace"] }, + { "id": "editor-advanced", "titleZh": "控制语义高亮、括号配色、保存/粘贴时格式化和空白清理", "titleEn": "Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming", "destination": { "kind": "settings", "pageId": "application.development", "viewId": "editor" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/editor.json#advanced.semanticHighlighting", "source:src/web-ui/src/locales/zh-CN/settings/editor.json#advanced.formatOnSave"] } + ], + "stepsZh": ["打开设置", "进入“应用 > 开发”", "切换“终端”或“编辑器”视图"], + "stepsEn": ["Open Settings", "Go to Application > Development", "Switch between Terminal and Editor"], + "agentExamplesZh": ["把编辑器字号改成 15", "打开终端设置"], + "agentExamplesEn": ["Set the editor font size to 15", "Open terminal settings"], + "destination": { "kind": "settings", "pageId": "application.development" }, + "operations": [], + "options": [ + { + "id": "editor-font-size", + "titleZh": "编辑器字号", + "titleEn": "Editor font size", + "descriptionZh": "设置代码编辑器的字体大小。", + "descriptionEn": "Set the code editor font size.", + "valueSchema": { "type": "integer", "minimum": 10, "maximum": 32 }, + "handler": { "kind": "config", "path": "editor.font_size" } + } + ] + }, + { + "id": "setting.ai.models", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "模型与供应商", + "titleEn": "Models & providers", + "summaryZh": "添加 AI 供应商和模型,选择默认模型,配置网络代理、订阅与流式超时。", + "summaryEn": "Add AI providers and models, choose defaults, and configure proxy, subscription, and streaming timeouts.", + "keywordsZh": ["模型设置", "供应商", "API Key", "默认模型", "代理", "订阅", "超时"], + "keywordsEn": ["model settings", "provider", "API key", "default model", "proxy", "subscription", "timeout"], + "highlightsZh": ["模型与供应商连接", "主模型、快速模型和任务模型", "代理、订阅与流式超时"], + "highlightsEn": ["Model and provider connections", "Primary, fast, and task-specific defaults", "Proxy, subscriptions, and streaming timeouts"], + "items": [ + { "id": "providers", "titleZh": "添加、编辑和删除内置或自定义 AI 供应商", "titleEn": "Add, edit, and remove built-in or custom AI providers", "evidence": ["command:get_model_configs", "command:refresh_model_client", "source:src/web-ui/src/locales/zh-CN/settings/models.json#providerSelection.customTitle"] }, + { "id": "credentials-endpoint", "titleZh": "配置 API Key、Base URL、请求格式和模型列表", "titleEn": "Configure API keys, base URLs, request formats, and model lists", "evidence": ["command:test_ai_config_connection", "source:src/web-ui/src/locales/zh-CN/settings/models.json#providerSelection.fetchModels"] }, + { "id": "subscription-auth", "titleZh": "登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户", "titleEn": "Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts", "evidence": ["command:start_subscription_login", "command:refresh_subscription_account", "command:logout_subscription_account", "command:list_subscription_accounts"] }, + { "id": "default-models", "titleZh": "选择主模型、快速模型以及图像理解、图像生成和语音识别模型", "titleEn": "Choose primary, fast, image-understanding, image-generation, and speech-recognition models", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/default-model.json#core.primary.label", "source:src/web-ui/src/locales/zh-CN/settings/default-model.json#optional.capabilities.image_generation.label"] }, + { "id": "reasoning", "titleZh": "为模型选择推理预设或自定义推理强度", "titleEn": "Choose reasoning presets or a custom reasoning effort per model", "evidence": ["command:project_ai_model_reasoning_catalog"] }, + { "id": "proxy", "titleZh": "配置 AI 请求使用的网络代理与绕过规则", "titleEn": "Configure network proxies and bypass rules for AI requests", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/default-model.json#sections.proxy"] }, + { "id": "stream-timeouts", "titleZh": "设置首 Token 等待和流式空闲超时", "titleEn": "Set time-to-first-token and streaming idle timeouts", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/models.json#streamIdleTimeout", "source:src/web-ui/src/locales/zh-CN/settings/models.json#streamTtftTimeout"] }, + { "id": "model-catalog", "titleZh": "查看 models.dev 目录状态、手动刷新并定位本地缓存", "titleEn": "Inspect models.dev catalog status, refresh it manually, and reveal its local cache", "evidence": ["command:get_models_dev_catalog_status", "command:refresh_models_dev_catalog_now", "command:reveal_models_dev_cache_directory"] }, + { "id": "advanced-request", "titleZh": "为供应商添加自定义 Header、请求体字段与 SSL 行为", "titleEn": "Add custom headers, request-body fields, and SSL behavior per provider", "evidence": ["source:src/web-ui/src/infrastructure/config/components/ModelSettingsPage.tsx#custom_headers", "source:src/web-ui/src/infrastructure/config/components/ModelSettingsPage.tsx#custom_request_body", "source:src/web-ui/src/infrastructure/config/components/ModelSettingsPage.tsx#skip_ssl_verify"] }, + { "id": "connection-test", "titleZh": "保存前测试供应商或模型连接并刷新运行时客户端", "titleEn": "Test provider or model connectivity before saving and refresh the runtime client", "evidence": ["command:test_ai_connection", "command:test_ai_config_connection", "command:refresh_model_client"] } + ], + "stepsZh": ["打开设置", "进入“AI > 模型”", "添加供应商并测试连接,再选择默认模型"], + "stepsEn": ["Open Settings", "Go to AI > Models", "Add and test a provider, then choose defaults"], + "agentExamplesZh": ["打开模型设置", "带我配置默认模型", "我想检查代理设置"], + "agentExamplesEn": ["Open model settings", "Take me to default-model setup", "I want to inspect proxy settings"], + "destination": { "kind": "settings", "pageId": "ai.models" }, + "operations": [], + "options": [] + }, + { + "id": "setting.ai.memory", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "记忆设置", + "titleEn": "Memory settings", + "summaryZh": "控制 BitFun 是否从会话中提取和使用长期记忆,以及保留、整理和模型策略。", + "summaryEn": "Control whether BitFun extracts and uses long-term memory from sessions, including retention, consolidation, and model policy.", + "keywordsZh": ["记忆设置", "长期记忆", "学习", "召回", "整理", "保留时间"], + "keywordsEn": ["memory settings", "long-term memory", "learning", "recall", "consolidation", "retention"], + "highlightsZh": ["启用记忆生成与召回", "BTW 会话与外部上下文策略", "提取、整理模型和后台并发"], + "highlightsEn": ["Enable memory generation and recall", "BTW sessions and external-context policy", "Extraction, consolidation models, and background concurrency"], + "items": [ + { "id": "generation-recall", "titleZh": "分别控制长期记忆生成与会话召回,也可一键同时启用", "titleEn": "Control long-term memory generation and recall independently or enable both together", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.generateMemories.label", "source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.useMemories.label"] }, + { "id": "btw", "titleZh": "决定 BTW 轻量会话是否参与记忆生成", "titleEn": "Choose whether lightweight BTW sessions contribute memories", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.generateForBtwSessions.label"] }, + { "id": "external-context", "titleZh": "存在外部工具上下文时选择清除工具结果、允许或跳过会话", "titleEn": "When external tool context exists, clear tool results, allow it, or skip the session", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.externalContextPolicy.label"] }, + { "id": "rollout-policy", "titleZh": "设置空闲时长、最大年龄、启动处理上限和扫描上限", "titleEn": "Set idle time, maximum age, startup rollout limit, and scan limit", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.minRolloutIdleHours.label", "source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.maxRolloutsPerStartup.label"] }, + { "id": "extraction", "titleZh": "选择记忆提取模型、并发数和单次原始候选上限", "titleEn": "Choose the extraction model, concurrency, and raw-candidate limit", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.extractModel.label", "source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.phase1MaxConcurrency.label"] }, + { "id": "retention", "titleZh": "设置未使用记忆的最长保留天数", "titleEn": "Set how long unused memories are retained", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.maxUnusedDays.label"] }, + { "id": "consolidation", "titleZh": "选择记忆整理模型并让它跟随主模型或提取模型", "titleEn": "Choose the consolidation model or make it follow the primary or extraction model", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/memory.json#fields.consolidationModel.label"] }, + { "id": "maintenance", "titleZh": "打开记忆目录、恢复默认设置或显式清空全部记忆", "titleEn": "Open the memory directory, restore defaults, or explicitly erase all memories", "evidence": ["command:get_memory_paths", "command:reset_memory", "source:src/web-ui/src/locales/zh-CN/settings/memory.json#actions.resetSettings"] } + ], + "stepsZh": ["打开设置", "进入“AI > 记忆”", "先启用记忆,再按需要调整高级参数"], + "stepsEn": ["Open Settings", "Go to AI > Memory", "Enable memory first, then tune advanced controls if needed"], + "agentExamplesZh": ["关闭长期记忆", "允许 BTW 会话生成记忆", "打开记忆设置"], + "agentExamplesEn": ["Turn off long-term memory", "Allow BTW sessions to generate memories", "Open Memory settings"], + "destination": { "kind": "settings", "pageId": "ai.memory" }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用记忆", + "titleEn": "Enable memory", + "descriptionZh": "同时启用记忆生成和召回。", + "descriptionEn": "Enable both memory generation and recall.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "memories", "fields": ["generate_memories", "use_memories"] } + }, + { + "id": "btw-sessions", + "titleZh": "BTW 会话生成记忆", + "titleEn": "Generate memory from BTW sessions", + "descriptionZh": "允许轻量 BTW 会话参与记忆提取。", + "descriptionEn": "Allow lightweight BTW sessions to contribute memories.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "memories", "fields": ["generate_for_btw_sessions"] } + }, + { + "id": "external-context-policy", + "titleZh": "外部上下文策略", + "titleEn": "External context policy", + "descriptionZh": "决定存在外部工具上下文时如何生成记忆。", + "descriptionEn": "Choose how memory generation handles external tool context.", + "valueSchema": { "type": "string", "enum": ["clear_tool_results", "allow", "skip_session"] }, + "handler": { "kind": "mergeConfig", "path": "memories", "fields": ["external_context_policy"] } + }, + { + "id": "startup-rollout-limit", + "titleZh": "每次启动整理上限", + "titleEn": "Startup rollout limit", + "descriptionZh": "每次启动最多处理的待整理记忆批次。", + "descriptionEn": "Maximum pending memory rollouts processed after startup.", + "valueSchema": { "type": "integer", "minimum": 0, "maximum": 100 }, + "handler": { "kind": "mergeConfig", "path": "memories", "fields": ["max_rollouts_per_startup"] } + } + ] + }, + { + "id": "setting.workspace.session", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "会话与工作区设置", + "titleEn": "Session & workspace settings", + "summaryZh": "控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。", + "summaryEn": "Control session-title generation, accelerated workspace search, and project-context behavior.", + "keywordsZh": ["会话设置", "工作区设置", "标题生成", "项目搜索", "索引"], + "keywordsEn": ["session settings", "workspace settings", "title generation", "project search", "index"], + "highlightsZh": ["自动生成会话标题", "本地工作区加速搜索", "会话使用的标题模型"], + "highlightsEn": ["Automatic session titles", "Accelerated local-workspace search", "Model used for session titles"], + "items": [ + { "id": "automatic-titles", "titleZh": "启用或停用根据会话内容自动生成标题", "titleEn": "Enable or disable automatic titles generated from session content", "evidence": ["command:generate_session_title", "source:src/web-ui/src/locales/zh-CN/settings/ai-features.json#features.sessionTitle.title"] }, + { "id": "title-model", "titleZh": "让标题模型继承主模型、快速模型或使用指定模型", "titleEn": "Make title generation inherit the primary or fast model, or use a selected model", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/models.json#sessionTitle.model.label"] }, + { "id": "accelerated-search", "titleZh": "为本地工作区启用 Flashgrep 加速搜索", "titleEn": "Enable Flashgrep-backed accelerated search for local workspaces", "evidence": ["command:search_build_index", "source:src/web-ui/src/locales/zh-CN/settings/runtime.json#features.workspaceSearch.enable"] }, + { "id": "search-index", "titleZh": "查看索引状态并在需要时重建工作区索引", "titleEn": "Inspect index status and rebuild the workspace index when needed", "evidence": ["command:search_get_repo_status", "command:search_rebuild_index"] }, + { "id": "remote-behavior", "titleZh": "远程工作区明确降级搜索实现,不把远程路径回退到本机", "titleEn": "Use an explicit remote-workspace search path without silently falling back to local files", "evidence": ["command:remote_execute", "command:remote_get_workspace_info"] } + ], + "stepsZh": ["打开设置", "进入“工作区 > 会话与工作区”", "调整标题或搜索选项"], + "stepsEn": ["Open Settings", "Go to Workspace > Session & Workspace", "Tune title or search controls"], + "agentExamplesZh": ["关闭自动生成会话标题", "启用工作区加速搜索"], + "agentExamplesEn": ["Turn off automatic session titles", "Enable accelerated workspace search"], + "destination": { "kind": "settings", "pageId": "workspace.session" }, + "operations": [], + "options": [ + { + "id": "session-title-generation", + "titleZh": "自动生成会话标题", + "titleEn": "Automatic session titles", + "descriptionZh": "根据会话内容生成易识别的标题。", + "descriptionEn": "Generate a recognizable title from session content.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["enable_session_title_generation"] } + }, + { + "id": "workspace-search", + "titleZh": "工作区加速搜索", + "titleEn": "Accelerated workspace search", + "descriptionZh": "为本地项目启用 Flashgrep 加速搜索。", + "descriptionEn": "Enable Flashgrep-backed search for local projects.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.ai_experience", "fields": ["enable_workspace_search"] } + } + ] + }, + { + "id": "setting.workspace.worktrees", + "kind": "setting", + "categoryId": "workspace", + "titleZh": "Worktree 设置", + "titleEn": "Worktree settings", + "summaryZh": "配置 Git Worktree 的根目录、分支前缀和自动清理规则,并查看现有隔离工作区。", + "summaryEn": "Configure the root, branch prefix, and cleanup rules for Git worktrees, and inspect existing isolated workspaces.", + "keywordsZh": ["Worktree 设置", "并行分支", "隔离工作区", "分支前缀", "自动清理"], + "keywordsEn": ["worktree settings", "parallel branch", "isolated workspace", "branch prefix", "automatic cleanup"], + "highlightsZh": ["Worktree 根目录与分支前缀", "自动清理数量", "现有 Worktree 和关联会话管理"], + "highlightsEn": ["Worktree root and branch prefix", "Automatic cleanup count", "Existing worktree and linked-session management"], + "items": [ + { "id": "isolation", "titleZh": "控制新会话是否默认使用独立 Git Worktree", "titleEn": "Choose whether new sessions use isolated Git worktrees by default", "evidence": ["source:src/web-ui/src/locales/zh-CN/worktrees.json#settings.isolation.title"] }, + { "id": "root-path", "titleZh": "设置受管 Worktree 的统一根目录", "titleEn": "Set the common root directory for managed worktrees", "evidence": ["source:src/web-ui/src/locales/zh-CN/worktrees.json#settings.rootPath.label"] }, + { "id": "branch-prefix", "titleZh": "设置自动创建分支使用的名称前缀", "titleEn": "Set the branch-name prefix used for automatically created branches", "evidence": ["source:src/web-ui/src/locales/zh-CN/worktrees.json#settings.branchPrefix.label"] }, + { "id": "copy-changes", "titleZh": "创建隔离工作区时选择是否复制当前未提交改动", "titleEn": "Choose whether current uncommitted changes are copied into a new isolated workspace", "evidence": ["source:src/web-ui/src/locales/zh-CN/worktrees.json#settings.copyChanges.label"] }, + { "id": "auto-cleanup", "titleZh": "启用自动清理并设置最多保留的受管 Worktree 数量", "titleEn": "Enable automatic cleanup and set the maximum number of managed worktrees to retain", "evidence": ["source:src/web-ui/src/locales/zh-CN/worktrees.json#settings.autoDeleteLimit.label"] }, + { "id": "management", "titleZh": "查看 Worktree 生命周期、脏状态、未发布提交与关联会话", "titleEn": "Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions", "evidence": ["command:worktree_list", "source:src/web-ui/src/locales/zh-CN/worktrees.json#management.state.unpublishedCommits"] }, + { "id": "open-restore-delete", "titleZh": "打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree", "titleEn": "Open or restore linked sessions and delete or force-delete a worktree after protection checks", "evidence": ["command:worktree_remove", "source:src/web-ui/src/locales/zh-CN/worktrees.json#management.sessions.restoreTitle", "source:src/web-ui/src/locales/zh-CN/worktrees.json#management.delete.forceTitle"] } + ], + "stepsZh": ["打开设置", "进入“工作区 > Worktrees”", "保存规则或管理现有 Worktree"], + "stepsEn": ["Open Settings", "Go to Workspace > Worktrees", "Save policy or manage existing worktrees"], + "agentExamplesZh": ["打开 Worktree 设置", "带我管理并行工作区"], + "agentExamplesEn": ["Open Worktree settings", "Take me to parallel-workspace management"], + "destination": { "kind": "settings", "pageId": "workspace.worktrees" }, + "operations": [], + "options": [] + }, + { + "id": "setting.tools.execution", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "执行与权限控制", + "titleEn": "Execution & permissions", + "summaryZh": "管理 Agent 工具权限、并行度、超时、延迟加载、Computer Use 与浏览器控制。", + "summaryEn": "Manage agent tool permissions, concurrency, timeouts, deferred loading, Computer Use, and browser control.", + "keywordsZh": ["执行控制", "工具权限", "审批", "并行", "超时", "Computer Use", "浏览器控制", "JSON 修复"], + "keywordsEn": ["execution control", "tool permissions", "approval", "parallel", "timeout", "computer use", "browser control", "JSON repair"], + "highlightsZh": ["询问、自动批准与完全访问策略", "子 Agent 并行度和工具超时", "Computer Use、浏览器连接与工具参数修复"], + "highlightsEn": ["Ask, auto-approve, and full-access policies", "Subagent concurrency and tool timeouts", "Computer Use, browser connection, and tool-argument repair"], + "items": [ + { "id": "permission-mode", "titleZh": "选择询问、自动批准或完全访问权限模式,并确认高风险警告", "titleEn": "Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#permissionPolicy.mode", "command:update_session_permission_mode"] }, + { "id": "permission-selector", "titleZh": "控制权限模式选择器是否显示在聊天输入框下方", "titleEn": "Choose whether the permission-mode selector appears below the chat composer", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#permissionPolicy.showInChatInput"] }, + { "id": "global-project-rules", "titleZh": "创建、排序和保存全局或项目级 Allow、Ask、Deny 规则", "titleEn": "Create, reorder, and save global or project-level Allow, Ask, and Deny rules", "evidence": ["command:get_project_permission_rules", "command:save_project_permission_rules", "source:src/web-ui/src/locales/zh-CN/settings/runtime.json#permissionPolicy.globalRules"] }, + { "id": "remembered-grants", "titleZh": "查看、撤销或清空项目中记住的权限授权与审计记录", "titleEn": "Review, revoke, or clear remembered project permission grants and audit records", "evidence": ["command:list_project_permission_grants", "command:remove_project_permission_grant", "command:clear_project_permission_grants", "command:list_project_permission_audit"] }, + { "id": "deferred-tools", "titleZh": "按需延迟加载大型工具定义以减少 Agent 初始上下文", "titleEn": "Load large tool definitions on demand to reduce initial agent context", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/runtime.json#deferredToolLoading.sectionTitle"] }, + { "id": "parallelism", "titleZh": "设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略", "titleEn": "Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/agentic-tools.json#config.subagentMaxConcurrency", "source:src/web-ui/src/locales/zh-CN/settings/agentic-tools.json#config.subagentBatchPolicy.label"] }, + { "id": "timeouts", "titleZh": "设置权限确认等待和单次工具执行超时", "titleEn": "Set permission-confirmation and per-tool execution timeouts", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/agentic-tools.json#config.confirmTimeout", "source:src/web-ui/src/locales/zh-CN/settings/agentic-tools.json#config.executionTimeout"] }, + { "id": "review-capacity", "titleZh": "设置 Deep Review 最大并行评审者和队列等待时间", "titleEn": "Set the maximum parallel Deep Review workers and queue wait time", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/review-capacity.json#capacity.maxParallelReviewers.label", "source:src/web-ui/src/locales/zh-CN/settings/review-capacity.json#capacity.maxQueueWaitSeconds.label"] }, + { "id": "computer-use", "titleZh": "启用 Computer Use 并查看辅助功能与屏幕录制权限", "titleEn": "Enable Computer Use and inspect accessibility and screen-recording permissions", "evidence": ["command:computer_use_get_status", "command:computer_use_request_permissions"] }, + { "id": "browser-control", "titleZh": "选择浏览器、配置默认 CDP 并控制启动时自动连接", "titleEn": "Choose a browser, configure default CDP, and control automatic connection at startup", "evidence": ["command:browser_control_list_browsers", "command:browser_control_enable_default_cdp", "source:src/web-ui/src/locales/zh-CN/settings/runtime.json#browserControl.autoConnectOnStartup"] }, + { "id": "json-repair", "titleZh": "控制是否在安全边界内修复模型生成的非法工具参数 JSON", "titleEn": "Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/models.json#toolArgumentJsonRepair.title"] } + ], + "stepsZh": ["打开设置", "进入“工具 > 执行与权限”", "先确认安全影响,再修改权限或执行参数"], + "stepsEn": ["Open Settings", "Go to Tools > Execution & Permissions", "Review the security impact before changing permissions or execution controls"], + "agentExamplesZh": ["启用 Computer Use", "把子 Agent 最大并发改为 8", "打开权限设置"], + "agentExamplesEn": ["Enable Computer Use", "Set maximum subagent concurrency to 8", "Open permission settings"], + "destination": { "kind": "settings", "pageId": "tools.execution" }, + "operations": [], + "options": [ + { + "id": "deferred-tool-loading", + "titleZh": "延迟加载工具", + "titleEn": "Deferred tool loading", + "descriptionZh": "按需加载大型工具定义,减少 Agent 初始上下文。", + "descriptionEn": "Load large tool definitions on demand to reduce initial agent context.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "ai.enable_deferred_tool_loading" } + }, + { + "id": "subagent-batch-policy", + "titleZh": "子 Agent 批量执行策略", + "titleEn": "Subagent batch policy", + "descriptionZh": "选择仅安全任务并行、强制并行或串行执行。", + "descriptionEn": "Choose safe-only parallelism, forced parallelism, or serial execution.", + "valueSchema": { "type": "string", "enum": ["safe_only", "force_parallel", "serial"] }, + "handler": { "kind": "config", "path": "ai.subagent_batch_execution_policy" } + }, + { + "id": "subagent-max-concurrency", + "titleZh": "子 Agent 最大并发", + "titleEn": "Maximum subagent concurrency", + "descriptionZh": "限制同时运行的子 Agent 数量。", + "descriptionEn": "Limit the number of subagents that may run at once.", + "valueSchema": { "type": "integer", "minimum": 1, "maximum": 32 }, + "handler": { "kind": "config", "path": "ai.subagent_max_concurrency" } + }, + { + "id": "swarm-max-concurrency", + "titleZh": "Swarm 最大并发", + "titleEn": "Maximum swarm concurrency", + "descriptionZh": "限制 Swarm 中同时执行的工作单元。", + "descriptionEn": "Limit concurrent work units inside a swarm.", + "valueSchema": { "type": "integer", "minimum": 1, "maximum": 64 }, + "handler": { "kind": "config", "path": "ai.swarm_max_concurrency" } + }, + { + "id": "tool-timeout-seconds", + "titleZh": "工具执行超时", + "titleEn": "Tool execution timeout", + "descriptionZh": "单次工具调用的超时秒数。", + "descriptionEn": "Timeout in seconds for one tool call.", + "valueSchema": { "type": "integer", "minimum": 1, "maximum": 86400 }, + "handler": { "kind": "config", "path": "ai.tool_execution_timeout_secs" } + }, + { + "id": "computer-use-enabled", + "titleZh": "Computer Use 桌面控制", + "titleEn": "Computer Use", + "descriptionZh": "允许 Agent 使用已授权的桌面控制能力。", + "descriptionEn": "Allow agents to use authorized desktop-control capabilities.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "ai.computer_use_enabled" } + }, + { + "id": "browser-auto-connect", + "titleZh": "启动时连接浏览器", + "titleEn": "Connect browser on startup", + "descriptionZh": "BitFun 启动后自动尝试连接浏览器控制。", + "descriptionEn": "Automatically try to connect browser control after BitFun starts.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "ai.browser_control_auto_connect_on_startup" } + }, + { + "id": "tool-json-repair", + "titleZh": "工具参数 JSON 修复", + "titleEn": "Tool-argument JSON repair", + "descriptionZh": "允许在安全边界内修复模型生成的轻微 JSON 格式错误。", + "descriptionEn": "Allow minor model-generated JSON formatting errors to be repaired within the safety boundary.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "ai.allow_tool_json_repair" } + } + ] + }, + { + "id": "setting.tools.automation", + "kind": "setting", + "categoryId": "automation", + "titleZh": "快捷操作与 Hooks", + "titleEn": "Quick actions & hooks", + "summaryZh": "自定义编码后的快捷操作,并配置在 Agent 生命周期事件上运行的 Hooks。", + "summaryEn": "Customize post-coding quick actions and configure hooks that run on agent lifecycle events.", + "keywordsZh": ["自动化设置", "快捷操作", "提交", "创建 PR", "Hooks", "生命周期"], + "keywordsEn": ["automation settings", "quick action", "commit", "create PR", "hooks", "lifecycle"], + "highlightsZh": ["编码后快捷操作", "内置提交与创建 PR 动作", "会话、工具与权限事件 Hooks"], + "highlightsEn": ["Post-coding quick actions", "Built-in commit and create-PR actions", "Hooks for session, tool, and permission events"], + "items": [ + { "id": "built-in-actions", "titleZh": "启用和调整内置的提交与创建 Pull Request 快捷操作", "titleEn": "Enable and tune the built-in Commit and Create Pull Request quick actions", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "quick-actions" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/quick-actions.json#quickActions.defaults.commit.label", "source:src/web-ui/src/locales/zh-CN/settings/quick-actions.json#quickActions.defaults.createPr.label"] }, + { "id": "custom-actions", "titleZh": "添加、编辑和删除自定义编码后快捷操作及 Prompt", "titleEn": "Add, edit, and delete custom post-coding quick actions and prompts", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "quick-actions" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/quick-actions.json#sections.custom.title", "source:src/web-ui/src/locales/zh-CN/settings/quick-actions.json#modal.promptField"] }, + { "id": "hooks-enabled", "titleZh": "整体启用或停用 Agent 生命周期 Hooks", "titleEn": "Enable or disable agent lifecycle hooks globally", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/hooks.json#fields.enabled.label"] }, + { "id": "project-hooks", "titleZh": "对可信仓库单独启用项目级 .bitfun/config/hooks.json", "titleEn": "Enable project-level .bitfun/config/hooks.json separately for trusted repositories", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/hooks.json#.bitfun/config/hooks.json"] }, + { "id": "hook-files", "titleZh": "定位用户级和项目级 Hooks 配置文件并在修改后即时生效", "titleEn": "Locate user and project hook configuration files and apply edits without restarting", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/hooks.json#修改 hooks.json 后立即生效"] }, + { "id": "hook-events", "titleZh": "在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器", "titleEn": "Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["source:docs/features/agent-hooks.md#Codex hook contract"] }, + { "id": "external-hooks", "titleZh": "查看外部 AI 应用的只读 Hook 目录并选择导入项", "titleEn": "Inspect read-only external-AI hook catalogs and choose entries to import", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["command:get_external_hook_catalog", "command:get_external_hook_import_snapshot"] }, + { "id": "hook-import", "titleZh": "预览、修改和应用 Hook 导入计划,并保留冲突诊断", "titleEn": "Preview, edit, and apply hook import plans while retaining conflict diagnostics", "destination": { "kind": "settings", "pageId": "tools.automation", "viewId": "hooks" }, "evidence": ["command:plan_external_hook_import_command", "command:mutate_external_hook_import_command", "command:apply_external_hook_import_command"] } + ], + "stepsZh": ["打开设置", "进入“工具 > 自动化”", "在“快捷操作”或“Hooks”中配置"], + "stepsEn": ["Open Settings", "Go to Tools > Automation", "Configure Quick Actions or Hooks"], + "agentExamplesZh": ["打开 Hooks 设置", "带我编辑编码后的快捷操作"], + "agentExamplesEn": ["Open Hooks settings", "Take me to post-coding quick actions"], + "destination": { "kind": "settings", "pageId": "tools.automation" }, + "operations": [], + "options": [ + { + "id": "hooks-enabled", + "titleZh": "启用 Hooks", + "titleEn": "Enable hooks", + "descriptionZh": "允许已配置的 Agent 生命周期 Hooks 运行。", + "descriptionEn": "Allow configured agent lifecycle hooks to run.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.hooks", "fields": ["enabled"] } + }, + { + "id": "project-hooks-enabled", + "titleZh": "启用项目 Hooks", + "titleEn": "Enable project hooks", + "descriptionZh": "允许当前项目中的 Hooks 配置生效。", + "descriptionEn": "Allow hook configuration from the current project.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "mergeConfig", "path": "app.hooks", "fields": ["project_hooks_enabled"] } + } + ] + }, + { + "id": "setting.tools.mcp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "MCP 服务器", + "titleEn": "MCP servers", + "summaryZh": "添加和管理 Model Context Protocol 服务器,查看工具、资源、提示词与远程授权状态。", + "summaryEn": "Add and manage Model Context Protocol servers, including tools, resources, prompts, and remote authorization state.", + "keywordsZh": ["MCP", "MCP 服务器", "工具服务器", "stdio", "SSE", "OAuth", "资源"], + "keywordsEn": ["MCP", "MCP server", "tool server", "stdio", "SSE", "OAuth", "resource"], + "highlightsZh": ["添加本地或远程 MCP 服务器", "查看连接健康与工具清单", "完成远程 OAuth 授权"], + "highlightsEn": ["Add local or remote MCP servers", "Inspect connection health and tool inventory", "Complete remote OAuth authorization"], + "items": [ + { "id": "json-config", "titleZh": "用表单或 JSON 查看和保存全部 MCP 服务器配置", "titleEn": "View and save all MCP server configuration through forms or JSON", "evidence": ["command:load_mcp_json_config", "command:save_mcp_json_config"] }, + { "id": "server-types", "titleZh": "添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器", "titleEn": "Add local-process, remote HTTP/SSE, or container MCP servers", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/mcp.json#server.typeLocal", "source:src/web-ui/src/locales/zh-CN/settings/mcp.json#server.typeRemote"] }, + { "id": "lifecycle", "titleZh": "启动、停止、重启和删除单个 MCP 服务器", "titleEn": "Start, stop, restart, and delete individual MCP servers", "evidence": ["command:start_mcp_server", "command:stop_mcp_server", "command:restart_mcp_server", "command:delete_mcp_server"] }, + { "id": "status", "titleZh": "查看初始化、连接、健康、重连、鉴权和失败状态", "titleEn": "Inspect initialization, connection, health, reconnecting, authentication, and failure states", "evidence": ["command:get_mcp_server_status", "command:get_mcp_servers"] }, + { "id": "remote-auth", "titleZh": "配置远程 Header/环境变量认证或清除已有凭据", "titleEn": "Configure remote header/environment authentication or clear stored credentials", "evidence": ["command:update_mcp_remote_auth", "command:clear_mcp_remote_auth"] }, + { "id": "oauth", "titleZh": "发起、轮询、取消或重新连接远程 MCP OAuth", "titleEn": "Start, poll, cancel, or reconnect remote MCP OAuth", "evidence": ["command:start_mcp_remote_oauth", "command:get_mcp_remote_oauth_session", "command:cancel_mcp_remote_oauth"] }, + { "id": "tools-prompts", "titleZh": "查看 MCP 工具、Prompt 列表并读取指定 Prompt", "titleEn": "Browse MCP tools and prompts and load a selected prompt", "evidence": ["command:list_mcp_prompts", "command:get_mcp_prompt", "command:get_mcp_tool_ui_uri"] }, + { "id": "resources", "titleZh": "列出、读取和打开 MCP Resources", "titleEn": "List, read, and open MCP resources", "evidence": ["command:list_mcp_resources", "command:read_mcp_resource", "command:fetch_mcp_app_resource"] }, + { "id": "mcp-apps", "titleZh": "打开 MCP App/UI、双向发送消息并回答交互请求", "titleEn": "Open MCP App/UI surfaces, exchange messages, and answer interaction requests", "evidence": ["command:send_mcp_app_message", "command:submit_mcp_interaction_response", "command:get_mcp_tool_ui_uri"] } + ], + "stepsZh": ["打开设置", "进入“工具 > MCP”", "添加服务器并确认其权限与连接状态"], + "stepsEn": ["Open Settings", "Go to Tools > MCP", "Add a server and review its permissions and connection state"], + "agentExamplesZh": ["打开 MCP 设置", "带我管理 MCP 服务器"], + "agentExamplesEn": ["Open MCP settings", "Take me to MCP server management"], + "destination": { "kind": "settings", "pageId": "tools.mcp" }, + "operations": [], + "options": [] + }, + { + "id": "setting.tools.acp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "ACP 外部 Agents", + "titleEn": "ACP external agents", + "summaryZh": "配置通过 Agent Client Protocol 接入的外部 Agent,并检查适配器、命令与会话选项。", + "summaryEn": "Configure external agents connected through Agent Client Protocol and inspect adapters, commands, and session options.", + "keywordsZh": ["ACP", "外部 Agent", "Agent Client Protocol", "OpenCode", "Claude Code", "Codex"], + "keywordsEn": ["ACP", "external agent", "Agent Client Protocol", "OpenCode", "Claude Code", "Codex"], + "highlightsZh": ["注册外部 Agent", "探测并安装 CLI 适配器", "配置 ACP 会话选项"], + "highlightsEn": ["Register external agents", "Probe and install CLI adapters", "Configure ACP session options"], + "items": [ + { "id": "presets", "titleZh": "使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设", "titleEn": "Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/acp-agents.json#presets.codex.description"] }, + { "id": "json-config", "titleZh": "通过 JSON 查看、添加和保存 ACP Agent 配置", "titleEn": "View, add, and save ACP agent configuration through JSON", "evidence": ["command:load_acp_json_config", "command:save_acp_json_config"] }, + { "id": "probe", "titleZh": "探测 CLI、适配器、路径、版本、连接与权限要求", "titleEn": "Probe CLI, adapter, path, version, connection, and permission requirements", "evidence": ["command:probe_acp_client_requirements", "command:get_acp_clients"] }, + { "id": "install", "titleZh": "安装外部 Agent CLI 并预下载 ACP 客户端适配器", "titleEn": "Install external-agent CLIs and predownload ACP client adapters", "evidence": ["command:install_acp_client_cli", "command:predownload_acp_client_adapter"] }, + { "id": "remote-detection", "titleZh": "在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因", "titleEn": "Detect available external agents in SSH workspaces and show explicit unsupported reasons", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/acp-agents.json#remote.refreshDetection"] }, + { "id": "session-model-options", "titleZh": "为 ACP 会话选择模型并修改客户端声明的配置选项", "titleEn": "Choose an ACP session model and edit client-declared configuration options", "evidence": ["command:get_acp_session_options", "command:set_acp_session_model", "command:set_acp_session_config_option"] }, + { "id": "session-commands", "titleZh": "查看并执行外部 Agent 暴露的会话命令", "titleEn": "Browse and run session commands exposed by an external agent", "evidence": ["command:get_acp_session_commands"] }, + { "id": "dialog-permissions", "titleZh": "开始或取消 ACP 对话,并远程回答外部 Agent 权限请求", "titleEn": "Start or cancel ACP turns and answer external-agent permission requests remotely", "evidence": ["command:start_acp_dialog_turn", "command:cancel_acp_dialog_turn", "command:submit_acp_permission_response"] } + ], + "stepsZh": ["打开设置", "进入“工具 > ACP”", "添加客户端并通过探测检查可用性"], + "stepsEn": ["Open Settings", "Go to Tools > ACP", "Add a client and probe its availability"], + "agentExamplesZh": ["打开 ACP 设置", "带我配置外部 Agent"], + "agentExamplesEn": ["Open ACP settings", "Take me to external-agent setup"], + "destination": { "kind": "settings", "pageId": "tools.acp" }, + "operations": [], + "options": [] + }, + { + "id": "setting.data.usage", + "kind": "setting", + "categoryId": "data", + "titleZh": "Token 用量", + "titleEn": "Token usage", + "summaryZh": "查看请求、输入输出 Token、缓存命中和估算成本等使用统计。", + "summaryEn": "Inspect request counts, input and output tokens, cache hits, and estimated cost statistics.", + "keywordsZh": ["Token 用量", "成本", "缓存", "请求统计", "用量历史"], + "keywordsEn": ["token usage", "cost", "cache", "request statistics", "usage history"], + "highlightsZh": ["按时间查看用量", "区分输入、输出与缓存 Token", "理解不同模型和会话的成本"], + "highlightsEn": ["Review usage over time", "Separate input, output, and cached tokens", "Understand cost by model and session"], + "items": [ + { "id": "time-range", "titleZh": "按最近 24 小时、今天、本周、本月或全部时间查看用量", "titleEn": "Review usage for the last 24 hours, today, this week, this month, or all time", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/usage.json#timeRange.last24Hours"] }, + { "id": "granularity", "titleZh": "按小时或天切换趋势粒度", "titleEn": "Switch trend granularity between hourly and daily views", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/usage.json#granularity.hour"] }, + { "id": "filter", "titleZh": "按供应商、模型或搜索关键词筛选用量", "titleEn": "Filter usage by provider, model, or search text", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/usage.json#filter.kind.provider"] }, + { "id": "summary", "titleZh": "查看请求数、总 Token、缓存 Token 与缓存命中率", "titleEn": "View request count, total tokens, cached tokens, and cache-hit rate", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/usage.json#summary.requests", "source:src/web-ui/src/locales/zh-CN/settings/usage.json#summary.cacheHitRate"] }, + { "id": "distribution", "titleZh": "按模型、供应商组和请求端点比较分布", "titleEn": "Compare distributions by model, provider group, and request endpoint", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/usage.json#distributions.byModel", "source:src/web-ui/src/locales/zh-CN/settings/usage.json#distributions.byEndpoint"] }, + { "id": "trend", "titleZh": "分别查看输入、输出、缓存创建、缓存读取和命中率趋势", "titleEn": "Track input, output, cache creation, cache read, and hit-rate trends separately", "evidence": ["command:get_token_usage_statistics", "source:src/web-ui/src/locales/zh-CN/settings/usage.json#trend.legend.cacheRead"] } + ], + "stepsZh": ["打开设置", "进入“数据 > 用量”", "选择时间范围并查看统计"], + "stepsEn": ["Open Settings", "Go to Data > Usage", "Choose a time range and inspect statistics"], + "agentExamplesZh": ["打开 Token 用量", "带我查看使用统计"], + "agentExamplesEn": ["Open Token usage", "Show me usage statistics"], + "destination": { "kind": "settings", "pageId": "data.usage" }, + "operations": [], + "options": [] + }, + { + "id": "setting.data.archived", + "kind": "setting", + "categoryId": "data", + "titleZh": "已归档会话", + "titleEn": "Archived sessions", + "summaryZh": "查找、恢复或永久删除已归档的会话,管理长期会话历史。", + "summaryEn": "Find, restore, or permanently delete archived sessions and manage long-term conversation history.", + "keywordsZh": ["已归档会话", "会话历史", "恢复会话", "取消归档", "删除历史"], + "keywordsEn": ["archived sessions", "session history", "restore session", "unarchive", "delete history"], + "highlightsZh": ["浏览归档会话", "恢复到原工作区", "显式永久删除历史"], + "highlightsEn": ["Browse archived sessions", "Restore to the original workspace", "Explicitly delete history permanently"], + "items": [ + { "id": "browse", "titleZh": "按工作区浏览分页归档会话及其元数据", "titleEn": "Browse paged archived sessions and metadata by workspace", "evidence": ["command:list_archived_sessions", "command:list_persisted_sessions_page"] }, + { "id": "search", "titleZh": "按标题、内容和工作区搜索已归档会话", "titleEn": "Search archived sessions by title, content, and workspace", "evidence": ["command:search_referenceable_sessions", "command:search_session_content"] }, + { "id": "restore", "titleZh": "恢复会话、轮次和原工作区视图并取消归档", "titleEn": "Restore a session, its turns, and original workspace view, then unarchive it", "evidence": ["command:restore_session", "command:restore_session_with_turns", "command:restore_session_view", "command:unarchive_session"] }, + { "id": "delete-selected", "titleZh": "明确确认后永久删除选中的归档会话", "titleEn": "Permanently delete a selected archived session after explicit confirmation", "evidence": ["command:delete_persisted_session"] }, + { "id": "delete-all", "titleZh": "明确确认后永久删除全部归档会话", "titleEn": "Permanently delete all archived sessions after explicit confirmation", "evidence": ["command:delete_all_archived_sessions"] } + ], + "stepsZh": ["打开设置", "进入“数据 > 已归档会话”", "选择会话后恢复或删除"], + "stepsEn": ["Open Settings", "Go to Data > Archived Sessions", "Choose a session to restore or delete"], + "agentExamplesZh": ["打开已归档会话", "带我恢复一个旧会话"], + "agentExamplesEn": ["Open archived sessions", "Take me to restore an old session"], + "destination": { "kind": "settings", "pageId": "data.archived" }, + "operations": [], + "options": [] + }, + { + "id": "setting.data.diagnostics", + "kind": "setting", + "categoryId": "data", + "titleZh": "日志与诊断", + "titleEn": "Logs & diagnostics", + "summaryZh": "调整日志级别,查看运行日志路径,并导出用于排查问题的诊断包。", + "summaryEn": "Adjust logging level, inspect runtime log locations, and export diagnostic bundles for troubleshooting.", + "keywordsZh": ["诊断", "日志", "调试", "日志级别", "诊断包", "故障排查"], + "keywordsEn": ["diagnostics", "logs", "debug", "log level", "diagnostic bundle", "troubleshooting"], + "highlightsZh": ["调整后端日志级别", "查看当前与上次异常退出日志", "导出诊断包并控制敏感信息"], + "highlightsEn": ["Adjust backend log level", "Inspect current and previous-crash logs", "Export bundles and control sensitive diagnostics"], + "items": [ + { "id": "log-level", "titleZh": "设置 Trace、Debug、Info、Warn、Error 或关闭后端日志", "titleEn": "Set backend logging to Trace, Debug, Info, Warn, Error, or Off", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#logging.levels.trace", "command:get_runtime_logging_info"] }, + { "id": "sensitive-diagnostics", "titleZh": "选择诊断中是否允许包含敏感上下文,并在导出前明确提示", "titleEn": "Choose whether diagnostics may include sensitive context, with an explicit warning before export", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#logging.sensitiveDiagnostics.label"] }, + { "id": "log-path", "titleZh": "查看日志路径并打开日志文件夹", "titleEn": "Inspect the log path and open the log folder", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#logging.actions.openFolder"] }, + { "id": "export-bundle", "titleZh": "导出包含系统、配置健康和日志信息的诊断包", "titleEn": "Export a diagnostics bundle containing system, configuration-health, and log information", "evidence": ["command:export_diagnostics_bundle", "command:get_system_info", "command:get_global_config_health"] }, + { "id": "crash-recovery", "titleZh": "查看上次崩溃、非正常退出、启动恢复和配置恢复信息", "titleEn": "Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery", "evidence": ["source:src/web-ui/src/locales/zh-CN/settings/application.json#logging.previousCrash.title", "source:src/web-ui/src/locales/zh-CN/settings/application.json#logging.startupRecovery.title"] }, + { "id": "devtools", "titleZh": "在开发构建中检查 DevTools 是否可用并打开或关闭", "titleEn": "In development builds, check DevTools availability and open or close them", "evidence": ["command:debug_devtools_available", "command:debug_open_devtools", "command:debug_close_devtools"] }, + { "id": "element-inspector", "titleZh": "在开发构建中启用主窗口元素检查并回传选中的元素", "titleEn": "In development builds, inspect main-window elements and report the selected element", "evidence": ["command:debug_element_picked", "source:src/web-ui/src/infrastructure/debug/mainWindowInspector.ts#debug_element_picked"] } + ], + "stepsZh": ["打开设置", "进入“数据 > 日志与诊断”", "选择日志级别,或按需导出诊断包"], + "stepsEn": ["Open Settings", "Go to Data > Logs & Diagnostics", "Choose a log level or export a bundle when needed"], + "agentExamplesZh": ["把日志级别改成 debug", "打开诊断设置", "带我导出诊断包"], + "agentExamplesEn": ["Set the log level to debug", "Open diagnostics settings", "Take me to export a diagnostic bundle"], + "destination": { "kind": "settings", "pageId": "data.diagnostics" }, + "operations": [], + "options": [ + { + "id": "log-level", + "titleZh": "日志级别", + "titleEn": "Log level", + "descriptionZh": "设置后端运行日志的详细程度。", + "descriptionEn": "Set the verbosity of backend runtime logs.", + "valueSchema": { "type": "string", "enum": ["error", "warn", "info", "debug", "trace"] }, + "handler": { "kind": "config", "path": "app.logging.level" } + }, + { + "id": "sensitive-diagnostics", + "titleZh": "诊断包包含敏感信息", + "titleEn": "Include sensitive diagnostics", + "descriptionZh": "仅在明确需要并理解隐私风险时启用。", + "descriptionEn": "Enable only when explicitly needed and after reviewing the privacy risk.", + "valueSchema": { "type": "boolean" }, + "handler": { "kind": "config", "path": "app.logging.include_sensitive_diagnostics" } + } + ] + } + ], + "productActionOwners": { + "session.new": "feature.ai-assistant", + "project.open": "feature.projects", + "project.new": "feature.projects", + "surface.browser.open": "feature.browser", + "surface.terminal.open": "feature.terminal", + "surface.files.open": "feature.files-editor", + "surface.agents.open": "feature.agents", + "surface.skills.open": "feature.skills", + "surface.ecosystemCompatibility.open": "feature.ecosystem-compatibility", + "surface.miniapps.open": "feature.miniapps", + "surface.todos.open": "feature.tasks-automation", + "surface.insights.open": "feature.insights", + "settings.open": "setting.application.general", + "settings.shortcuts.open": "setting.application.input" + }, + "sceneOwners": { + "welcome": "feature.ai-assistant", + "session": "feature.ai-assistant", + "terminal": "feature.terminal", + "git": "feature.git", + "settings": "setting.application.general", + "file-viewer": "feature.files-editor", + "profile": "feature.personal-assistants", + "agents": "feature.agents", + "skills": "feature.skills", + "ecosystem-compatibility": "feature.ecosystem-compatibility", + "miniapps": "feature.miniapps", + "pages": "feature.pages", + "browser": "feature.browser", + "assistant": "feature.personal-assistants", + "todos": "feature.tasks-automation", + "insights": "feature.insights", + "shell": "feature.terminal", + "panel-view": "feature.canvas" + }, + "implementationOwners": { + "commands": { "capabilityId": "feature.projects", "reviewedCommandCount": 78 }, + "agentic": { "capabilityId": "feature.ai-assistant", "reviewedCommandCount": 53 }, + "remote_connect": { "capabilityId": "feature.remote-connect", "reviewedCommandCount": 41 }, + "miniapp": { "capabilityId": "feature.miniapps", "reviewedCommandCount": 39 }, + "ssh": { "capabilityId": "feature.remote-workspaces", "reviewedCommandCount": 33 }, + "git": { "capabilityId": "feature.git", "reviewedCommandCount": 31 }, + "external_sources": { "capabilityId": "feature.ecosystem-compatibility", "reviewedCommandCount": 25 }, + "snapshot_service": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 24 }, + "lsp_workspace": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 24 }, + "mcp": { "capabilityId": "setting.tools.mcp", "reviewedCommandCount": 23 }, + "config": { "capabilityId": "setting.application.general", "reviewedCommandCount": 19 }, + "session": { "capabilityId": "feature.ai-assistant", "reviewedCommandCount": 19 }, + "lsp": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 19 }, + "dispatch": { "capabilityId": "feature.detached-dispatch", "reviewedCommandCount": 18 }, + "system": { "capabilityId": "setting.application.general", "reviewedCommandCount": 17 }, + "miniapp_market": { "capabilityId": "feature.miniapps", "reviewedCommandCount": 17 }, + "acp_client": { "capabilityId": "setting.tools.acp", "reviewedCommandCount": 16 }, + "terminal": { "capabilityId": "feature.terminal", "reviewedCommandCount": 14 }, + "skill": { "capabilityId": "feature.skills", "reviewedCommandCount": 13 }, + "subagent": { "capabilityId": "feature.agents", "reviewedCommandCount": 10 }, + "pages": { "capabilityId": "feature.pages", "reviewedCommandCount": 10 }, + "review_platform": { "capabilityId": "feature.code-review", "reviewedCommandCount": 10 }, + "appearance_market": { "capabilityId": "setting.application.appearance", "reviewedCommandCount": 9 }, + "speech": { "capabilityId": "feature.voice-input", "reviewedCommandCount": 9 }, + "worktree": { "capabilityId": "feature.git", "reviewedCommandCount": 8 }, + "relay_deploy": { "capabilityId": "feature.remote-connect", "reviewedCommandCount": 7 }, + "browser": { "capabilityId": "feature.browser", "reviewedCommandCount": 7 }, + "storage_commands": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 6 }, + "announcement": { "capabilityId": "setting.application.general", "reviewedCommandCount": 6 }, + "tool": { "capabilityId": "feature.ai-assistant", "reviewedCommandCount": 6 }, + "external_hooks": { "capabilityId": "feature.ecosystem-compatibility", "reviewedCommandCount": 5 }, + "browser_control": { "capabilityId": "feature.computer-use", "reviewedCommandCount": 5 }, + "insights": { "capabilityId": "feature.insights", "reviewedCommandCount": 5 }, + "cron": { "capabilityId": "feature.tasks-automation", "reviewedCommandCount": 5 }, + "custom_agent": { "capabilityId": "feature.agents", "reviewedCommandCount": 5 }, + "i18n": { "capabilityId": "setting.application.appearance", "reviewedCommandCount": 5 }, + "miniapp_agent": { "capabilityId": "feature.miniapps", "reviewedCommandCount": 5 }, + "peer_host_invoke": { "capabilityId": "feature.remote-connect", "reviewedCommandCount": 5 }, + "debug": { "capabilityId": "setting.data.diagnostics", "reviewedCommandCount": 4 }, + "appearance": { "capabilityId": "feature.desktop-pet", "reviewedCommandCount": 4 }, + "canvas": { "capabilityId": "feature.canvas", "reviewedCommandCount": 4 }, + "diff": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 3 }, + "computer_use": { "capabilityId": "feature.computer-use", "reviewedCommandCount": 3 }, + "git_agent": { "capabilityId": "feature.code-review", "reviewedCommandCount": 3 }, + "lib": { "capabilityId": null, "reviewedCommandCount": 3 }, + "search": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 3 }, + "btw": { "capabilityId": "feature.ai-assistant", "reviewedCommandCount": 2 }, + "editor_ai": { "capabilityId": "feature.ai-assistant", "reviewedCommandCount": 2 }, + "clipboard_file": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 2 }, + "sleep_prevention": { "capabilityId": "setting.application.general", "reviewedCommandCount": 2 }, + "runtime": { "capabilityId": null, "reviewedCommandCount": 1 }, + "token_usage": { "capabilityId": "feature.insights", "reviewedCommandCount": 1 }, + "miniapp_export": { "capabilityId": "feature.miniapps", "reviewedCommandCount": 1 }, + "bitfun_control_host": { "capabilityId": null, "reviewedCommandCount": 2 }, + "context_upload": { "capabilityId": "feature.files-editor", "reviewedCommandCount": 1 } + } +} diff --git a/src/web-ui/src/app/App.tsx b/src/web-ui/src/app/App.tsx index 145df164ce..627f21e26d 100644 --- a/src/web-ui/src/app/App.tsx +++ b/src/web-ui/src/app/App.tsx @@ -92,6 +92,7 @@ function App() { const userCloseRequestedRef = useRef(false); const interactiveShellReadyRef = useRef(false); const interactiveShellReadyFrameRef = useRef(null); + const bitFunControlStartupRef = useRef(false); const workspaceLoadingRef = useRef(workspaceLoading); const appLayoutReadyRef = useRef(false); const [interactiveShellReady, setInteractiveShellReady] = useState(false); @@ -324,6 +325,26 @@ function App() { return () => window.clearTimeout(timer); }, [verifyMainWindowVisible]); + // Register the control listener as soon as the product surface is usable. + // The backend does not expose BitFunControl until this readiness handshake succeeds. + useEffect(() => { + if ( + !isTauriRuntime() + || !shouldScheduleDeferredStartupSystems({ interactiveShellReady, startupOverlayVisible }) + || bitFunControlStartupRef.current + ) { + return; + } + bitFunControlStartupRef.current = true; + void import('./global-search/bitfunControlBridge') + .then(({ initializeBitFunControlBridge }) => initializeBitFunControlBridge()) + .then(() => startupTrace.markPhase('bitfun_control_surface_ready')) + .catch(error => { + bitFunControlStartupRef.current = false; + log.error('Failed to initialize the BitFun control surface', error); + }); + }, [interactiveShellReady, startupOverlayVisible]); + // Non-critical systems are delayed until the shell is interactive and the // startup overlay has fully handed off to the app surface. useEffect(() => { diff --git a/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx b/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx index 9641ed9da2..7d8327cb5f 100644 --- a/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx +++ b/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx @@ -139,14 +139,29 @@ const PersistentFooterActions: React.FC = () => { return; } + setRemoteInitialGroup(undefined); setShowRemoteDisclaimer(true); }, [hasAgreedRemoteDisclaimer]); + useEffect(() => { + const handlePlaybookOpen = (event: Event) => { + const requestedGroup = (event as CustomEvent<{ group?: 'network' | 'bot' | 'account' }>).detail?.group; + setRemoteInitialGroup(requestedGroup); + if (hasAgreedRemoteDisclaimer || getRemoteConnectDisclaimerAgreed()) { + setHasAgreedRemoteDisclaimer(true); + setShowRemoteConnect(true); + } else { + setShowRemoteDisclaimer(true); + } + }; + window.addEventListener('bitfun:open-remote-connect', handlePlaybookOpen); + return () => window.removeEventListener('bitfun:open-remote-connect', handlePlaybookOpen); + }, [hasAgreedRemoteDisclaimer]); + const handleAgreeDisclaimer = useCallback(() => { setRemoteConnectDisclaimerAgreed(); setHasAgreedRemoteDisclaimer(true); setShowRemoteDisclaimer(false); - setRemoteInitialGroup(undefined); setShowRemoteConnect(true); }, []); diff --git a/src/web-ui/src/app/global-search/GlobalSearchRoot.tsx b/src/web-ui/src/app/global-search/GlobalSearchRoot.tsx index f53e56173e..e25bc2c48b 100644 --- a/src/web-ui/src/app/global-search/GlobalSearchRoot.tsx +++ b/src/web-ui/src/app/global-search/GlobalSearchRoot.tsx @@ -102,6 +102,7 @@ const GROUP_ICONS: Record, LucideIcon> = files: FileText, workspaces: FolderOpen, assistants: Bot, + capabilities: Blocks, settings: SlidersHorizontal, }; diff --git a/src/web-ui/src/app/global-search/bitfunControlBridge.test.ts b/src/web-ui/src/app/global-search/bitfunControlBridge.test.ts new file mode 100644 index 0000000000..ae62f4cca3 --- /dev/null +++ b/src/web-ui/src/app/global-search/bitfunControlBridge.test.ts @@ -0,0 +1,184 @@ +import { appearanceService } from '@/infrastructure/appearance'; +import { configManager } from '@/infrastructure/config'; +import { i18nService } from '@/infrastructure/i18n'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { INTERACTIVE_CAPABILITY_CATALOG } from './interactiveCapabilityCatalog'; +import { + discoverBitFunCapabilities, + executeBitFunControlRequest, +} from './bitfunControlBridge'; + +const mocks = vi.hoisted(() => ({ + activateInteractiveCapability: vi.fn(), +})); + +vi.mock('./interactiveCapabilityActivator', () => ({ + activateInteractiveCapability: mocks.activateInteractiveCapability, +})); + +describe('BitFunControl discovery', () => { + afterEach(() => { + vi.clearAllMocks(); + vi.restoreAllMocks(); + }); + + it('lists the shared catalog with bounded pagination', () => { + const result = discoverBitFunCapabilities({ + requestId: 'test', + action: 'list', + }) as { items: unknown[]; totalCount: number; nextCursor: number | null }; + expect(result.items).toHaveLength(INTERACTIVE_CAPABILITY_CATALOG.counts.userFacing); + expect(result.totalCount).toBe(INTERACTIVE_CAPABILITY_CATALOG.capabilities.length); + expect(result.nextCursor).toBeNull(); + }); + + it('searches Chinese and English against the same source', () => { + const english = discoverBitFunCapabilities({ + requestId: 'en', + action: 'search', + query: 'terminal', + }) as { items: Array<{ id: string }> }; + const chinese = discoverBitFunCapabilities({ + requestId: 'zh', + action: 'search', + query: '终端', + }) as { items: Array<{ id: string }> }; + expect(english.items.some(({ id }) => id === 'feature.terminal')).toBe(true); + expect(chinese.items.some(({ id }) => id === 'feature.terminal')).toBe(true); + }); + + it('returns matching documented sub-capabilities without loading the full catalog into the tool prompt', () => { + const result = discoverBitFunCapabilities({ + requestId: 'browser-picker', + action: 'search', + query: '元素选择器', + }) as { items: Array<{ id: string; matchedItems: Array<{ id: string }> }> }; + const browser = result.items.find(({ id }) => id === 'feature.browser'); + expect(browser?.matchedItems.some(({ id }) => id === 'element-picker')).toBe(true); + }); + + it('returns the on-demand shared browser control workflow to the agent', async () => { + const result = await executeBitFunControlRequest({ + requestId: 'get-browser-control', + action: 'get', + capabilityId: 'feature.browser', + }) as { + capability: { + agentControl?: { tool: string; workflowZh: string[]; workflowEn: string[] }; + }; + }; + expect(result.capability.agentControl?.tool).toBe('ControlHub'); + expect(result.capability.agentControl?.workflowZh.join(' ')).toContain('browser.open_builtin'); + expect(result.capability.agentControl?.workflowEn.join(' ')).toContain('external CDP contract'); + }); + + it('discovers personal-assistant configuration as its own user feature', () => { + const result = discoverBitFunCapabilities({ + requestId: 'assistant-persona', + action: 'search', + query: 'IDENTITY.md', + }) as { items: Array<{ id: string; matchedItems: Array<{ id: string }> }> }; + const assistant = result.items.find(({ id }) => id === 'feature.personal-assistants'); + expect(assistant).toBeDefined(); + expect(assistant?.matchedItems.some(({ id }) => id === 'persona-documents')).toBe(true); + }); + + it('never lists raw Tauri commands as user capabilities', () => { + const result = discoverBitFunCapabilities({ + requestId: 'semantic', + action: 'list', + }) as { items: Array<{ id: string; kind: string }> }; + expect(result.items.every(({ id, kind }) => + /^(feature|setting)\./.test(id) && ['feature', 'setting'].includes(kind))).toBe(true); + expect(result.items.some(({ id }) => id === 'get_configs')).toBe(false); + }); + + it('opens the exact documented item returned by discovery', async () => { + await executeBitFunControlRequest({ + requestId: 'open-shortcuts', + action: 'open', + capabilityId: 'setting.application.input', + itemId: 'shortcut-browser', + }); + expect(mocks.activateInteractiveCapability).toHaveBeenCalledWith( + 'setting.application.input', + { itemId: 'shortcut-browser' }, + ); + }); + + it('returns one public setting contract without leaking internal handlers', async () => { + vi.spyOn(appearanceService, 'initialize').mockResolvedValue(undefined); + vi.spyOn(appearanceService, 'getSnapshot').mockReturnValue({ + ...appearanceService.getSnapshot(), + selectedAppearanceId: 'system', + }); + vi.spyOn(i18nService, 'getCurrentLocale').mockReturnValue('zh-CN'); + const result = await executeBitFunControlRequest({ + requestId: 'get-setting', + action: 'get', + capabilityId: 'setting.application.appearance', + }) as { capability: { items: Array<{ id: string }> }; currentOptionValues: Record }; + expect(JSON.stringify(result.capability)).not.toContain('handler'); + expect(JSON.stringify(result.capability)).not.toContain('appearance.selection'); + expect(result.currentOptionValues).toEqual({ theme: 'system', language: 'zh-CN' }); + expect(result.capability.items.length).toBeGreaterThanOrEqual(4); + }); + + it('configures only an option resolved from the semantic catalog', async () => { + const select = vi.spyOn(appearanceService, 'select').mockResolvedValue(undefined); + vi.spyOn(appearanceService, 'initialize').mockResolvedValue(undefined); + vi.spyOn(appearanceService, 'getSnapshot').mockReturnValue({ + ...appearanceService.getSnapshot(), + selectedAppearanceId: 'bitfun-dark', + }); + const result = await executeBitFunControlRequest({ + requestId: 'configure-theme', + action: 'configure', + capabilityId: 'setting.application.appearance', + optionId: 'theme', + value: 'bitfun-dark', + }) as { effectiveValue: unknown }; + expect(select).toHaveBeenCalledWith('bitfun-dark'); + expect(result.effectiveValue).toBe('bitfun-dark'); + await expect(executeBitFunControlRequest({ + requestId: 'raw-command', + action: 'configure', + capabilityId: 'set_config', + optionId: 'anything', + value: true, + })).rejects.toThrow('Unknown BitFun capability'); + }); + + it('merges grouped settings without overwriting sibling values', async () => { + vi.spyOn(configManager, 'getOptionalConfig').mockResolvedValue({ + enable_agent_companion: true, + agent_companion_display_mode: 'desktop', + }); + const setConfig = vi.spyOn(configManager, 'setConfig').mockResolvedValue(undefined); + await executeBitFunControlRequest({ + requestId: 'configure-companion', + action: 'configure', + capabilityId: 'setting.application.pet', + optionId: 'display-mode', + value: 'input', + }); + expect(setConfig).toHaveBeenCalledWith('app.ai_experience', { + enable_agent_companion: true, + agent_companion_display_mode: 'input', + }); + }); + + it('changes language through the live i18n service', async () => { + const changeLanguage = vi.spyOn(i18nService, 'changeLanguage').mockResolvedValue(undefined); + vi.spyOn(i18nService, 'getCurrentLocale').mockReturnValue('en-US'); + const result = await executeBitFunControlRequest({ + requestId: 'configure-language', + action: 'configure', + capabilityId: 'setting.application.appearance', + optionId: 'language', + value: 'en-US', + }) as { effectiveValue: unknown }; + expect(changeLanguage).toHaveBeenCalledWith('en-US'); + expect(result.effectiveValue).toBe('en-US'); + }); +}); diff --git a/src/web-ui/src/app/global-search/bitfunControlBridge.ts b/src/web-ui/src/app/global-search/bitfunControlBridge.ts new file mode 100644 index 0000000000..48a6e64f20 --- /dev/null +++ b/src/web-ui/src/app/global-search/bitfunControlBridge.ts @@ -0,0 +1,330 @@ +import { api } from '@/infrastructure/api/service-api/ApiClient'; +import { appearanceService } from '@/infrastructure/appearance'; +import { configManager } from '@/infrastructure/config'; +import { i18nService, type LocaleId } from '@/infrastructure/i18n'; +import { createLogger } from '@/shared/utils/logger'; +import { activateInteractiveCapability } from './interactiveCapabilityActivator'; +import { activateProductAction } from './productActionActivator'; +import { + getInteractiveCapability, + INTERACTIVE_CAPABILITY_CATALOG, + type InteractiveCapability, + type InteractiveCapabilityOption, + type InteractiveCapabilityValueSchema, +} from './interactiveCapabilityCatalog'; +import { scoreTextMatch } from './searchMatching'; + +const log = createLogger('BitFunControlBridge'); +const REQUEST_EVENT = 'agentic://bitfun-control-request'; +const DEFAULT_SEARCH_LIMIT = 20; +const MAX_LIMIT = 50; + +type BitFunControlAction = 'list' | 'search' | 'get' | 'open' | 'execute' | 'configure'; + +export interface BitFunControlRequest { + requestId: string; + action: BitFunControlAction; + query?: string; + capabilityId?: string; + itemId?: string; + operationId?: string; + optionId?: string; + value?: unknown; + cursor?: number; + limit?: number; +} + +interface BitFunControlResponse { + requestId: string; + success: boolean; + result?: unknown; + error?: string; +} + +let unlisten: (() => void) | null = null; + +function compactCapability(capability: InteractiveCapability, query = '') { + const matchingItems = query + ? capability.items + .map((item) => ({ item, score: scoreTextMatch(query, [item.titleZh, item.titleEn]) })) + .filter(({ score }) => score > 0) + .sort((left, right) => right.score - left.score) + .slice(0, 5) + .map(({ item }) => item) + : []; + return { + id: capability.id, + kind: capability.kind, + titleZh: capability.titleZh, + titleEn: capability.titleEn, + summaryZh: capability.summaryZh, + summaryEn: capability.summaryEn, + categoryId: capability.categoryId, + operationCount: capability.operations.length, + configurableOptionCount: capability.options.length, + documentedItemCount: capability.items.length, + matchedItems: matchingItems, + }; +} + +function publicCapability(capability: InteractiveCapability) { + return { + id: capability.id, + kind: capability.kind, + titleZh: capability.titleZh, + titleEn: capability.titleEn, + summaryZh: capability.summaryZh, + summaryEn: capability.summaryEn, + categoryId: capability.categoryId, + highlightsZh: capability.highlightsZh, + highlightsEn: capability.highlightsEn, + stepsZh: capability.stepsZh, + stepsEn: capability.stepsEn, + agentExamplesZh: capability.agentExamplesZh, + agentExamplesEn: capability.agentExamplesEn, + agentControl: capability.agentControl, + items: capability.items, + destination: capability.destination, + operations: capability.operations.map(({ handler: _handler, ...operation }) => operation), + options: capability.options.map(({ handler: _handler, ...option }) => option), + docsUrl: capability.docsUrl, + }; +} + +function pagination(request: BitFunControlRequest) { + const cursor = Number.isInteger(request.cursor) && (request.cursor ?? 0) >= 0 + ? request.cursor ?? 0 + : 0; + const defaultLimit = request.action === 'list' ? MAX_LIMIT : DEFAULT_SEARCH_LIMIT; + const requestedLimit = Number.isInteger(request.limit) ? request.limit ?? defaultLimit : defaultLimit; + return { cursor, limit: Math.min(MAX_LIMIT, Math.max(1, requestedLimit)) }; +} + +export function discoverBitFunCapabilities(request: BitFunControlRequest): unknown { + const { cursor, limit } = pagination(request); + const query = request.query?.trim() ?? ''; + const matches = INTERACTIVE_CAPABILITY_CATALOG.capabilities + .map((capability) => ({ + capability, + score: request.action === 'search' + ? scoreTextMatch(query, [ + capability.id, + capability.titleZh, + capability.titleEn, + ...capability.searchTerms, + ]) + : 1, + })) + .filter(({ score }) => score > 0) + .sort((left, right) => right.score - left.score + || left.capability.kind.localeCompare(right.capability.kind) + || left.capability.id.localeCompare(right.capability.id)); + const items = matches.slice(cursor, cursor + limit) + .map(({ capability }) => compactCapability(capability, query)); + const nextCursor = cursor + items.length < matches.length ? cursor + items.length : null; + return { + catalogDigest: INTERACTIVE_CAPABILITY_CATALOG.digest, + counts: INTERACTIVE_CAPABILITY_CATALOG.counts, + totalCount: matches.length, + cursor, + nextCursor, + items, + }; +} + +function errorMessage(error: unknown): string { + if (error instanceof Error && error.message.trim()) return error.message; + if (typeof error === 'string' && error.trim()) return error; + return 'BitFunControl request failed'; +} + +function valuesEqual(left: unknown, right: unknown): boolean { + return JSON.stringify(left) === JSON.stringify(right); +} + +function readNestedValue(value: unknown, field: string): unknown { + let current = value; + for (const segment of field.split('.')) { + if (!current || typeof current !== 'object' || Array.isArray(current)) return undefined; + current = (current as Record)[segment]; + } + return current; +} + +function setNestedValue( + value: Record, + field: string, + nextValue: unknown, +): Record { + const [head, ...tail] = field.split('.'); + if (!head) return value; + if (tail.length === 0) return { ...value, [head]: nextValue }; + const child = value[head]; + const childRecord = child && typeof child === 'object' && !Array.isArray(child) + ? child as Record + : {}; + return { + ...value, + [head]: setNestedValue(childRecord, tail.join('.'), nextValue), + }; +} + +function assertValueMatchesSchema(value: unknown, schema: InteractiveCapabilityValueSchema): void { + const typeMatches = (() => { + switch (schema.type) { + case 'boolean': return typeof value === 'boolean'; + case 'string': return typeof value === 'string'; + case 'integer': return typeof value === 'number' && Number.isInteger(value); + case 'number': return typeof value === 'number' && Number.isFinite(value); + case 'object': return !!value && typeof value === 'object' && !Array.isArray(value); + case 'array': return Array.isArray(value); + } + })(); + if (!typeMatches) throw new Error(`value must match type ${schema.type}`); + if (schema.enum && !schema.enum.some((candidate) => valuesEqual(candidate, value))) { + throw new Error(`value must be one of: ${schema.enum.map(String).join(', ')}`); + } + if (typeof value === 'number' && schema.minimum !== undefined && value < schema.minimum) { + throw new Error(`value must be at least ${schema.minimum}`); + } + if (typeof value === 'number' && schema.maximum !== undefined && value > schema.maximum) { + throw new Error(`value must be at most ${schema.maximum}`); + } +} + +async function currentOptionValue(option: InteractiveCapabilityOption): Promise { + if (option.handler.kind === 'appearanceSelection') { + await appearanceService.initialize(); + return appearanceService.getSnapshot().selectedAppearanceId; + } + if (option.handler.kind === 'language') return i18nService.getCurrentLocale(); + const current = await configManager.getOptionalConfig(option.handler.path); + if (option.handler.kind === 'config') return current; + const values = option.handler.fields.map((field) => readNestedValue(current, field)); + if (values.length === 1 || values.every((value) => valuesEqual(value, values[0]))) return values[0]; + return Object.fromEntries(option.handler.fields.map((field, index) => [field, values[index]])); +} + +async function inspectCapability(capability: InteractiveCapability): Promise { + const optionValues = Object.fromEntries(await Promise.all(capability.options.map(async (option) => [ + option.id, + await currentOptionValue(option).catch(() => undefined), + ] as const))); + return { + catalogDigest: INTERACTIVE_CAPABILITY_CATALOG.digest, + capability: publicCapability(capability), + currentOptionValues: optionValues, + }; +} + +async function configureOption(option: InteractiveCapabilityOption, value: unknown): Promise { + assertValueMatchesSchema(value, option.valueSchema); + if (option.handler.kind === 'appearanceSelection') { + await appearanceService.select(value as string); + return; + } + if (option.handler.kind === 'language') { + await i18nService.changeLanguage(value as LocaleId); + return; + } + if (option.handler.kind === 'config') { + await configManager.setConfig(option.handler.path, value); + return; + } + const loaded = await configManager.getOptionalConfig(option.handler.path); + const current = loaded as Record | null | undefined; + let next = current && typeof current === 'object' && !Array.isArray(current) ? current : {}; + for (const field of option.handler.fields) next = setNestedValue(next, field, value); + await configManager.setConfig(option.handler.path, next); +} + +export async function executeBitFunControlRequest(request: BitFunControlRequest): Promise { + switch (request.action) { + case 'list': + case 'search': + if (request.action === 'search' && !request.query?.trim()) { + throw new Error('query is required for search'); + } + return discoverBitFunCapabilities(request); + case 'get': { + const capability = request.capabilityId ? getInteractiveCapability(request.capabilityId) : undefined; + if (!capability) throw new Error(`Unknown BitFun capability: ${request.capabilityId ?? ''}`); + return inspectCapability(capability); + } + case 'open': { + if (!request.capabilityId) throw new Error('capabilityId is required for open'); + await activateInteractiveCapability(request.capabilityId, { itemId: request.itemId }); + return { + capabilityId: request.capabilityId, + itemId: request.itemId, + opened: true, + surface: 'desktop', + }; + } + case 'execute': { + const capability = request.capabilityId ? getInteractiveCapability(request.capabilityId) : undefined; + if (!capability) throw new Error(`Unknown BitFun capability: ${request.capabilityId ?? ''}`); + const operation = capability.operations.find(({ id }) => id === request.operationId); + if (!operation) throw new Error(`Unknown operation for ${capability.id}: ${request.operationId ?? ''}`); + if (operation.handler.kind === 'productAction') { + await activateProductAction(operation.handler.actionId); + } + return { capabilityId: capability.id, operationId: operation.id, executed: true }; + } + case 'configure': { + const capability = request.capabilityId ? getInteractiveCapability(request.capabilityId) : undefined; + if (!capability) throw new Error(`Unknown BitFun capability: ${request.capabilityId ?? ''}`); + const option = capability.options.find(({ id }) => id === request.optionId); + if (!option) throw new Error(`Unknown option for ${capability.id}: ${request.optionId ?? ''}`); + if (!Object.prototype.hasOwnProperty.call(request, 'value')) throw new Error('value is required for configure'); + await configureOption(option, request.value); + const effectiveValue = await currentOptionValue(option); + return { + capabilityId: capability.id, + optionId: option.id, + configured: true, + effectiveValue, + }; + } + default: + throw new Error(`Unsupported BitFunControl action: ${String(request.action)}`); + } +} + +async function reportResponse(response: BitFunControlResponse): Promise { + await api.invoke('report_bitfun_control_result', { request: response }); +} + +async function handleRequest(request: BitFunControlRequest): Promise { + try { + const result = await executeBitFunControlRequest(request); + await reportResponse({ requestId: request.requestId, success: true, result }); + } catch (error) { + try { + await reportResponse({ + requestId: request.requestId, + success: false, + error: errorMessage(error), + }); + } catch (reportError) { + log.warn('Failed to report BitFunControl result', { + requestId: request.requestId, + error: reportError, + }); + } + } +} + +export async function initializeBitFunControlBridge(): Promise { + if (unlisten) return; + unlisten = api.listen(REQUEST_EVENT, (request) => { + void handleRequest(request); + }); + try { + await api.invoke('mark_bitfun_control_surface_ready'); + } catch (error) { + unlisten(); + unlisten = null; + throw error; + } +} diff --git a/src/web-ui/src/app/global-search/generated/interactive-capabilities.json b/src/web-ui/src/app/global-search/generated/interactive-capabilities.json new file mode 100644 index 0000000000..4e06de54c1 --- /dev/null +++ b/src/web-ui/src/app/global-search/generated/interactive-capabilities.json @@ -0,0 +1,6188 @@ +{ + "schemaVersion": 3, + "product": "BitFun", + "title": "BitFun Playbook", + "origin": "https://playbook.openbitfun.com", + "source": "src/shared/interactive-capabilities/catalog.json", + "digest": "3207e4dc899c9109f0be952b9497d2f6169f9e2bb3ba9a859dda7e6959903470", + "counts": { + "features": 22, + "settings": 16, + "userFacing": 38, + "documentedItems": 297 + }, + "categories": { + "assistant": { + "titleZh": "AI 与协作", + "titleEn": "AI & collaboration", + "descriptionZh": "会话、Agent、记忆与智能协作。", + "descriptionEn": "Sessions, agents, memory, and AI collaboration." + }, + "workspace": { + "titleZh": "项目与开发", + "titleEn": "Projects & development", + "descriptionZh": "项目、文件、终端、Git、浏览器与开发工具。", + "descriptionEn": "Projects, files, terminal, Git, browser, and development tools." + }, + "automation": { + "titleZh": "扩展与自动化", + "titleEn": "Extensions & automation", + "descriptionZh": "Skills、Mini Apps、任务、Hooks 与生态兼容。", + "descriptionEn": "Skills, Mini Apps, tasks, hooks, and ecosystem compatibility." + }, + "connect": { + "titleZh": "连接与发布", + "titleEn": "Connect & publish", + "descriptionZh": "远程工作、多设备控制、派发与页面发布。", + "descriptionEn": "Remote work, multi-device control, dispatch, and publishing." + }, + "application": { + "titleZh": "应用设置", + "titleEn": "Application settings", + "descriptionZh": "外观、输入、开发环境与应用行为。", + "descriptionEn": "Appearance, input, development environment, and app behavior." + }, + "data": { + "titleZh": "数据与诊断", + "titleEn": "Data & diagnostics", + "descriptionZh": "用量、归档、日志与问题诊断。", + "descriptionEn": "Usage, archives, logs, and troubleshooting." + } + }, + "capabilities": [ + { + "id": "feature.ai-assistant", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "AI 助手与会话", + "titleEn": "AI assistant & sessions", + "summaryZh": "在项目上下文中与 AI 协作,创建会话、继续任务、处理权限请求,并保留完整的工作记录。", + "summaryEn": "Work with AI in project context, create sessions, continue tasks, answer permission requests, and keep a durable work record.", + "keywordsZh": [ + "对话", + "聊天", + "会话", + "新建会话", + "继续任务", + "权限", + "目标" + ], + "keywordsEn": [ + "chat", + "conversation", + "session", + "new session", + "continue task", + "permission", + "goal" + ], + "highlightsZh": [ + "创建、归档、恢复和分叉会话", + "暂停、继续或引导正在运行的任务", + "查看工具调用、权限请求和用量" + ], + "highlightsEn": [ + "Create, archive, restore, and fork sessions", + "Pause, continue, or steer running work", + "Inspect tool calls, permission requests, and usage" + ], + "items": [ + { + "id": "session-lifecycle", + "titleZh": "新建、重命名、归档、恢复、删除、分叉与导出会话", + "titleEn": "Create, rename, archive, restore, delete, fork, and export sessions" + }, + { + "id": "model-mode-permissions", + "titleZh": "为会话选择模型、工作模式、记忆模式与权限模式", + "titleEn": "Choose the model, work mode, memory mode, and permission mode per session" + }, + { + "id": "turn-control", + "titleZh": "开始、引导、打断、取消或恢复一次 Agent 运行", + "titleEn": "Start, steer, interrupt, cancel, or recover an agent turn" + }, + { + "id": "permission-mailbox", + "titleZh": "查看并逐个或批量回答等待中的权限请求", + "titleEn": "Review and answer pending permission requests individually or in a batch" + }, + { + "id": "history-search", + "titleZh": "分页加载、搜索和回填历史消息与会话内容", + "titleEn": "Page through, search, and backfill historical turns and session content" + }, + { + "id": "tool-activity", + "titleZh": "查看工具调用与后台命令,读取输出并继续输入或停止", + "titleEn": "Inspect tool calls and background commands, read output, send input, or stop them" + }, + { + "id": "goals", + "titleZh": "创建会话目标、更新目标内容与状态并清除目标", + "titleEn": "Create session goals, update their objective and status, and clear them" + }, + { + "id": "usage", + "titleZh": "查看单个会话的请求、Token 与成本用量报告", + "titleEn": "View request, token, and cost usage for an individual session" + }, + { + "id": "context-memory", + "titleZh": "重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆", + "titleEn": "Reload session context, initialize AGENTS.md, and manage long-term memory" + }, + { + "id": "btw-editor-ai", + "titleZh": "使用 BTW 轻量问答与编辑器内联 AI,并可随时取消", + "titleEn": "Use lightweight BTW questions and inline editor AI, with cancellation" + } + ], + "stepsZh": [ + "打开 AI 助手或新建会话", + "选择项目、模型和工作模式", + "描述目标;BitFun 会在会话中持续记录进度" + ], + "stepsEn": [ + "Open the AI assistant or create a session", + "Choose a project, model, and working mode", + "Describe the goal; BitFun keeps progress in the session" + ], + "agentExamplesZh": [ + "新建一个会话,我们来排查这个构建错误", + "打开 AI 助手,我想继续刚才的任务" + ], + "agentExamplesEn": [ + "Start a new session so we can debug this build error", + "Open the AI assistant; I want to continue my previous task" + ], + "destination": { + "kind": "scene", + "sceneId": "session" + }, + "operations": [ + { + "id": "new-session", + "titleZh": "新建会话", + "titleEn": "Create a session", + "descriptionZh": "打开一个新的 AI 会话。", + "descriptionEn": "Open a new AI session.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + }, + "handler": { + "kind": "productAction", + "actionId": "session.new" + } + } + ], + "options": [], + "searchTerms": [ + "feature.ai-assistant", + "AI 助手与会话", + "AI assistant & sessions", + "AI 与协作", + "AI & collaboration", + "对话", + "聊天", + "会话", + "新建会话", + "继续任务", + "权限", + "目标", + "chat", + "conversation", + "session", + "new session", + "continue task", + "permission", + "goal", + "创建、归档、恢复和分叉会话", + "暂停、继续或引导正在运行的任务", + "查看工具调用、权限请求和用量", + "Create, archive, restore, and fork sessions", + "Pause, continue, or steer running work", + "Inspect tool calls, permission requests, and usage", + "新建、重命名、归档、恢复、删除、分叉与导出会话", + "Create, rename, archive, restore, delete, fork, and export sessions", + "为会话选择模型、工作模式、记忆模式与权限模式", + "Choose the model, work mode, memory mode, and permission mode per session", + "开始、引导、打断、取消或恢复一次 Agent 运行", + "Start, steer, interrupt, cancel, or recover an agent turn", + "查看并逐个或批量回答等待中的权限请求", + "Review and answer pending permission requests individually or in a batch", + "分页加载、搜索和回填历史消息与会话内容", + "Page through, search, and backfill historical turns and session content", + "查看工具调用与后台命令,读取输出并继续输入或停止", + "Inspect tool calls and background commands, read output, send input, or stop them", + "创建会话目标、更新目标内容与状态并清除目标", + "Create session goals, update their objective and status, and clear them", + "查看单个会话的请求、Token 与成本用量报告", + "View request, token, and cost usage for an individual session", + "重新加载会话上下文、运行 AGENTS.md 初始化并管理长期记忆", + "Reload session context, initialize AGENTS.md, and manage long-term memory", + "使用 BTW 轻量问答与编辑器内联 AI,并可随时取消", + "Use lightweight BTW questions and inline editor AI, with cancellation" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.ai-assistant/" + }, + { + "id": "feature.agents", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "Agent 管理", + "titleEn": "Agents", + "summaryZh": "管理内置、自定义和子 Agent,让不同角色分工处理研究、编码、评审等任务。", + "summaryEn": "Manage built-in, custom, and subagents so specialized roles can handle research, coding, review, and more.", + "keywordsZh": [ + "智能体", + "子 Agent", + "自定义 Agent", + "多 Agent", + "并行协作" + ], + "keywordsEn": [ + "agent", + "subagent", + "custom agent", + "multi-agent", + "parallel collaboration" + ], + "highlightsZh": [ + "查看可用 Agent", + "创建和编辑自定义 Agent", + "让主 Agent 委派并行任务" + ], + "highlightsEn": [ + "Browse available agents", + "Create and edit custom agents", + "Let the primary agent delegate parallel work" + ], + "items": [ + { + "id": "browse-agents", + "titleZh": "查看内置、用户、项目与当前环境可见的 Agent", + "titleEn": "Browse built-in, user, project, and currently visible agents" + }, + { + "id": "custom-agent-create", + "titleZh": "创建自定义 Agent 并设置名称、说明和角色", + "titleEn": "Create custom agents with a name, description, and role" + }, + { + "id": "custom-agent-manage", + "titleZh": "读取、编辑、重新加载或删除自定义 Agent", + "titleEn": "Inspect, edit, reload, or delete custom agents" + }, + { + "id": "subagent-manage", + "titleZh": "创建、配置、查看和删除可委派的子 Agent", + "titleEn": "Create, configure, inspect, and delete delegatable subagents" + }, + { + "id": "capability-summary", + "titleZh": "查看每个 Agent 的工具、Skills、只读状态和能力摘要", + "titleEn": "Inspect each agent's tools, Skills, read-only state, and capability summary" + }, + { + "id": "tools-skills", + "titleZh": "按 Agent 选择工具组、单个工具、Skill 组与 Skills", + "titleEn": "Choose tool groups, individual tools, skill groups, and Skills per agent" + }, + { + "id": "delegation", + "titleZh": "让主 Agent 委派并行研究、编码和评审任务并设置超时", + "titleEn": "Let the primary agent delegate parallel research, coding, and review work with timeouts" + } + ], + "stepsZh": [ + "打开 Agents", + "选择现有 Agent 或创建一个角色", + "在会话中指定角色,或让主 Agent 自动委派" + ], + "stepsEn": [ + "Open Agents", + "Choose an existing agent or create a role", + "Select the role in a session or let the primary agent delegate" + ], + "agentExamplesZh": [ + "打开 Agents,我想看看有哪些专门角色", + "帮我进入 Agent 管理页" + ], + "agentExamplesEn": [ + "Open Agents so I can see the specialized roles", + "Take me to agent management" + ], + "destination": { + "kind": "action", + "actionId": "surface.agents.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.agents", + "Agent 管理", + "Agents", + "AI 与协作", + "AI & collaboration", + "智能体", + "子 Agent", + "自定义 Agent", + "多 Agent", + "并行协作", + "agent", + "subagent", + "custom agent", + "multi-agent", + "parallel collaboration", + "查看可用 Agent", + "创建和编辑自定义 Agent", + "让主 Agent 委派并行任务", + "Browse available agents", + "Create and edit custom agents", + "Let the primary agent delegate parallel work", + "查看内置、用户、项目与当前环境可见的 Agent", + "Browse built-in, user, project, and currently visible agents", + "创建自定义 Agent 并设置名称、说明和角色", + "Create custom agents with a name, description, and role", + "读取、编辑、重新加载或删除自定义 Agent", + "Inspect, edit, reload, or delete custom agents", + "创建、配置、查看和删除可委派的子 Agent", + "Create, configure, inspect, and delete delegatable subagents", + "查看每个 Agent 的工具、Skills、只读状态和能力摘要", + "Inspect each agent's tools, Skills, read-only state, and capability summary", + "按 Agent 选择工具组、单个工具、Skill 组与 Skills", + "Choose tool groups, individual tools, skill groups, and Skills per agent", + "让主 Agent 委派并行研究、编码和评审任务并设置超时", + "Let the primary agent delegate parallel research, coding, and review work with timeouts" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.agents/" + }, + { + "id": "feature.personal-assistants", + "kind": "feature", + "categoryId": "assistant", + "titleZh": "个人助理", + "titleEn": "Personal assistants", + "summaryZh": "在助理空间中创建和管理自己的长期 AI 助理,定义身份与人设、配置默认能力,并从同一处开始会话或安排定时任务。", + "summaryEn": "Create and manage persistent AI assistants, define their identity and persona, configure default capabilities, and start chats or scheduled work from one place.", + "keywordsZh": [ + "助理", + "个人助理", + "育苗场", + "主助理", + "身份", + "头像", + "人设", + "Persona", + "默认工具", + "默认技能" + ], + "keywordsEn": [ + "assistant", + "personal assistant", + "nursery", + "primary assistant", + "identity", + "avatar", + "persona", + "default tools", + "default skills" + ], + "highlightsZh": [ + "创建、设为主助理或删除助理", + "编辑身份、头像与 Persona 文档", + "配置默认 Skills、内置工具和 MCP 工具" + ], + "highlightsEn": [ + "Create, select a primary assistant, or delete assistants", + "Edit identity, avatar, and persona documents", + "Configure default Skills, built-in tools, and MCP tools" + ], + "items": [ + { + "id": "assistant-gallery", + "titleZh": "浏览已有助理、创建新助理并查看每个助理的身份与能力概览", + "titleEn": "Browse existing assistants, create a new one, and review each assistant's identity and capability summary" + }, + { + "id": "primary-delete-reset", + "titleZh": "设为主助理、删除非主助理,或将助理工作区重置为默认状态", + "titleEn": "Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults" + }, + { + "id": "identity-avatar", + "titleZh": "编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符", + "titleEn": "Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character" + }, + { + "id": "persona-documents", + "titleZh": "读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter", + "titleEn": "Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter" + }, + { + "id": "default-skills", + "titleZh": "为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态", + "titleEn": "Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability" + }, + { + "id": "default-builtin-tools", + "titleZh": "逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态", + "titleEn": "Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults" + }, + { + "id": "default-mcp-tools", + "titleZh": "按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具", + "titleEn": "Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants" + }, + { + "id": "defaults-discovery-reset", + "titleZh": "按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值", + "titleEn": "Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults" + }, + { + "id": "assistant-sessions", + "titleZh": "从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话", + "titleEn": "Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page" + }, + { + "id": "assistant-schedules", + "titleZh": "查看和管理仅属于当前助理工作区的定时会话与自动任务", + "titleEn": "Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace" + } + ], + "stepsZh": [ + "打开“助理”", + "创建助理或选择现有助理", + "编辑身份与人设,配置默认能力,然后开始会话或定时任务" + ], + "stepsEn": [ + "Open Assistants", + "Create an assistant or choose an existing one", + "Edit its identity and persona, configure defaults, then start a chat or scheduled task" + ], + "agentExamplesZh": [ + "打开我的个人助理", + "带我去育苗场配置助理的默认工具", + "我想修改主助理的人设" + ], + "agentExamplesEn": [ + "Open my personal assistants", + "Take me to the nursery to configure default assistant tools", + "I want to edit my primary assistant's persona" + ], + "destination": { + "kind": "scene", + "sceneId": "profile" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.personal-assistants", + "个人助理", + "Personal assistants", + "AI 与协作", + "AI & collaboration", + "助理", + "育苗场", + "主助理", + "身份", + "头像", + "人设", + "Persona", + "默认工具", + "默认技能", + "assistant", + "personal assistant", + "nursery", + "primary assistant", + "identity", + "avatar", + "persona", + "default tools", + "default skills", + "创建、设为主助理或删除助理", + "编辑身份、头像与 Persona 文档", + "配置默认 Skills、内置工具和 MCP 工具", + "Create, select a primary assistant, or delete assistants", + "Edit identity, avatar, and persona documents", + "Configure default Skills, built-in tools, and MCP tools", + "浏览已有助理、创建新助理并查看每个助理的身份与能力概览", + "Browse existing assistants, create a new one, and review each assistant's identity and capability summary", + "设为主助理、删除非主助理,或将助理工作区重置为默认状态", + "Set the primary assistant, delete non-primary assistants, or reset an assistant workspace to defaults", + "编辑助理名称、角色类型和气质,并选择官方头像、Emoji 或自定义头像字符", + "Edit an assistant's name, creature type, and vibe, then choose an official avatar, emoji, or custom avatar character", + "读取和编辑 IDENTITY.md、SOUL.md 与 USER.md,并自动保存 Markdown 正文和 Frontmatter", + "Read and edit IDENTITY.md, SOUL.md, and USER.md with autosaved Markdown body and frontmatter", + "为新助理选择默认 Skills,识别用户级与项目级来源、遮蔽关系和当前可用状态", + "Choose default Skills for new assistants while seeing user/project sources, shadowing, and availability", + "逐个或批量启用默认内置工具,并查看说明、只读或可执行属性及产品默认状态", + "Enable default built-in tools individually or in groups and inspect descriptions, read-only or executable access, and product defaults", + "按 MCP 服务器查看连接状态、工具详情与传输信息,并为新助理启用整个服务或单个工具", + "Inspect MCP server status, tool details, and transport, then enable a whole server or individual tools for new assistants", + "按 Skills、内置工具或 MCP 分类搜索,筛选启用、停用、已更改或不可用项,查看详情并恢复产品默认值", + "Search Skills, built-in tools, or MCP entries; filter enabled, disabled, changed, or unavailable items; inspect details; and restore product defaults", + "从助理卡片新建会话,或在助理详情中选择模型、输入消息并查看该助理的历史会话", + "Start a session from an assistant card, or choose a model, send a message, and browse that assistant's sessions from its detail page", + "查看和管理仅属于当前助理工作区的定时会话与自动任务", + "Review and manage scheduled sessions and automated jobs scoped to the current assistant workspace" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.personal-assistants/" + }, + { + "id": "feature.projects", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "项目与工作区", + "titleEn": "Projects & workspaces", + "summaryZh": "打开本地目录或创建项目,让文件、会话、终端和 Agent 围绕同一工作区协作。", + "summaryEn": "Open a local directory or create a project so files, sessions, terminals, and agents share one workspace.", + "keywordsZh": [ + "项目", + "工作区", + "打开文件夹", + "新建项目", + "切换项目" + ], + "keywordsEn": [ + "project", + "workspace", + "open folder", + "new project", + "switch project" + ], + "highlightsZh": [ + "打开现有目录", + "创建新项目", + "在多个工作区间切换" + ], + "highlightsEn": [ + "Open an existing directory", + "Create a new project", + "Switch between workspaces" + ], + "items": [ + { + "id": "open-close-switch", + "titleZh": "打开、关闭、切换并重新排序多个工作区", + "titleEn": "Open, close, switch, and reorder multiple workspaces" + }, + { + "id": "recent-workspaces", + "titleZh": "查看、清理和重新打开最近使用的项目", + "titleEn": "Review, clean up, and reopen recently used projects" + }, + { + "id": "workspace-metadata", + "titleZh": "扫描并维护工作区名称、信息、关联目录和 Persona 文件", + "titleEn": "Scan and maintain workspace names, metadata, related directories, and persona files" + }, + { + "id": "file-watch", + "titleZh": "监听项目文件变化并查看当前监听路径", + "titleEn": "Watch project file changes and inspect active watched paths" + }, + { + "id": "workspace-search", + "titleZh": "按文件名、路径或文件内容搜索本地工作区", + "titleEn": "Search local workspaces by filename, path, or file content" + }, + { + "id": "remote-open", + "titleZh": "从项目流程打开 SSH 或其他远程工作区", + "titleEn": "Open SSH and other remote workspaces from the project flow" + }, + { + "id": "project-health", + "titleZh": "查看当前工作区、应用状态、健康状态与统计信息", + "titleEn": "Inspect the current workspace, app state, health, and statistics" + } + ], + "stepsZh": [ + "选择“打开项目”或“新建项目”", + "选择本地目录或配置远程位置", + "从侧边栏进入项目文件与会话" + ], + "stepsEn": [ + "Choose Open Project or New Project", + "Select a local directory or configure a remote location", + "Use the sidebar to access files and sessions" + ], + "agentExamplesZh": [ + "帮我打开一个项目", + "打开新建项目的界面" + ], + "agentExamplesEn": [ + "Help me open a project", + "Open the new-project flow" + ], + "destination": { + "kind": "action", + "actionId": "project.open" + }, + "operations": [ + { + "id": "open-project", + "titleZh": "打开项目", + "titleEn": "Open project", + "descriptionZh": "选择并打开一个已有目录。", + "descriptionEn": "Choose and open an existing directory.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + }, + "handler": { + "kind": "productAction", + "actionId": "project.open" + } + }, + { + "id": "new-project", + "titleZh": "新建项目", + "titleEn": "Create project", + "descriptionZh": "打开新建项目流程。", + "descriptionEn": "Open the new-project flow.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + }, + "handler": { + "kind": "productAction", + "actionId": "project.new" + } + } + ], + "options": [], + "searchTerms": [ + "feature.projects", + "项目与工作区", + "Projects & workspaces", + "项目与开发", + "Projects & development", + "项目", + "工作区", + "打开文件夹", + "新建项目", + "切换项目", + "project", + "workspace", + "open folder", + "new project", + "switch project", + "打开现有目录", + "创建新项目", + "在多个工作区间切换", + "Open an existing directory", + "Create a new project", + "Switch between workspaces", + "打开、关闭、切换并重新排序多个工作区", + "Open, close, switch, and reorder multiple workspaces", + "查看、清理和重新打开最近使用的项目", + "Review, clean up, and reopen recently used projects", + "扫描并维护工作区名称、信息、关联目录和 Persona 文件", + "Scan and maintain workspace names, metadata, related directories, and persona files", + "监听项目文件变化并查看当前监听路径", + "Watch project file changes and inspect active watched paths", + "按文件名、路径或文件内容搜索本地工作区", + "Search local workspaces by filename, path, or file content", + "从项目流程打开 SSH 或其他远程工作区", + "Open SSH and other remote workspaces from the project flow", + "查看当前工作区、应用状态、健康状态与统计信息", + "Inspect the current workspace, app state, health, and statistics" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.projects/" + }, + { + "id": "feature.files-editor", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "文件与代码编辑", + "titleEn": "Files & code editing", + "summaryZh": "浏览、搜索和编辑项目文件,查看差异、代码符号、诊断与 Agent 产生的改动。", + "summaryEn": "Browse, search, and edit project files while inspecting diffs, symbols, diagnostics, and agent changes.", + "keywordsZh": [ + "文件", + "代码", + "编辑器", + "搜索文件", + "差异", + "诊断", + "LSP" + ], + "keywordsEn": [ + "files", + "code", + "editor", + "file search", + "diff", + "diagnostics", + "LSP" + ], + "highlightsZh": [ + "文件树与全文搜索", + "代码导航、格式化和诊断", + "查看、接受或撤销 Agent 改动" + ], + "highlightsEn": [ + "File tree and full-text search", + "Code navigation, formatting, and diagnostics", + "Review, accept, or revert agent changes" + ], + "items": [ + { + "id": "file-tree", + "titleZh": "浏览文件树并创建、重命名、删除或在系统中显示文件和目录", + "titleEn": "Browse the file tree and create, rename, delete, or reveal files and directories" + }, + { + "id": "indexed-search", + "titleZh": "建立或重建索引,按文件名和全文内容流式搜索", + "titleEn": "Build or rebuild an index and stream filename and full-text search results" + }, + { + "id": "edit-save", + "titleZh": "读取、编辑、保存文件并同步编辑器状态", + "titleEn": "Read, edit, and save files while synchronizing editor state" + }, + { + "id": "diffs", + "titleZh": "查看修改文件、会话、轮次和单次操作的差异与统计", + "titleEn": "Inspect diffs and statistics by file, session, turn, or operation" + }, + { + "id": "accept-reject", + "titleZh": "按文件、操作或整个会话接受或拒绝 Agent 改动", + "titleEn": "Accept or reject agent changes by file, operation, or whole session" + }, + { + "id": "snapshots-rollback", + "titleZh": "查看文件变更历史和快照,并回滚整个会话或指定轮次", + "titleEn": "Review file history and snapshots, then roll back a session or selected turn" + }, + { + "id": "lsp-navigation", + "titleZh": "使用 Hover、跳转定义、查找引用、文档符号与高亮", + "titleEn": "Use hover, go to definition, references, document symbols, and highlights" + }, + { + "id": "lsp-editing", + "titleZh": "使用补全、格式化、重命名、代码操作、内联提示与语义高亮", + "titleEn": "Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting" + }, + { + "id": "lsp-plugins", + "titleZh": "检测项目并安装、启动、停止或卸载 LSP 插件", + "titleEn": "Detect projects and install, start, stop, or uninstall LSP plugins" + }, + { + "id": "attachments", + "titleZh": "粘贴、拖放或上传文件与图片作为会话上下文", + "titleEn": "Paste, drop, or upload files and images as session context" + } + ], + "stepsZh": [ + "先打开一个项目", + "打开“文件”", + "选择文件进行编辑,或搜索内容与符号" + ], + "stepsEn": [ + "Open a project first", + "Open Files", + "Choose a file to edit, or search content and symbols" + ], + "agentExamplesZh": [ + "打开项目文件", + "带我去文件和代码编辑器" + ], + "agentExamplesEn": [ + "Open the project files", + "Take me to the file and code editor" + ], + "destination": { + "kind": "action", + "actionId": "surface.files.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.files-editor", + "文件与代码编辑", + "Files & code editing", + "项目与开发", + "Projects & development", + "文件", + "代码", + "编辑器", + "搜索文件", + "差异", + "诊断", + "LSP", + "files", + "code", + "editor", + "file search", + "diff", + "diagnostics", + "文件树与全文搜索", + "代码导航、格式化和诊断", + "查看、接受或撤销 Agent 改动", + "File tree and full-text search", + "Code navigation, formatting, and diagnostics", + "Review, accept, or revert agent changes", + "浏览文件树并创建、重命名、删除或在系统中显示文件和目录", + "Browse the file tree and create, rename, delete, or reveal files and directories", + "建立或重建索引,按文件名和全文内容流式搜索", + "Build or rebuild an index and stream filename and full-text search results", + "读取、编辑、保存文件并同步编辑器状态", + "Read, edit, and save files while synchronizing editor state", + "查看修改文件、会话、轮次和单次操作的差异与统计", + "Inspect diffs and statistics by file, session, turn, or operation", + "按文件、操作或整个会话接受或拒绝 Agent 改动", + "Accept or reject agent changes by file, operation, or whole session", + "查看文件变更历史和快照,并回滚整个会话或指定轮次", + "Review file history and snapshots, then roll back a session or selected turn", + "使用 Hover、跳转定义、查找引用、文档符号与高亮", + "Use hover, go to definition, references, document symbols, and highlights", + "使用补全、格式化、重命名、代码操作、内联提示与语义高亮", + "Use completion, formatting, rename, code actions, inlay hints, and semantic highlighting", + "检测项目并安装、启动、停止或卸载 LSP 插件", + "Detect projects and install, start, stop, or uninstall LSP plugins", + "粘贴、拖放或上传文件与图片作为会话上下文", + "Paste, drop, or upload files and images as session context" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.files-editor/" + }, + { + "id": "feature.terminal", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "终端", + "titleEn": "Terminal", + "summaryZh": "在当前项目中运行 Shell、查看输出、保留命令历史,并让 Agent 与同一终端环境协作。", + "summaryEn": "Run a shell in the current project, inspect output, keep command history, and share the same terminal context with agents.", + "keywordsZh": [ + "终端", + "命令行", + "Shell", + "控制台", + "运行命令" + ], + "keywordsEn": [ + "terminal", + "command line", + "shell", + "console", + "run command" + ], + "highlightsZh": [ + "创建多个终端", + "选择默认 Shell", + "查看运行状态和历史" + ], + "highlightsEn": [ + "Create multiple terminals", + "Choose the default shell", + "Inspect running state and history" + ], + "items": [ + { + "id": "multiple-terminals", + "titleZh": "创建、列出、切换和关闭多个终端会话", + "titleEn": "Create, list, switch, and close multiple terminal sessions" + }, + { + "id": "shells", + "titleZh": "检测可用 Shell,并为终端选择默认或指定 Shell", + "titleEn": "Detect available shells and choose a default or explicit shell" + }, + { + "id": "working-directory", + "titleZh": "在当前项目目录或指定起始目录创建终端", + "titleEn": "Create terminals in the current project or a chosen starting directory" + }, + { + "id": "command-control", + "titleZh": "执行命令、写入输入并发送中断或其他信号", + "titleEn": "Execute commands, write input, and send interrupt or other signals" + }, + { + "id": "resize", + "titleZh": "随终端面板大小变化同步行列尺寸", + "titleEn": "Synchronize terminal rows and columns as the panel resizes" + }, + { + "id": "history-integration", + "titleZh": "查看命令历史并检测 Shell Integration 支持", + "titleEn": "Review command history and detect shell-integration support" + }, + { + "id": "shutdown", + "titleZh": "确认输出接收并安全关闭单个或全部终端", + "titleEn": "Acknowledge output and safely shut down one or all terminals" + } + ], + "stepsZh": [ + "打开终端", + "确认当前目录", + "输入命令;需要时新建额外终端" + ], + "stepsEn": [ + "Open Terminal", + "Confirm the current directory", + "Enter a command and create extra terminals as needed" + ], + "agentExamplesZh": [ + "打开一个终端", + "切到终端界面" + ], + "agentExamplesEn": [ + "Open a terminal", + "Switch to the terminal" + ], + "destination": { + "kind": "action", + "actionId": "surface.terminal.open" + }, + "operations": [ + { + "id": "new-terminal", + "titleZh": "新建终端", + "titleEn": "Create terminal", + "descriptionZh": "在当前工作区创建终端。", + "descriptionEn": "Create a terminal in the current workspace.", + "risk": "ui", + "inputSchema": { + "type": "object", + "additionalProperties": false + }, + "handler": { + "kind": "productAction", + "actionId": "surface.terminal.open" + } + } + ], + "options": [], + "searchTerms": [ + "feature.terminal", + "终端", + "Terminal", + "项目与开发", + "Projects & development", + "命令行", + "Shell", + "控制台", + "运行命令", + "terminal", + "command line", + "shell", + "console", + "run command", + "创建多个终端", + "选择默认 Shell", + "查看运行状态和历史", + "Create multiple terminals", + "Choose the default shell", + "Inspect running state and history", + "创建、列出、切换和关闭多个终端会话", + "Create, list, switch, and close multiple terminal sessions", + "检测可用 Shell,并为终端选择默认或指定 Shell", + "Detect available shells and choose a default or explicit shell", + "在当前项目目录或指定起始目录创建终端", + "Create terminals in the current project or a chosen starting directory", + "执行命令、写入输入并发送中断或其他信号", + "Execute commands, write input, and send interrupt or other signals", + "随终端面板大小变化同步行列尺寸", + "Synchronize terminal rows and columns as the panel resizes", + "查看命令历史并检测 Shell Integration 支持", + "Review command history and detect shell-integration support", + "确认输出接收并安全关闭单个或全部终端", + "Acknowledge output and safely shut down one or all terminals" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.terminal/" + }, + { + "id": "feature.git", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "Git 版本控制", + "titleEn": "Git version control", + "summaryZh": "查看改动、分支和提交,完成暂存、提交、合并、Cherry-pick 与 Worktree 工作流。", + "summaryEn": "Inspect changes, branches, and commits; stage, commit, merge, cherry-pick, and work with Git worktrees.", + "keywordsZh": [ + "Git", + "版本控制", + "分支", + "提交", + "暂存", + "合并", + "Worktree" + ], + "keywordsEn": [ + "git", + "source control", + "branch", + "commit", + "stage", + "merge", + "worktree" + ], + "highlightsZh": [ + "查看工作区改动", + "管理分支与提交", + "使用 Worktree 隔离并行任务" + ], + "highlightsEn": [ + "Inspect workspace changes", + "Manage branches and commits", + "Use worktrees to isolate parallel work" + ], + "items": [ + { + "id": "status-diff", + "titleZh": "查看仓库状态、修改文件和逐文件 Diff", + "titleEn": "Inspect repository status, changed files, and per-file diffs" + }, + { + "id": "stage-reset", + "titleZh": "暂存文件、取消暂存并重置到指定提交", + "titleEn": "Stage files, unstage changes, and reset to a selected commit" + }, + { + "id": "commit", + "titleZh": "预览或生成提交信息并创建提交", + "titleEn": "Preview or generate a commit message and create the commit" + }, + { + "id": "sync", + "titleZh": "从远端 Pull 并向远端 Push", + "titleEn": "Pull from and push to remotes" + }, + { + "id": "branches", + "titleZh": "查看、创建、切换和删除本地分支", + "titleEn": "Browse, create, check out, and delete local branches" + }, + { + "id": "graph-history", + "titleZh": "浏览提交图谱与仓库历史并保存最近访问记录", + "titleEn": "Browse the commit graph and repository history, including recent-history persistence" + }, + { + "id": "revision-content", + "titleZh": "解析 Revision 并查看任意提交中的文件内容", + "titleEn": "Resolve revisions and inspect file content from any commit" + }, + { + "id": "cherry-pick", + "titleZh": "执行、继续或中止 Cherry-pick", + "titleEn": "Start, continue, or abort a cherry-pick" + }, + { + "id": "trust-worktrees", + "titleZh": "管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除", + "titleEn": "Manage repository trust and create, bind, promote, recreate, or remove worktrees" + } + ], + "stepsZh": [ + "打开 Git", + "选择改动或分支", + "执行暂存、提交或分支操作" + ], + "stepsEn": [ + "Open Git", + "Choose changes or a branch", + "Stage, commit, or perform a branch operation" + ], + "agentExamplesZh": [ + "打开 Git 面板", + "带我查看当前代码改动" + ], + "agentExamplesEn": [ + "Open the Git panel", + "Show me the current code changes" + ], + "destination": { + "kind": "scene", + "sceneId": "git" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.git", + "Git 版本控制", + "Git version control", + "项目与开发", + "Projects & development", + "Git", + "版本控制", + "分支", + "提交", + "暂存", + "合并", + "Worktree", + "git", + "source control", + "branch", + "commit", + "stage", + "merge", + "worktree", + "查看工作区改动", + "管理分支与提交", + "使用 Worktree 隔离并行任务", + "Inspect workspace changes", + "Manage branches and commits", + "Use worktrees to isolate parallel work", + "查看仓库状态、修改文件和逐文件 Diff", + "Inspect repository status, changed files, and per-file diffs", + "暂存文件、取消暂存并重置到指定提交", + "Stage files, unstage changes, and reset to a selected commit", + "预览或生成提交信息并创建提交", + "Preview or generate a commit message and create the commit", + "从远端 Pull 并向远端 Push", + "Pull from and push to remotes", + "查看、创建、切换和删除本地分支", + "Browse, create, check out, and delete local branches", + "浏览提交图谱与仓库历史并保存最近访问记录", + "Browse the commit graph and repository history, including recent-history persistence", + "解析 Revision 并查看任意提交中的文件内容", + "Resolve revisions and inspect file content from any commit", + "执行、继续或中止 Cherry-pick", + "Start, continue, or abort a cherry-pick", + "管理仓库信任与 Worktree 的创建、绑定、提升、重建和删除", + "Manage repository trust and create, bind, promote, recreate, or remove worktrees" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.git/" + }, + { + "id": "feature.code-review", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "代码评审与 Pull Request", + "titleEn": "Code review & pull requests", + "summaryZh": "阅读改动与 PR 上下文,查看 CI 日志,生成提交信息,并组织深度代码评审。", + "summaryEn": "Review changes and pull-request context, inspect CI logs, generate commit messages, and run deeper code reviews.", + "keywordsZh": [ + "代码评审", + "PR", + "Pull Request", + "CI 日志", + "提交信息", + "Deep Review" + ], + "keywordsEn": [ + "code review", + "PR", + "pull request", + "CI log", + "commit message", + "deep review" + ], + "highlightsZh": [ + "查看 PR、Issue 和 CI 上下文", + "生成提交信息", + "针对改动发起深度评审" + ], + "highlightsEn": [ + "Inspect PR, issue, and CI context", + "Generate commit messages", + "Run deep reviews against changes" + ], + "items": [ + { + "id": "workspace-context", + "titleZh": "读取仓库、分支、工作区快照和评审目标", + "titleEn": "Load repository, branch, workspace snapshot, and review-target context" + }, + { + "id": "pull-request", + "titleZh": "查看 Pull Request 详情、分页内容与关联改动", + "titleEn": "Inspect pull-request details, paged content, and related changes" + }, + { + "id": "ci-logs", + "titleZh": "读取 Pull Request 的 CI 运行日志", + "titleEn": "Read CI run logs for a pull request" + }, + { + "id": "issues", + "titleZh": "读取关联 Issue 的标题、描述与上下文", + "titleEn": "Read the title, body, and context of linked issues" + }, + { + "id": "authentication", + "titleZh": "保存或清除评审平台访问令牌", + "titleEn": "Store or clear review-platform access tokens" + }, + { + "id": "commit-message", + "titleZh": "预览、生成或快速采用提交信息", + "titleEn": "Preview, generate, or quickly apply a commit message" + }, + { + "id": "deep-review", + "titleZh": "针对工作区、提交或 PR 发起 Deep Review 并控制评审队列", + "titleEn": "Run Deep Review against a workspace, commit, or pull request and control its queue" + } + ], + "stepsZh": [ + "打开项目文件或 Git", + "选择改动或评审目标", + "在会话中请求评审或打开对应详情" + ], + "stepsEn": [ + "Open project files or Git", + "Choose a change or review target", + "Ask for a review in the session or open its details" + ], + "agentExamplesZh": [ + "打开文件面板,我要评审当前改动", + "带我查看 Pull Request 相关能力" + ], + "agentExamplesEn": [ + "Open Files so I can review the current changes", + "Take me to the pull-request workflow" + ], + "destination": { + "kind": "action", + "actionId": "surface.files.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.code-review", + "代码评审与 Pull Request", + "Code review & pull requests", + "项目与开发", + "Projects & development", + "代码评审", + "PR", + "Pull Request", + "CI 日志", + "提交信息", + "Deep Review", + "code review", + "pull request", + "CI log", + "commit message", + "deep review", + "查看 PR、Issue 和 CI 上下文", + "生成提交信息", + "针对改动发起深度评审", + "Inspect PR, issue, and CI context", + "Generate commit messages", + "Run deep reviews against changes", + "读取仓库、分支、工作区快照和评审目标", + "Load repository, branch, workspace snapshot, and review-target context", + "查看 Pull Request 详情、分页内容与关联改动", + "Inspect pull-request details, paged content, and related changes", + "读取 Pull Request 的 CI 运行日志", + "Read CI run logs for a pull request", + "读取关联 Issue 的标题、描述与上下文", + "Read the title, body, and context of linked issues", + "保存或清除评审平台访问令牌", + "Store or clear review-platform access tokens", + "预览、生成或快速采用提交信息", + "Preview, generate, or quickly apply a commit message", + "针对工作区、提交或 PR 发起 Deep Review 并控制评审队列", + "Run Deep Review against a workspace, commit, or pull request and control its queue" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.code-review/" + }, + { + "id": "feature.browser", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "内置浏览器", + "titleEn": "Built-in browser", + "summaryZh": "在 BitFun 内打开网页和本地服务;Agent 可直接读取页面、选择元素并点击、填写、滚动或截图。", + "summaryEn": "Open webpages and local services inside BitFun, where an agent can inspect the page and select, click, fill, scroll, or capture elements directly.", + "keywordsZh": [ + "浏览器", + "网页", + "URL", + "本地预览", + "Webview", + "Agent 控制浏览器", + "网页自动化", + "元素选择", + "点击网页", + "填写表单" + ], + "keywordsEn": [ + "browser", + "web", + "URL", + "local preview", + "webview", + "agent browser control", + "web automation", + "element selection", + "click page", + "fill form" + ], + "highlightsZh": [ + "打开网页和本地开发地址", + "Agent 读取并操作内置网页", + "与外部 CDP 浏览器共用动作契约", + "在会话旁并排查看页面" + ], + "highlightsEn": [ + "Open webpages and local development URLs", + "Let an agent inspect and operate the built-in page", + "Share one action contract with external CDP browsers", + "Keep the page beside a session" + ], + "items": [ + { + "id": "open-urls", + "titleZh": "输入完整网址、本地域名或开发服务端口并在 BitFun 内打开", + "titleEn": "Open full URLs, local hostnames, or development-service ports inside BitFun" + }, + { + "id": "history-navigation", + "titleZh": "使用后退、前进和地址栏浏览页面历史", + "titleEn": "Navigate page history with Back, Forward, and the address bar" + }, + { + "id": "reload-status", + "titleZh": "刷新页面,并同步当前 URL、加载状态与错误提示", + "titleEn": "Reload pages and synchronize the current URL, loading state, and errors" + }, + { + "id": "scene-and-panel", + "titleZh": "既可作为独立浏览器场景,也可在会话旁的辅助面板中打开", + "titleEn": "Use the browser as a standalone scene or an auxiliary panel beside a session" + }, + { + "id": "element-picker", + "titleZh": "启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class", + "titleEn": "Start the element picker to highlight hovered elements and show tag, ID, and class details" + }, + { + "id": "element-context", + "titleZh": "点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文", + "titleEn": "Click an element to capture its CSS path, attributes, text, and HTML into the current session context" + }, + { + "id": "element-picker-cancel", + "titleZh": "再次点击选择按钮或按 Esc 取消元素选择并清理高亮", + "titleEn": "Click the picker again or press Escape to cancel selection and remove overlays" + }, + { + "id": "agent-page-automation", + "titleZh": "让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图", + "titleEn": "Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page" + }, + { + "id": "shared-browser-action-contract", + "titleZh": "内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约", + "titleEn": "Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers" + }, + { + "id": "browser-target-selection", + "titleZh": "通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面", + "titleEn": "Choose the built-in or external browser with target and locate a page by session_id, URL, or title" + }, + { + "id": "embedded-webview", + "titleZh": "桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接", + "titleEn": "Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place" + } + ], + "stepsZh": [ + "打开浏览器并输入网址或本地端口", + "直接告诉 Agent 要在页面上完成什么", + "Agent 先读取页面,再用元素引用执行操作" + ], + "stepsEn": [ + "Open Browser and enter a URL or local port", + "Tell the agent what to accomplish on the page", + "The agent inspects the page, then acts through element refs" + ], + "agentControl": { + "tool": "ControlHub", + "workflowZh": [ + "用 browser.open_builtin 打开网址并取得内置页面的 session_id", + "对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约", + "页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external" + ], + "workflowEn": [ + "Open the URL with browser.open_builtin and keep the returned built-in session_id", + "Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract", + "Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection" + ] + }, + "agentExamplesZh": [ + "在内置浏览器打开这个网址,然后找到登录按钮", + "读取当前内置网页并填写这个表单", + "用内置浏览器点开搜索结果并总结页面" + ], + "agentExamplesEn": [ + "Open this URL in the built-in browser and find the sign-in button", + "Inspect the current built-in page and fill this form", + "Use the built-in browser to open the search result and summarize the page" + ], + "destination": { + "kind": "action", + "actionId": "surface.browser.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.browser", + "内置浏览器", + "Built-in browser", + "项目与开发", + "Projects & development", + "浏览器", + "网页", + "URL", + "本地预览", + "Webview", + "Agent 控制浏览器", + "网页自动化", + "元素选择", + "点击网页", + "填写表单", + "browser", + "web", + "local preview", + "webview", + "agent browser control", + "web automation", + "element selection", + "click page", + "fill form", + "打开网页和本地开发地址", + "Agent 读取并操作内置网页", + "与外部 CDP 浏览器共用动作契约", + "在会话旁并排查看页面", + "Open webpages and local development URLs", + "Let an agent inspect and operate the built-in page", + "Share one action contract with external CDP browsers", + "Keep the page beside a session", + "输入完整网址、本地域名或开发服务端口并在 BitFun 内打开", + "Open full URLs, local hostnames, or development-service ports inside BitFun", + "使用后退、前进和地址栏浏览页面历史", + "Navigate page history with Back, Forward, and the address bar", + "刷新页面,并同步当前 URL、加载状态与错误提示", + "Reload pages and synchronize the current URL, loading state, and errors", + "既可作为独立浏览器场景,也可在会话旁的辅助面板中打开", + "Use the browser as a standalone scene or an auxiliary panel beside a session", + "启动元素选择器,悬停时高亮页面元素并显示标签、ID 和 Class", + "Start the element picker to highlight hovered elements and show tag, ID, and class details", + "点击元素后捕获 CSS 路径、属性、文本和 HTML,并加入当前会话上下文", + "Click an element to capture its CSS path, attributes, text, and HTML into the current session context", + "再次点击选择按钮或按 Esc 取消元素选择并清理高亮", + "Click the picker again or press Escape to cancel selection and remove overlays", + "让 Agent 对内置网页执行快照、读取、点击、悬停、填写、按键、滚动、等待、脚本求值和截图", + "Let an agent snapshot, read, click, hover, fill, press keys, scroll, wait, evaluate scripts, and capture the built-in page", + "内置 WebView 与外部 CDP 浏览器共用同一套 BrowserActions 参数、元素引用、结果与错误契约", + "Use one BrowserActions parameter, element-ref, result, and error contract across the built-in WebView and external CDP browsers", + "通过 target 选择内置或外部浏览器,并用 session_id、URL 或标题精确定位页面", + "Choose the built-in or external browser with target and locate a page by session_id, URL, or title", + "桌面端使用原生 WebView,Web 端回退到受限 iframe,并在当前页打开新窗口链接", + "Use a native WebView on desktop, a sandboxed iframe on web, and open new-window links in place", + "用 browser.open_builtin 打开网址并取得内置页面的 session_id", + "对同一个 session_id 指定 target 为 builtin,也可用 target_url 或 target_title 定位;快照、点击、填写、滚动和截图等动作与外部 CDP 浏览器共用同一套契约", + "页面变化后重新快照并使用最新元素引用;只有网络追踪、原始 CDP 和文件输入等协议扩展才切换到 external", + "Open the URL with browser.open_builtin and keep the returned built-in session_id", + "Address that session_id with target set to builtin, or locate it by target_url or target_title; snapshots, clicks, fills, scrolling, screenshots, and other portable actions share the external CDP contract", + "Take a new snapshot after page changes and use fresh element refs; switch to external only for protocol extensions such as network tracing, raw CDP, or file-input injection", + "ControlHub" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.browser/" + }, + { + "id": "feature.computer-use", + "kind": "feature", + "categoryId": "workspace", + "titleZh": "浏览器与桌面控制", + "titleEn": "Browser & desktop control", + "summaryZh": "授权 Agent 操作浏览器或本机界面,并明确管理辅助功能、屏幕录制与浏览器连接。", + "summaryEn": "Allow agents to operate a browser or local UI while explicitly managing accessibility, screen-recording, and browser connection access.", + "keywordsZh": [ + "Computer Use", + "桌面控制", + "浏览器控制", + "CDP", + "辅助功能", + "屏幕录制" + ], + "keywordsEn": [ + "computer use", + "desktop control", + "browser control", + "CDP", + "accessibility", + "screen recording" + ], + "highlightsZh": [ + "启用或停用 Computer Use", + "连接受支持的浏览器", + "检查并打开系统权限设置" + ], + "highlightsEn": [ + "Enable or disable Computer Use", + "Connect a supported browser", + "Inspect and open OS permission settings" + ], + "items": [ + { + "id": "status", + "titleZh": "检查 Computer Use 可用性、辅助功能和屏幕录制授权状态", + "titleEn": "Check Computer Use availability plus accessibility and screen-recording permission status" + }, + { + "id": "request-permissions", + "titleZh": "请求桌面控制所需的系统权限", + "titleEn": "Request the operating-system permissions required for desktop control" + }, + { + "id": "system-settings", + "titleZh": "直接打开对应的系统隐私与安全设置", + "titleEn": "Open the matching operating-system privacy and security settings" + }, + { + "id": "browser-discovery", + "titleZh": "发现受支持的浏览器并查看当前 CDP 连接状态", + "titleEn": "Discover supported browsers and inspect the current CDP connection state" + }, + { + "id": "launch-connect", + "titleZh": "启动浏览器控制或连接已经开放 CDP 的浏览器", + "titleEn": "Launch browser control or connect to a browser that already exposes CDP" + }, + { + "id": "default-cdp", + "titleZh": "启用默认 CDP 配置并按需要重启浏览器", + "titleEn": "Enable the default CDP setup and restart the browser when required" + }, + { + "id": "agent-actions", + "titleZh": "授权后让 Agent 截图、点击、输入、滚动并读取可见界面", + "titleEn": "After authorization, let agents capture, click, type, scroll, and inspect the visible interface" + } + ], + "stepsZh": [ + "打开执行控制设置", + "启用需要的能力", + "按提示授予系统权限或连接浏览器" + ], + "stepsEn": [ + "Open Execution Control settings", + "Enable the required capability", + "Grant OS access or connect a browser when prompted" + ], + "agentExamplesZh": [ + "打开桌面控制设置", + "带我配置浏览器控制" + ], + "agentExamplesEn": [ + "Open desktop-control settings", + "Take me to browser-control setup" + ], + "destination": { + "kind": "settings", + "pageId": "tools.execution" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.computer-use", + "浏览器与桌面控制", + "Browser & desktop control", + "项目与开发", + "Projects & development", + "Computer Use", + "桌面控制", + "浏览器控制", + "CDP", + "辅助功能", + "屏幕录制", + "computer use", + "desktop control", + "browser control", + "accessibility", + "screen recording", + "启用或停用 Computer Use", + "连接受支持的浏览器", + "检查并打开系统权限设置", + "Enable or disable Computer Use", + "Connect a supported browser", + "Inspect and open OS permission settings", + "检查 Computer Use 可用性、辅助功能和屏幕录制授权状态", + "Check Computer Use availability plus accessibility and screen-recording permission status", + "请求桌面控制所需的系统权限", + "Request the operating-system permissions required for desktop control", + "直接打开对应的系统隐私与安全设置", + "Open the matching operating-system privacy and security settings", + "发现受支持的浏览器并查看当前 CDP 连接状态", + "Discover supported browsers and inspect the current CDP connection state", + "启动浏览器控制或连接已经开放 CDP 的浏览器", + "Launch browser control or connect to a browser that already exposes CDP", + "启用默认 CDP 配置并按需要重启浏览器", + "Enable the default CDP setup and restart the browser when required", + "授权后让 Agent 截图、点击、输入、滚动并读取可见界面", + "After authorization, let agents capture, click, type, scroll, and inspect the visible interface" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.computer-use/" + }, + { + "id": "feature.skills", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Skills 技能", + "titleEn": "Skills", + "summaryZh": "为 Agent 安装和管理可复用的专业工作流,并控制哪些模式可以使用它们。", + "summaryEn": "Install and manage reusable expert workflows for agents, and control which modes can use them.", + "keywordsZh": [ + "Skill", + "技能", + "工作流", + "技能市场", + "安装技能" + ], + "keywordsEn": [ + "skill", + "workflow", + "skill market", + "install skill", + "agent capability" + ], + "highlightsZh": [ + "浏览与搜索 Skills", + "安装、更新或移除 Skill", + "按模式启用或停用" + ], + "highlightsEn": [ + "Browse and search Skills", + "Install, update, or remove a Skill", + "Enable or disable by mode" + ], + "items": [ + { + "id": "installed-catalog", + "titleZh": "统一查看用户级、项目级、本地和远程来源的已安装 Skills", + "titleEn": "Browse installed Skills from user, project, local, and remote sources in one catalog" + }, + { + "id": "market", + "titleZh": "浏览、搜索和刷新 Skill 市场", + "titleEn": "Browse, search, and refresh the Skill market" + }, + { + "id": "market-install", + "titleZh": "把市场 Skill 下载到用户级或当前项目", + "titleEn": "Download a market Skill for the user or current project" + }, + { + "id": "local-add", + "titleZh": "校验本地 Skill 路径并添加到用户级或项目级", + "titleEn": "Validate a local Skill path and add it at user or project scope" + }, + { + "id": "remove", + "titleZh": "删除已安装的用户级或项目级 Skill", + "titleEn": "Remove an installed user-level or project-level Skill" + }, + { + "id": "global-enable", + "titleZh": "在全局范围启用或停用单个 Skill", + "titleEn": "Enable or disable an individual Skill globally" + }, + { + "id": "mode-selection", + "titleZh": "按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择", + "titleEn": "Choose Skills and skill groups per agent mode and restore defaults" + }, + { + "id": "shadowing", + "titleZh": "识别同名 Skill 的用户级与项目级遮蔽优先级", + "titleEn": "Understand user-versus-project shadowing precedence for same-named Skills" + } + ], + "stepsZh": [ + "打开 Skills", + "搜索需要的工作流", + "安装后在会话中调用" + ], + "stepsEn": [ + "Open Skills", + "Search for the workflow you need", + "Install it and invoke it from a session" + ], + "agentExamplesZh": [ + "打开 Skills", + "带我去技能管理" + ], + "agentExamplesEn": [ + "Open Skills", + "Take me to skill management" + ], + "destination": { + "kind": "action", + "actionId": "surface.skills.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.skills", + "Skills 技能", + "Skills", + "扩展与自动化", + "Extensions & automation", + "Skill", + "技能", + "工作流", + "技能市场", + "安装技能", + "skill", + "workflow", + "skill market", + "install skill", + "agent capability", + "浏览与搜索 Skills", + "安装、更新或移除 Skill", + "按模式启用或停用", + "Browse and search Skills", + "Install, update, or remove a Skill", + "Enable or disable by mode", + "统一查看用户级、项目级、本地和远程来源的已安装 Skills", + "Browse installed Skills from user, project, local, and remote sources in one catalog", + "浏览、搜索和刷新 Skill 市场", + "Browse, search, and refresh the Skill market", + "把市场 Skill 下载到用户级或当前项目", + "Download a market Skill for the user or current project", + "校验本地 Skill 路径并添加到用户级或项目级", + "Validate a local Skill path and add it at user or project scope", + "删除已安装的用户级或项目级 Skill", + "Remove an installed user-level or project-level Skill", + "在全局范围启用或停用单个 Skill", + "Enable or disable an individual Skill globally", + "按 Agent 模式选择 Skill 与 Skill 组,并可恢复默认选择", + "Choose Skills and skill groups per agent mode and restore defaults", + "识别同名 Skill 的用户级与项目级遮蔽优先级", + "Understand user-versus-project shadowing precedence for same-named Skills" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.skills/" + }, + { + "id": "feature.miniapps", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Mini Apps 小应用", + "titleEn": "Mini Apps", + "summaryZh": "在 BitFun 内安装、创建和运行轻量应用,让界面、数据与 Agent 工作流组合在一起。", + "summaryEn": "Install, create, and run lightweight apps inside BitFun, combining UI, data, and agent workflows.", + "keywordsZh": [ + "Mini App", + "小应用", + "应用市场", + "创建应用", + "运行应用" + ], + "keywordsEn": [ + "mini app", + "app market", + "create app", + "run app", + "embedded app" + ], + "highlightsZh": [ + "浏览 Mini App 市场", + "安装或创建 Mini App", + "在独立场景中运行并与 Agent 对话" + ], + "highlightsEn": [ + "Browse the Mini App market", + "Install or create a Mini App", + "Run it in its own scene and chat with its agent" + ], + "items": [ + { + "id": "gallery-lifecycle", + "titleZh": "查看、搜索、创建、导入、编辑和删除 Mini App", + "titleEn": "Browse, search, create, import, edit, and delete Mini Apps" + }, + { + "id": "market", + "titleZh": "浏览市场、查看详情并安装或更新发布版本", + "titleEn": "Browse the market, inspect listings, and install or update releases" + }, + { + "id": "market-account", + "titleZh": "登录市场账户并收藏、评分和查看已安装来源", + "titleEn": "Sign in to the market, favorite and rate apps, and inspect installed origins" + }, + { + "id": "permissions", + "titleZh": "按路径或工作区授予权限,并在定制前审查权限差异", + "titleEn": "Grant path or workspace access and review permission changes before customization" + }, + { + "id": "runtime", + "titleZh": "运行 Mini App Host 与 Worker,查看状态并停止后台 Worker", + "titleEn": "Run Mini App host and worker calls, inspect status, and stop background workers" + }, + { + "id": "storage", + "titleZh": "为正式应用和定制草稿分别读取与保存持久状态", + "titleEn": "Read and save persistent state separately for installed apps and customization drafts" + }, + { + "id": "agent-ai", + "titleZh": "在 Mini App 中调用模型补全、聊天和专属 Agent 会话", + "titleEn": "Use model completion, chat, and dedicated agent sessions inside Mini Apps" + }, + { + "id": "customization", + "titleZh": "创建定制草稿、实时预览,并应用、同步或丢弃修改", + "titleEn": "Create customization drafts, preview them live, and apply, sync, or discard changes" + }, + { + "id": "versions", + "titleZh": "查看版本历史并回滚到旧版本", + "titleEn": "Inspect version history and roll back to an earlier release" + }, + { + "id": "publishing", + "titleZh": "提交、撤回和审查市场发布,并可渲染幻灯片页面", + "titleEn": "Submit, withdraw, and review market releases, and render slide pages" + } + ], + "stepsZh": [ + "打开 Mini Apps", + "选择市场、已安装或创建", + "打开应用并按页面提示使用" + ], + "stepsEn": [ + "Open Mini Apps", + "Choose Market, Installed, or Create", + "Launch the app and follow its interface" + ], + "agentExamplesZh": [ + "打开 Mini Apps", + "带我去小应用市场" + ], + "agentExamplesEn": [ + "Open Mini Apps", + "Take me to the Mini App market" + ], + "destination": { + "kind": "action", + "actionId": "surface.miniapps.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.miniapps", + "Mini Apps 小应用", + "Mini Apps", + "扩展与自动化", + "Extensions & automation", + "Mini App", + "小应用", + "应用市场", + "创建应用", + "运行应用", + "mini app", + "app market", + "create app", + "run app", + "embedded app", + "浏览 Mini App 市场", + "安装或创建 Mini App", + "在独立场景中运行并与 Agent 对话", + "Browse the Mini App market", + "Install or create a Mini App", + "Run it in its own scene and chat with its agent", + "查看、搜索、创建、导入、编辑和删除 Mini App", + "Browse, search, create, import, edit, and delete Mini Apps", + "浏览市场、查看详情并安装或更新发布版本", + "Browse the market, inspect listings, and install or update releases", + "登录市场账户并收藏、评分和查看已安装来源", + "Sign in to the market, favorite and rate apps, and inspect installed origins", + "按路径或工作区授予权限,并在定制前审查权限差异", + "Grant path or workspace access and review permission changes before customization", + "运行 Mini App Host 与 Worker,查看状态并停止后台 Worker", + "Run Mini App host and worker calls, inspect status, and stop background workers", + "为正式应用和定制草稿分别读取与保存持久状态", + "Read and save persistent state separately for installed apps and customization drafts", + "在 Mini App 中调用模型补全、聊天和专属 Agent 会话", + "Use model completion, chat, and dedicated agent sessions inside Mini Apps", + "创建定制草稿、实时预览,并应用、同步或丢弃修改", + "Create customization drafts, preview them live, and apply, sync, or discard changes", + "查看版本历史并回滚到旧版本", + "Inspect version history and roll back to an earlier release", + "提交、撤回和审查市场发布,并可渲染幻灯片页面", + "Submit, withdraw, and review market releases, and render slide pages" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.miniapps/" + }, + { + "id": "feature.canvas", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Canvas 与交互产物", + "titleEn": "Canvas & interactive artifacts", + "summaryZh": "在会话旁展示和保存 Agent 生成的可视化、交互页面与结构化产物。", + "summaryEn": "Display and save visualizations, interactive pages, and structured artifacts generated beside a session.", + "keywordsZh": [ + "Canvas", + "画布", + "可视化", + "交互产物", + "Artifact" + ], + "keywordsEn": [ + "canvas", + "visualization", + "interactive artifact", + "artifact", + "preview" + ], + "highlightsZh": [ + "在会话中打开交互内容", + "保留画布状态", + "在面板中查看运行错误" + ], + "highlightsEn": [ + "Open interactive content from a session", + "Persist canvas state", + "Inspect runtime errors in the panel" + ], + "items": [ + { + "id": "artifact-open", + "titleZh": "从会话工具结果加载并打开持久化 Canvas 产物", + "titleEn": "Load and open persistent Canvas artifacts from session tool results" + }, + { + "id": "html-react", + "titleZh": "渲染 HTML 或 React 交互界面、图表和可视化", + "titleEn": "Render HTML or React interfaces, charts, and interactive visualizations" + }, + { + "id": "state", + "titleZh": "在重新打开或刷新 Canvas 时加载和保存交互状态", + "titleEn": "Load and save interactive state when a Canvas is reopened or refreshed" + }, + { + "id": "source-inspection", + "titleZh": "查看 Canvas 源码、编译版本和最后可用版本", + "titleEn": "Inspect Canvas source, compiled revisions, and the last known good revision" + }, + { + "id": "element-context", + "titleZh": "选择 Canvas 内的元素并把元素引用加入会话上下文", + "titleEn": "Select an element inside Canvas and add its reference to session context" + }, + { + "id": "runtime-errors", + "titleZh": "捕获运行错误、上报诊断并请求 Agent 自动修复", + "titleEn": "Capture runtime errors, report diagnostics, and ask the agent to repair them" + }, + { + "id": "export-html", + "titleZh": "把当前 Canvas 导出为可独立打开的 HTML 文件", + "titleEn": "Export the current Canvas as a standalone HTML file" + } + ], + "stepsZh": [ + "打开一个 AI 会话", + "让 Agent 创建可视化或交互工具", + "从工具结果打开 Canvas" + ], + "stepsEn": [ + "Open an AI session", + "Ask the agent for a visualization or interactive tool", + "Open the Canvas from the tool result" + ], + "agentExamplesZh": [ + "打开 AI 助手,我想做一个交互可视化", + "创建一个可交互的 Canvas" + ], + "agentExamplesEn": [ + "Open the AI assistant; I want an interactive visualization", + "Create an interactive Canvas" + ], + "destination": { + "kind": "scene", + "sceneId": "session" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.canvas", + "Canvas 与交互产物", + "Canvas & interactive artifacts", + "扩展与自动化", + "Extensions & automation", + "Canvas", + "画布", + "可视化", + "交互产物", + "Artifact", + "canvas", + "visualization", + "interactive artifact", + "artifact", + "preview", + "在会话中打开交互内容", + "保留画布状态", + "在面板中查看运行错误", + "Open interactive content from a session", + "Persist canvas state", + "Inspect runtime errors in the panel", + "从会话工具结果加载并打开持久化 Canvas 产物", + "Load and open persistent Canvas artifacts from session tool results", + "渲染 HTML 或 React 交互界面、图表和可视化", + "Render HTML or React interfaces, charts, and interactive visualizations", + "在重新打开或刷新 Canvas 时加载和保存交互状态", + "Load and save interactive state when a Canvas is reopened or refreshed", + "查看 Canvas 源码、编译版本和最后可用版本", + "Inspect Canvas source, compiled revisions, and the last known good revision", + "选择 Canvas 内的元素并把元素引用加入会话上下文", + "Select an element inside Canvas and add its reference to session context", + "捕获运行错误、上报诊断并请求 Agent 自动修复", + "Capture runtime errors, report diagnostics, and ask the agent to repair them", + "把当前 Canvas 导出为可独立打开的 HTML 文件", + "Export the current Canvas as a standalone HTML file" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.canvas/" + }, + { + "id": "feature.tasks-automation", + "kind": "feature", + "categoryId": "automation", + "titleZh": "任务板与定时任务", + "titleEn": "Task board & scheduled jobs", + "summaryZh": "集中查看待办事项,并让任务在指定时间或目标主机上持续运行。", + "summaryEn": "Track work in one task board and let scheduled jobs run at a chosen time or host.", + "keywordsZh": [ + "任务板", + "待办", + "Todo", + "定时任务", + "计划任务", + "Cron" + ], + "keywordsEn": [ + "task board", + "todo", + "scheduled job", + "automation", + "cron", + "recurring task" + ], + "highlightsZh": [ + "查看和整理待办", + "创建一次性或重复任务", + "为本地或远程工作区安排执行" + ], + "highlightsEn": [ + "Review and organize todos", + "Create one-time or recurring jobs", + "Schedule work for local or remote workspaces" + ], + "items": [ + { + "id": "board-views", + "titleZh": "按待处理、日历和已停用视图浏览任务", + "titleEn": "Browse tasks in Pending, Calendar, and Inactive views" + }, + { + "id": "create-edit", + "titleZh": "创建、编辑、启用、停用和删除定时任务", + "titleEn": "Create, edit, enable, disable, and delete scheduled jobs" + }, + { + "id": "schedule-types", + "titleZh": "设置一次性、每日、每周或自定义 Cron 时间表", + "titleEn": "Choose one-time, daily, weekly, or custom cron schedules" + }, + { + "id": "calendar-occurrences", + "titleZh": "在日历中预览任务的下一次与后续运行时间", + "titleEn": "Preview the next and future job occurrences on a calendar" + }, + { + "id": "agent-workspace", + "titleZh": "为任务选择 Agent、模型、工作模式和工作区", + "titleEn": "Choose the agent, model, work mode, and workspace for a job" + }, + { + "id": "local-remote-target", + "titleZh": "把任务安排在当前主机或已连接的远程目标上运行", + "titleEn": "Schedule jobs to run on the current host or a connected remote target" + }, + { + "id": "host-readiness", + "titleZh": "查看任务列表并等待桌面 Host 就绪后可靠执行", + "titleEn": "List jobs and wait for desktop-host readiness before reliable execution" + } + ], + "stepsZh": [ + "打开任务板", + "选择待办或定时任务", + "创建任务并确认运行目标与时间" + ], + "stepsEn": [ + "Open the Task Board", + "Choose todos or scheduled jobs", + "Create the job and confirm its target and timing" + ], + "agentExamplesZh": [ + "打开任务板", + "带我去看定时任务" + ], + "agentExamplesEn": [ + "Open the task board", + "Take me to scheduled jobs" + ], + "destination": { + "kind": "action", + "actionId": "surface.todos.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.tasks-automation", + "任务板与定时任务", + "Task board & scheduled jobs", + "扩展与自动化", + "Extensions & automation", + "任务板", + "待办", + "Todo", + "定时任务", + "计划任务", + "Cron", + "task board", + "todo", + "scheduled job", + "automation", + "cron", + "recurring task", + "查看和整理待办", + "创建一次性或重复任务", + "为本地或远程工作区安排执行", + "Review and organize todos", + "Create one-time or recurring jobs", + "Schedule work for local or remote workspaces", + "按待处理、日历和已停用视图浏览任务", + "Browse tasks in Pending, Calendar, and Inactive views", + "创建、编辑、启用、停用和删除定时任务", + "Create, edit, enable, disable, and delete scheduled jobs", + "设置一次性、每日、每周或自定义 Cron 时间表", + "Choose one-time, daily, weekly, or custom cron schedules", + "在日历中预览任务的下一次与后续运行时间", + "Preview the next and future job occurrences on a calendar", + "为任务选择 Agent、模型、工作模式和工作区", + "Choose the agent, model, work mode, and workspace for a job", + "把任务安排在当前主机或已连接的远程目标上运行", + "Schedule jobs to run on the current host or a connected remote target", + "查看任务列表并等待桌面 Host 就绪后可靠执行", + "List jobs and wait for desktop-host readiness before reliable execution" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.tasks-automation/" + }, + { + "id": "feature.insights", + "kind": "feature", + "categoryId": "automation", + "titleZh": "Insights 工作洞察", + "titleEn": "Insights", + "summaryZh": "把会话和项目活动汇总成可读的洞察,帮助回顾工作方式、用量和进展。", + "summaryEn": "Turn session and project activity into readable insights about working patterns, usage, and progress.", + "keywordsZh": [ + "洞察", + "分析", + "统计", + "工作报告", + "用量" + ], + "keywordsEn": [ + "insights", + "analytics", + "statistics", + "work report", + "usage" + ], + "highlightsZh": [ + "生成工作洞察", + "查看最新报告", + "结合 Token 用量理解成本" + ], + "highlightsEn": [ + "Generate work insights", + "Read the latest report", + "Relate activity to token usage" + ], + "items": [ + { + "id": "availability", + "titleZh": "检查当前账户与会话是否已有可分析的洞察数据", + "titleEn": "Check whether the current account and sessions contain analyzable insight data" + }, + { + "id": "generate", + "titleZh": "按所选日期范围和模型生成工作洞察报告", + "titleEn": "Generate a work-insights report for a selected date range and model" + }, + { + "id": "cancel", + "titleZh": "取消正在运行的洞察生成任务", + "titleEn": "Cancel an in-progress insights generation job" + }, + { + "id": "latest-report", + "titleZh": "查看最新报告或加载指定的历史报告", + "titleEn": "Open the latest report or load a selected historical report" + }, + { + "id": "usage-statistics", + "titleZh": "把工作活动与模型、Token 和缓存用量统计关联起来", + "titleEn": "Relate work activity to model, token, and cache-usage statistics" + }, + { + "id": "patterns", + "titleZh": "回顾项目分布、工作时段、任务类型和协作习惯", + "titleEn": "Review project distribution, working hours, task types, and collaboration patterns" + } + ], + "stepsZh": [ + "打开 Insights", + "选择可用的数据范围", + "生成或查看最新报告" + ], + "stepsEn": [ + "Open Insights", + "Choose the available data scope", + "Generate or read the latest report" + ], + "agentExamplesZh": [ + "打开 Insights", + "带我查看工作洞察" + ], + "agentExamplesEn": [ + "Open Insights", + "Show me my work insights" + ], + "destination": { + "kind": "action", + "actionId": "surface.insights.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.insights", + "Insights 工作洞察", + "Insights", + "扩展与自动化", + "Extensions & automation", + "洞察", + "分析", + "统计", + "工作报告", + "用量", + "insights", + "analytics", + "statistics", + "work report", + "usage", + "生成工作洞察", + "查看最新报告", + "结合 Token 用量理解成本", + "Generate work insights", + "Read the latest report", + "Relate activity to token usage", + "检查当前账户与会话是否已有可分析的洞察数据", + "Check whether the current account and sessions contain analyzable insight data", + "按所选日期范围和模型生成工作洞察报告", + "Generate a work-insights report for a selected date range and model", + "取消正在运行的洞察生成任务", + "Cancel an in-progress insights generation job", + "查看最新报告或加载指定的历史报告", + "Open the latest report or load a selected historical report", + "把工作活动与模型、Token 和缓存用量统计关联起来", + "Relate work activity to model, token, and cache-usage statistics", + "回顾项目分布、工作时段、任务类型和协作习惯", + "Review project distribution, working hours, task types, and collaboration patterns" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.insights/" + }, + { + "id": "feature.ecosystem-compatibility", + "kind": "feature", + "categoryId": "automation", + "titleZh": "外部 AI 生态兼容", + "titleEn": "External AI ecosystem compatibility", + "summaryZh": "发现并迁移 OpenCode、Claude Code、Codex 等外部 AI 工具的配置、命令、Hooks 与 MCP 资源。", + "summaryEn": "Discover and migrate configuration, commands, hooks, and MCP resources from OpenCode, Claude Code, Codex, and other AI tools.", + "keywordsZh": [ + "生态兼容", + "外部 AI", + "迁移配置", + "OpenCode", + "Claude Code", + "Codex", + "导入" + ], + "keywordsEn": [ + "ecosystem compatibility", + "external AI", + "configuration migration", + "OpenCode", + "Claude Code", + "Codex", + "import" + ], + "highlightsZh": [ + "扫描外部 AI 应用", + "预览冲突与迁移计划", + "按项导入提示词、Hooks、Agent 与 MCP" + ], + "highlightsEn": [ + "Scan external AI applications", + "Preview conflicts and migration plans", + "Import prompts, hooks, agents, and MCP selectively" + ], + "items": [ + { + "id": "source-discovery", + "titleZh": "发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容", + "titleEn": "Discover OpenCode, Claude Code, Codex, and other external AI sources and content" + }, + { + "id": "source-policy", + "titleZh": "按来源启用或停用集成,并选择管理、预览或只读策略", + "titleEn": "Enable or disable each source and choose managed, preview, or read-only policy" + }, + { + "id": "prompts-commands", + "titleZh": "展开外部 Prompt/Command 内容并处理与原生命令的冲突", + "titleEn": "Expand external prompt/command content and resolve conflicts with native commands" + }, + { + "id": "subagents", + "titleZh": "导入或启用外部 Agent,处理同名冲突并绑定模型", + "titleEn": "Import or enable external agents, resolve naming conflicts, and bind models" + }, + { + "id": "mcp-import", + "titleZh": "预览 MCP 导入计划,逐个处理服务器冲突并应用", + "titleEn": "Preview MCP import plans, resolve server conflicts individually, and apply them" + }, + { + "id": "tool-targets", + "titleZh": "选择外部工具目标、解决冲突并控制是否启用", + "titleEn": "Choose external tool targets, resolve conflicts, and control activation" + }, + { + "id": "hooks", + "titleZh": "查看外部 Hooks 目录、规划导入、修改选择并应用", + "titleEn": "Inspect external hook catalogs, plan imports, edit selections, and apply" + }, + { + "id": "security-review", + "titleZh": "在迁移前查看冲突、安全影响和来源控制快照", + "titleEn": "Review conflicts, security impact, and source-control snapshots before migration" + }, + { + "id": "reveal-source", + "titleZh": "在文件管理器或远程环境中定位外部配置来源", + "titleEn": "Reveal external configuration sources in the file manager or remote environment" + } + ], + "stepsZh": [ + "打开“生态兼容”", + "选择来源并查看扫描结果", + "确认计划后导入需要的内容" + ], + "stepsEn": [ + "Open Ecosystem Compatibility", + "Choose a source and review the scan", + "Confirm the plan and import selected content" + ], + "agentExamplesZh": [ + "打开外部 AI 生态兼容", + "我想迁移 Claude Code 的配置" + ], + "agentExamplesEn": [ + "Open external AI ecosystem compatibility", + "I want to migrate my Claude Code configuration" + ], + "destination": { + "kind": "action", + "actionId": "surface.ecosystemCompatibility.open" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.ecosystem-compatibility", + "外部 AI 生态兼容", + "External AI ecosystem compatibility", + "扩展与自动化", + "Extensions & automation", + "生态兼容", + "外部 AI", + "迁移配置", + "OpenCode", + "Claude Code", + "Codex", + "导入", + "ecosystem compatibility", + "external AI", + "configuration migration", + "import", + "扫描外部 AI 应用", + "预览冲突与迁移计划", + "按项导入提示词、Hooks、Agent 与 MCP", + "Scan external AI applications", + "Preview conflicts and migration plans", + "Import prompts, hooks, agents, and MCP selectively", + "发现 OpenCode、Claude Code、Codex 等外部 AI 来源与可用内容", + "Discover OpenCode, Claude Code, Codex, and other external AI sources and content", + "按来源启用或停用集成,并选择管理、预览或只读策略", + "Enable or disable each source and choose managed, preview, or read-only policy", + "展开外部 Prompt/Command 内容并处理与原生命令的冲突", + "Expand external prompt/command content and resolve conflicts with native commands", + "导入或启用外部 Agent,处理同名冲突并绑定模型", + "Import or enable external agents, resolve naming conflicts, and bind models", + "预览 MCP 导入计划,逐个处理服务器冲突并应用", + "Preview MCP import plans, resolve server conflicts individually, and apply them", + "选择外部工具目标、解决冲突并控制是否启用", + "Choose external tool targets, resolve conflicts, and control activation", + "查看外部 Hooks 目录、规划导入、修改选择并应用", + "Inspect external hook catalogs, plan imports, edit selections, and apply", + "在迁移前查看冲突、安全影响和来源控制快照", + "Review conflicts, security impact, and source-control snapshots before migration", + "在文件管理器或远程环境中定位外部配置来源", + "Reveal external configuration sources in the file manager or remote environment" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.ecosystem-compatibility/" + }, + { + "id": "feature.remote-workspaces", + "kind": "feature", + "categoryId": "connect", + "titleZh": "远程工作区", + "titleEn": "Remote workspaces", + "summaryZh": "通过 SSH 或容器在远程主机上打开项目,让文件、搜索、终端和 Agent 都在目标环境执行。", + "summaryEn": "Open projects over SSH or in containers so files, search, terminal, and agents all execute in the target environment.", + "keywordsZh": [ + "远程工作区", + "SSH", + "远程项目", + "容器", + "跳板机", + "远程开发" + ], + "keywordsEn": [ + "remote workspace", + "SSH", + "remote project", + "container", + "jump host", + "remote development" + ], + "highlightsZh": [ + "保存 SSH 连接配置", + "上传下载与远程文件操作", + "在远程环境运行终端和 Agent" + ], + "highlightsEn": [ + "Save SSH connection profiles", + "Transfer and edit remote files", + "Run terminals and agents in the remote environment" + ], + "items": [ + { + "id": "ssh-profiles", + "titleZh": "保存、列出、测试和删除 SSH 连接配置", + "titleEn": "Save, list, test, and delete SSH connection profiles" + }, + { + "id": "ssh-auth", + "titleZh": "使用密码、私钥、证书、SSH Config Host 与跳板机连接", + "titleEn": "Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts" + }, + { + "id": "docker", + "titleZh": "发现远程 Docker 容器并把容器作为工作环境", + "titleEn": "Discover remote Docker containers and use a container as the work environment" + }, + { + "id": "remote-open", + "titleZh": "打开、关闭和移除远程工作区,并读取服务器信息", + "titleEn": "Open, close, and remove remote workspaces, and inspect server information" + }, + { + "id": "remote-files", + "titleZh": "浏览、读取、写入、创建、重命名和删除远程文件与目录", + "titleEn": "Browse, read, write, create, rename, and remove remote files and directories" + }, + { + "id": "transfer", + "titleZh": "上传本地文件、下载远程文件并取消进行中的传输", + "titleEn": "Upload local files, download remote files, and cancel active transfers" + }, + { + "id": "remote-execution", + "titleZh": "在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面", + "titleEn": "Execute commands on the target so terminals, search, and agents use the remote data plane" + }, + { + "id": "port-forwarding", + "titleZh": "发现远程监听端口并启动、查看或停止端口转发", + "titleEn": "Discover remote listening ports and start, inspect, or stop port forwarding" + }, + { + "id": "connection-lifecycle", + "titleZh": "查看连接状态并断开单个或全部 SSH 会话", + "titleEn": "Inspect connection status and disconnect one or all SSH sessions" + } + ], + "stepsZh": [ + "打开新建项目", + "选择远程连接方式", + "配置主机并测试连接后打开工作区" + ], + "stepsEn": [ + "Open New Project", + "Choose a remote connection type", + "Configure and test the host, then open the workspace" + ], + "agentExamplesZh": [ + "打开远程项目配置", + "我想连接一个 SSH 工作区" + ], + "agentExamplesEn": [ + "Open remote-project setup", + "I want to connect to an SSH workspace" + ], + "destination": { + "kind": "action", + "actionId": "project.new" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.remote-workspaces", + "远程工作区", + "Remote workspaces", + "连接与发布", + "Connect & publish", + "SSH", + "远程项目", + "容器", + "跳板机", + "远程开发", + "remote workspace", + "remote project", + "container", + "jump host", + "remote development", + "保存 SSH 连接配置", + "上传下载与远程文件操作", + "在远程环境运行终端和 Agent", + "Save SSH connection profiles", + "Transfer and edit remote files", + "Run terminals and agents in the remote environment", + "保存、列出、测试和删除 SSH 连接配置", + "Save, list, test, and delete SSH connection profiles", + "使用密码、私钥、证书、SSH Config Host 与跳板机连接", + "Connect with passwords, private keys, certificates, SSH config hosts, and jump hosts", + "发现远程 Docker 容器并把容器作为工作环境", + "Discover remote Docker containers and use a container as the work environment", + "打开、关闭和移除远程工作区,并读取服务器信息", + "Open, close, and remove remote workspaces, and inspect server information", + "浏览、读取、写入、创建、重命名和删除远程文件与目录", + "Browse, read, write, create, rename, and remove remote files and directories", + "上传本地文件、下载远程文件并取消进行中的传输", + "Upload local files, download remote files, and cancel active transfers", + "在目标主机执行命令,让终端、搜索和 Agent 使用远程数据面", + "Execute commands on the target so terminals, search, and agents use the remote data plane", + "发现远程监听端口并启动、查看或停止端口转发", + "Discover remote listening ports and start, inspect, or stop port forwarding", + "查看连接状态并断开单个或全部 SSH 会话", + "Inspect connection status and disconnect one or all SSH sessions" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.remote-workspaces/" + }, + { + "id": "feature.remote-connect", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Remote Connect 与多设备", + "titleEn": "Remote Connect & devices", + "summaryZh": "从手机、Bot 或另一台 BitFun 设备连接当前主机,远程查看会话、回答权限并继续工作。", + "summaryEn": "Connect to this host from mobile, a bot, or another BitFun device to inspect sessions, answer permissions, and continue work remotely.", + "keywordsZh": [ + "Remote Connect", + "远程控制", + "手机", + "飞书", + "Telegram", + "微信", + "多设备", + "Peer Device", + "账户同步" + ], + "keywordsEn": [ + "remote connect", + "remote control", + "mobile", + "Feishu", + "Telegram", + "WeChat", + "multi-device", + "peer device", + "account sync" + ], + "highlightsZh": [ + "通过局域网、Ngrok 或自建 Relay 连接", + "接入飞书、Telegram 或微信 Bot", + "登录账户、同步会话并进入 Peer Device Mode" + ], + "highlightsEn": [ + "Connect through LAN, Ngrok, or a self-hosted relay", + "Use Feishu, Telegram, or WeChat bots", + "Sign in, sync sessions, and enter Peer Device Mode" + ], + "items": [ + { + "id": "connection-methods", + "titleZh": "选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器", + "titleEn": "Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server" + }, + { + "id": "start-stop-status", + "titleZh": "启动、停止 Remote Connect 并查看实时连接状态和设备信息", + "titleEn": "Start or stop Remote Connect and inspect live status and device information" + }, + { + "id": "network", + "titleZh": "查看局域网 IP、网络信息与可分享的连接配置", + "titleEn": "Inspect LAN IP, network details, and shareable connection configuration" + }, + { + "id": "bots", + "titleZh": "配置飞书、Telegram、微信等 Bot 并单独停止 Bot", + "titleEn": "Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently" + }, + { + "id": "relay-wizard", + "titleZh": "通过向导预检、安装 Docker、部署、注册并验证自建 Relay", + "titleEn": "Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard" + }, + { + "id": "account", + "titleZh": "登录、退出并查看账户状态和凭据提示", + "titleEn": "Sign in, sign out, and inspect account status and credential hints" + }, + { + "id": "devices", + "titleZh": "列出、连接、查看在线状态和删除同账户设备", + "titleEn": "List, connect, inspect online status, and remove same-account devices" + }, + { + "id": "session-sync", + "titleZh": "同步、导出、导入、删除或发送会话到另一台设备", + "titleEn": "Sync, export, import, delete, or send sessions to another device" + }, + { + "id": "settings-sync", + "titleZh": "在设备间自动或手动同步 BitFun 设置", + "titleEn": "Synchronize BitFun settings across devices automatically or on demand" + }, + { + "id": "peer-device", + "titleZh": "进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面", + "titleEn": "Enter Peer Device Mode and use another BitFun device as the command and event data plane" + } + ], + "stepsZh": [ + "打开 Remote Connect", + "选择网络、Bot 或账户", + "按向导连接并确认安全提示" + ], + "stepsEn": [ + "Open Remote Connect", + "Choose Network, Bot, or Account", + "Follow the connection flow and review its security notice" + ], + "agentExamplesZh": [ + "打开 Remote Connect", + "我想配置手机远程控制", + "带我管理已连接设备" + ], + "agentExamplesEn": [ + "Open Remote Connect", + "I want to configure mobile remote control", + "Take me to connected-device management" + ], + "destination": { + "kind": "event", + "eventName": "bitfun:open-remote-connect" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.remote-connect", + "Remote Connect 与多设备", + "Remote Connect & devices", + "连接与发布", + "Connect & publish", + "Remote Connect", + "远程控制", + "手机", + "飞书", + "Telegram", + "微信", + "多设备", + "Peer Device", + "账户同步", + "remote connect", + "remote control", + "mobile", + "Feishu", + "WeChat", + "multi-device", + "peer device", + "account sync", + "通过局域网、Ngrok 或自建 Relay 连接", + "接入飞书、Telegram 或微信 Bot", + "登录账户、同步会话并进入 Peer Device Mode", + "Connect through LAN, Ngrok, or a self-hosted relay", + "Use Feishu, Telegram, or WeChat bots", + "Sign in, sync sessions, and enter Peer Device Mode", + "选择局域网、Ngrok、官方 Relay、自建 Relay 或自定义服务器", + "Choose LAN, Ngrok, the hosted relay, a self-hosted relay, or a custom server", + "启动、停止 Remote Connect 并查看实时连接状态和设备信息", + "Start or stop Remote Connect and inspect live status and device information", + "查看局域网 IP、网络信息与可分享的连接配置", + "Inspect LAN IP, network details, and shareable connection configuration", + "配置飞书、Telegram、微信等 Bot 并单独停止 Bot", + "Configure Feishu, Telegram, WeChat, and other bots, and stop a bot independently", + "通过向导预检、安装 Docker、部署、注册并验证自建 Relay", + "Preflight, install Docker, deploy, register, and verify a self-hosted relay through the wizard", + "登录、退出并查看账户状态和凭据提示", + "Sign in, sign out, and inspect account status and credential hints", + "列出、连接、查看在线状态和删除同账户设备", + "List, connect, inspect online status, and remove same-account devices", + "同步、导出、导入、删除或发送会话到另一台设备", + "Sync, export, import, delete, or send sessions to another device", + "在设备间自动或手动同步 BitFun 设置", + "Synchronize BitFun settings across devices automatically or on demand", + "进入 Peer Device Mode,把另一台 BitFun 设备作为命令与事件数据面", + "Enter Peer Device Mode and use another BitFun device as the command and event data plane" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.remote-connect/" + }, + { + "id": "feature.detached-dispatch", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Detached Dispatch 远程派发", + "titleEn": "Detached Dispatch", + "summaryZh": "把可持续运行的任务派发到另一台 BitFun 主机;控制端可以断开,目标主机继续执行并保留记录。", + "summaryEn": "Dispatch durable work to another BitFun host; the controller may disconnect while the target continues and keeps the record.", + "keywordsZh": [ + "派发任务", + "Detached Dispatch", + "远程执行", + "目标主机", + "离线任务" + ], + "keywordsEn": [ + "detached dispatch", + "dispatch task", + "remote execution", + "target host", + "offline job" + ], + "highlightsZh": [ + "发现与探测目标主机", + "派发、继续或取消任务", + "断线后重新加载事件与执行记录" + ], + "highlightsEn": [ + "Discover and probe target hosts", + "Dispatch, continue, or cancel jobs", + "Reload events and execution history after reconnecting" + ], + "items": [ + { + "id": "targets", + "titleZh": "列出可派发目标并探测版本、连接和运行能力", + "titleEn": "List dispatch targets and probe their version, connectivity, and runtime capabilities" + }, + { + "id": "provision", + "titleZh": "为目标主机配置运行环境并安装或更新 BitFun CLI", + "titleEn": "Provision the target runtime and install or update the BitFun CLI" + }, + { + "id": "model-sync", + "titleZh": "在提交任务前同步目标所需的模型配置", + "titleEn": "Synchronize required model configuration before submitting a job" + }, + { + "id": "submit", + "titleZh": "把包含工作区、会话、模型和权限策略的持久任务提交到目标", + "titleEn": "Submit a durable job with workspace, session, model, and permission policy to the target" + }, + { + "id": "status-list", + "titleZh": "列出派发任务并查询运行状态、结果和错误", + "titleEn": "List dispatched jobs and query their status, result, and errors" + }, + { + "id": "transcript", + "titleZh": "保存、追加和重新加载可断线恢复的执行记录", + "titleEn": "Save, append, and reload reconnectable execution transcripts" + }, + { + "id": "permission-continuation", + "titleZh": "远程回答权限请求,并继续或取消目标端任务", + "titleEn": "Answer permission requests remotely and continue or cancel target-side work" + }, + { + "id": "result-sync", + "titleZh": "将目标端结果同步回控制端,而不把控制端当作远程文件系统代理", + "titleEn": "Synchronize target-side results back without treating the controller as a remote-filesystem proxy" + } + ], + "stepsZh": [ + "先在 Remote Connect 中登录并连接设备", + "从会话的派发入口选择目标", + "提交任务后在任务状态中跟踪" + ], + "stepsEn": [ + "Sign in and connect devices through Remote Connect", + "Choose a target from the session dispatch flow", + "Submit the work and follow its job status" + ], + "agentExamplesZh": [ + "打开设备管理,我想把任务派发到另一台机器", + "带我配置远程任务派发" + ], + "agentExamplesEn": [ + "Open device management so I can dispatch work to another machine", + "Take me to remote task dispatch setup" + ], + "destination": { + "kind": "event", + "eventName": "bitfun:open-remote-connect", + "detail": { + "group": "account" + } + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.detached-dispatch", + "Detached Dispatch 远程派发", + "Detached Dispatch", + "连接与发布", + "Connect & publish", + "派发任务", + "远程执行", + "目标主机", + "离线任务", + "detached dispatch", + "dispatch task", + "remote execution", + "target host", + "offline job", + "发现与探测目标主机", + "派发、继续或取消任务", + "断线后重新加载事件与执行记录", + "Discover and probe target hosts", + "Dispatch, continue, or cancel jobs", + "Reload events and execution history after reconnecting", + "列出可派发目标并探测版本、连接和运行能力", + "List dispatch targets and probe their version, connectivity, and runtime capabilities", + "为目标主机配置运行环境并安装或更新 BitFun CLI", + "Provision the target runtime and install or update the BitFun CLI", + "在提交任务前同步目标所需的模型配置", + "Synchronize required model configuration before submitting a job", + "把包含工作区、会话、模型和权限策略的持久任务提交到目标", + "Submit a durable job with workspace, session, model, and permission policy to the target", + "列出派发任务并查询运行状态、结果和错误", + "List dispatched jobs and query their status, result, and errors", + "保存、追加和重新加载可断线恢复的执行记录", + "Save, append, and reload reconnectable execution transcripts", + "远程回答权限请求,并继续或取消目标端任务", + "Answer permission requests remotely and continue or cancel target-side work", + "将目标端结果同步回控制端,而不把控制端当作远程文件系统代理", + "Synchronize target-side results back without treating the controller as a remote-filesystem proxy" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.detached-dispatch/" + }, + { + "id": "feature.pages", + "kind": "feature", + "categoryId": "connect", + "titleZh": "Pages 发布", + "titleEn": "Pages publishing", + "summaryZh": "保存页面版本并发布到公开或私有地址,管理标题、可见性、历史版本和分享链接。", + "summaryEn": "Save page versions and publish them to public or private URLs while managing titles, visibility, history, and share links.", + "keywordsZh": [ + "Pages", + "发布网页", + "页面托管", + "分享链接", + "版本", + "部署" + ], + "keywordsEn": [ + "pages", + "publish website", + "page hosting", + "share link", + "version", + "deploy" + ], + "highlightsZh": [ + "保存页面版本", + "发布、取消发布或删除页面", + "更新标题和访问可见性" + ], + "highlightsEn": [ + "Save page versions", + "Publish, unpublish, or delete pages", + "Update titles and access visibility" + ], + "items": [ + { + "id": "pages-list", + "titleZh": "查看账户下的 Pages 与每个页面的当前发布状态", + "titleEn": "List account Pages and inspect each page's current publishing state" + }, + { + "id": "immutable-versions", + "titleZh": "保存不可变页面版本并浏览版本历史", + "titleEn": "Save immutable page versions and browse version history" + }, + { + "id": "publish", + "titleZh": "发布或重新部署选中的页面版本", + "titleEn": "Publish or redeploy a selected page version" + }, + { + "id": "visibility", + "titleZh": "更新标题、公开/私有可见性和访问设置", + "titleEn": "Update titles, public/private visibility, and access settings" + }, + { + "id": "share-open", + "titleZh": "创建可打开和分享的页面链接", + "titleEn": "Create an openable, shareable link for a page" + }, + { + "id": "unpublish", + "titleZh": "取消发布页面,同时保留可再次发布的版本", + "titleEn": "Unpublish a page while retaining versions for later publication" + }, + { + "id": "delete", + "titleZh": "删除单个版本或整个 Page", + "titleEn": "Delete an individual version or an entire Page" + } + ], + "stepsZh": [ + "登录 BitFun 账户", + "打开 Pages", + "选择页面并确认发布与可见性" + ], + "stepsEn": [ + "Sign in to a BitFun account", + "Open Pages", + "Choose a page and confirm publishing and visibility" + ], + "agentExamplesZh": [ + "打开 Pages", + "带我管理已发布的页面" + ], + "agentExamplesEn": [ + "Open Pages", + "Take me to my published pages" + ], + "destination": { + "kind": "scene", + "sceneId": "pages" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.pages", + "Pages 发布", + "Pages publishing", + "连接与发布", + "Connect & publish", + "Pages", + "发布网页", + "页面托管", + "分享链接", + "版本", + "部署", + "pages", + "publish website", + "page hosting", + "share link", + "version", + "deploy", + "保存页面版本", + "发布、取消发布或删除页面", + "更新标题和访问可见性", + "Save page versions", + "Publish, unpublish, or delete pages", + "Update titles and access visibility", + "查看账户下的 Pages 与每个页面的当前发布状态", + "List account Pages and inspect each page's current publishing state", + "保存不可变页面版本并浏览版本历史", + "Save immutable page versions and browse version history", + "发布或重新部署选中的页面版本", + "Publish or redeploy a selected page version", + "更新标题、公开/私有可见性和访问设置", + "Update titles, public/private visibility, and access settings", + "创建可打开和分享的页面链接", + "Create an openable, shareable link for a page", + "取消发布页面,同时保留可再次发布的版本", + "Unpublish a page while retaining versions for later publication", + "删除单个版本或整个 Page", + "Delete an individual version or an entire Page" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.pages/" + }, + { + "id": "feature.voice-input", + "kind": "feature", + "categoryId": "application", + "titleZh": "语音输入", + "titleEn": "Voice input", + "summaryZh": "在聊天输入框中录音并转成文字,可选择本地模型、语言、麦克风与最长录音时间。", + "summaryEn": "Record speech in the chat composer and transcribe it to text, with control over local models, language, microphone, and duration.", + "keywordsZh": [ + "语音输入", + "录音", + "转写", + "麦克风", + "语音模型", + "听写" + ], + "keywordsEn": [ + "voice input", + "recording", + "transcription", + "microphone", + "speech model", + "dictation" + ], + "highlightsZh": [ + "下载和校验本地语音模型", + "选择识别语言与麦克风", + "在发送前编辑转写文本" + ], + "highlightsEn": [ + "Download and verify local speech models", + "Choose a recognition language and microphone", + "Edit transcribed text before sending" + ], + "items": [ + { + "id": "composer-recording", + "titleZh": "从聊天输入框开始、结束或取消一次录音", + "titleEn": "Start, finish, or cancel a recording from the chat composer" + }, + { + "id": "stream-audio", + "titleZh": "录音过程中分块传输音频并显示识别进度", + "titleEn": "Stream audio chunks during recording and show recognition progress" + }, + { + "id": "local-models", + "titleZh": "查看本地语音模型及安装、下载、验证、修复和删除状态", + "titleEn": "Browse local speech models and their install, download, verify, repair, and delete states" + }, + { + "id": "cancel-download", + "titleZh": "取消正在进行的语音模型下载", + "titleEn": "Cancel an in-progress speech-model download" + }, + { + "id": "language-microphone", + "titleZh": "选择自动检测或指定识别语言,并选择系统麦克风", + "titleEn": "Use automatic language detection or choose a language and system microphone" + }, + { + "id": "diagnostic-test", + "titleZh": "在设置页进行麦克风与语音识别测试并查看耗时和错误", + "titleEn": "Test the microphone and speech recognition in Settings, including timing and errors" + }, + { + "id": "edit-transcript", + "titleZh": "把转写结果放回输入框,在发送前继续编辑", + "titleEn": "Return the transcript to the composer for editing before sending" + } + ], + "stepsZh": [ + "打开输入设置的“语音”页", + "启用语音并准备模型", + "在聊天输入框点击麦克风开始录音" + ], + "stepsEn": [ + "Open the Voice input settings view", + "Enable voice and prepare a model", + "Use the microphone button in the chat composer" + ], + "agentExamplesZh": [ + "打开语音输入设置", + "帮我配置听写功能" + ], + "agentExamplesEn": [ + "Open voice-input settings", + "Help me configure dictation" + ], + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.voice-input", + "语音输入", + "Voice input", + "应用设置", + "Application settings", + "录音", + "转写", + "麦克风", + "语音模型", + "听写", + "voice input", + "recording", + "transcription", + "microphone", + "speech model", + "dictation", + "下载和校验本地语音模型", + "选择识别语言与麦克风", + "在发送前编辑转写文本", + "Download and verify local speech models", + "Choose a recognition language and microphone", + "Edit transcribed text before sending", + "从聊天输入框开始、结束或取消一次录音", + "Start, finish, or cancel a recording from the chat composer", + "录音过程中分块传输音频并显示识别进度", + "Stream audio chunks during recording and show recognition progress", + "查看本地语音模型及安装、下载、验证、修复和删除状态", + "Browse local speech models and their install, download, verify, repair, and delete states", + "取消正在进行的语音模型下载", + "Cancel an in-progress speech-model download", + "选择自动检测或指定识别语言,并选择系统麦克风", + "Use automatic language detection or choose a language and system microphone", + "在设置页进行麦克风与语音识别测试并查看耗时和错误", + "Test the microphone and speech recognition in Settings, including timing and errors", + "把转写结果放回输入框,在发送前继续编辑", + "Return the transcript to the composer for editing before sending" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.voice-input/" + }, + { + "id": "feature.desktop-pet", + "kind": "feature", + "categoryId": "application", + "titleZh": "Agent 桌面伙伴", + "titleEn": "Agent desktop companion", + "summaryZh": "在输入框或桌面上显示 Agent 伙伴,并选择、导入或管理 Petdex 角色包。", + "summaryEn": "Show an agent companion in the composer or on the desktop, and choose, import, or manage Petdex character packs.", + "keywordsZh": [ + "桌面宠物", + "Agent 伙伴", + "Petdex", + "像素宠物", + "角色包" + ], + "keywordsEn": [ + "desktop pet", + "agent companion", + "Petdex", + "pixel pet", + "character pack" + ], + "highlightsZh": [ + "在桌面或输入框显示伙伴", + "选择预设角色", + "导入和删除 Petdex 包" + ], + "highlightsEn": [ + "Show the companion on desktop or in the composer", + "Choose a preset character", + "Import and remove Petdex packs" + ], + "items": [ + { + "id": "enable", + "titleZh": "整体启用或停用 Agent 桌面伙伴", + "titleEn": "Enable or disable the agent desktop companion globally" + }, + { + "id": "display-modes", + "titleZh": "选择在聊天输入框、独立桌面窗口或两处显示", + "titleEn": "Show the companion in the chat composer, a desktop window, or both" + }, + { + "id": "presets", + "titleZh": "查看并切换内置 Petdex 角色预设", + "titleEn": "Browse and switch among built-in Petdex character presets" + }, + { + "id": "petdex-import", + "titleZh": "从本地 Petdex 包导入新的角色与动画", + "titleEn": "Import new characters and animations from a local Petdex package" + }, + { + "id": "petdex-delete", + "titleZh": "删除已导入的 Petdex 包并回退到可用角色", + "titleEn": "Delete an imported Petdex package and fall back to an available character" + }, + { + "id": "desktop-window", + "titleZh": "显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口", + "titleEn": "Show, hide, and resize the desktop companion window, and return to the main window" + } + ], + "stepsZh": [ + "打开桌面伙伴设置", + "启用伙伴并选择显示位置", + "选择预设或导入 Petdex 包" + ], + "stepsEn": [ + "Open Companion settings", + "Enable it and choose where it appears", + "Choose a preset or import a Petdex pack" + ], + "agentExamplesZh": [ + "打开桌面宠物设置", + "带我配置 Agent 伙伴" + ], + "agentExamplesEn": [ + "Open desktop-pet settings", + "Take me to agent-companion setup" + ], + "destination": { + "kind": "settings", + "pageId": "application.pet" + }, + "operations": [], + "options": [], + "searchTerms": [ + "feature.desktop-pet", + "Agent 桌面伙伴", + "Agent desktop companion", + "应用设置", + "Application settings", + "桌面宠物", + "Agent 伙伴", + "Petdex", + "像素宠物", + "角色包", + "desktop pet", + "agent companion", + "pixel pet", + "character pack", + "在桌面或输入框显示伙伴", + "选择预设角色", + "导入和删除 Petdex 包", + "Show the companion on desktop or in the composer", + "Choose a preset character", + "Import and remove Petdex packs", + "整体启用或停用 Agent 桌面伙伴", + "Enable or disable the agent desktop companion globally", + "选择在聊天输入框、独立桌面窗口或两处显示", + "Show the companion in the chat composer, a desktop window, or both", + "查看并切换内置 Petdex 角色预设", + "Browse and switch among built-in Petdex character presets", + "从本地 Petdex 包导入新的角色与动画", + "Import new characters and animations from a local Petdex package", + "删除已导入的 Petdex 包并回退到可用角色", + "Delete an imported Petdex package and fall back to an available character", + "显示、隐藏和调整独立桌面伙伴窗口大小,并可回到主窗口", + "Show, hide, and resize the desktop companion window, and return to the main window" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/feature.desktop-pet/" + }, + { + "id": "setting.application.general", + "kind": "setting", + "categoryId": "application", + "titleZh": "常规设置", + "titleEn": "General settings", + "summaryZh": "管理启动、更新、关闭行为、通知与睡眠保持等应用级偏好。", + "summaryEn": "Manage app-level preferences for startup, updates, close behavior, notifications, and sleep prevention.", + "keywordsZh": [ + "常规设置", + "开机启动", + "自动更新", + "通知", + "关闭按钮", + "阻止睡眠" + ], + "keywordsEn": [ + "general settings", + "launch at login", + "auto update", + "notifications", + "close button", + "prevent sleep" + ], + "highlightsZh": [ + "开机启动与自动更新", + "窗口关闭和托盘行为", + "任务完成、权限请求与启动提示通知" + ], + "highlightsEn": [ + "Launch-at-login and automatic updates", + "Window close and tray behavior", + "Completion, permission, and startup-tip notifications" + ], + "items": [ + { + "id": "automatic-updates", + "titleZh": "启用或停用自动检查更新", + "titleEn": "Enable or disable automatic update checks" + }, + { + "id": "manual-update", + "titleZh": "手动检查、下载并安装可用更新,然后按需重启", + "titleEn": "Check for, download, and install an available update manually, then restart when needed" + }, + { + "id": "launch-at-login", + "titleZh": "控制 BitFun 是否在登录系统后自动启动", + "titleEn": "Choose whether BitFun launches automatically after system sign-in" + }, + { + "id": "prevent-sleep", + "titleZh": "在长任务运行时阻止电脑自动睡眠", + "titleEn": "Prevent the computer from sleeping while long-running work is active" + }, + { + "id": "close-behavior", + "titleZh": "选择关闭主窗口时退出、最小化到托盘或每次询问", + "titleEn": "Choose whether closing the main window quits, minimizes to tray, or asks each time" + }, + { + "id": "notifications", + "titleZh": "分别控制任务完成、权限请求和启动提示通知", + "titleEn": "Control completion, permission-request, and startup-tip notifications independently" + }, + { + "id": "announcements", + "titleZh": "查看、标记已读、忽略或永久隐藏产品公告与提示", + "titleEn": "Review, mark seen, dismiss, or permanently hide product announcements and tips" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 常规”", + "修改开关;变更会自动保存" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > General", + "Change a control; updates are saved automatically" + ], + "agentExamplesZh": [ + "关闭自动更新", + "以后关闭窗口时最小化到托盘", + "打开常规设置" + ], + "agentExamplesEn": [ + "Turn off automatic updates", + "Minimize to tray when I close the window", + "Open General settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.general" + }, + "operations": [], + "options": [ + { + "id": "auto-update", + "titleZh": "自动检查更新", + "titleEn": "Automatic updates", + "descriptionZh": "启动后自动检查可用更新。", + "descriptionEn": "Check for available updates automatically after startup.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "app.auto_update" + } + }, + { + "id": "close-button-behavior", + "titleZh": "关闭按钮行为", + "titleEn": "Close button behavior", + "descriptionZh": "选择退出应用或最小化到托盘。", + "descriptionEn": "Choose whether closing quits the app or minimizes it to the tray.", + "valueSchema": { + "type": "string", + "enum": [ + "ask", + "minimize_to_tray", + "quit" + ] + }, + "handler": { + "kind": "config", + "path": "app.close_button_behavior" + } + }, + { + "id": "completion-notification", + "titleZh": "任务完成通知", + "titleEn": "Completion notifications", + "descriptionZh": "会话任务完成时发送系统通知。", + "descriptionEn": "Send an OS notification when session work completes.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "app.notifications.dialog_completion_notify" + } + }, + { + "id": "permission-notification", + "titleZh": "权限请求通知", + "titleEn": "Permission request notifications", + "descriptionZh": "Agent 等待权限确认时发送系统通知。", + "descriptionEn": "Send an OS notification when an agent waits for permission.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "app.notifications.permission_request_notify" + } + }, + { + "id": "startup-tips", + "titleZh": "启动提示", + "titleEn": "Startup tips", + "descriptionZh": "启动后显示功能提示。", + "descriptionEn": "Show product tips after startup.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "app.notifications.enable_startup_tips" + } + } + ], + "searchTerms": [ + "setting.application.general", + "常规设置", + "General settings", + "应用设置", + "Application settings", + "开机启动", + "自动更新", + "通知", + "关闭按钮", + "阻止睡眠", + "general settings", + "launch at login", + "auto update", + "notifications", + "close button", + "prevent sleep", + "开机启动与自动更新", + "窗口关闭和托盘行为", + "任务完成、权限请求与启动提示通知", + "Launch-at-login and automatic updates", + "Window close and tray behavior", + "Completion, permission, and startup-tip notifications", + "启用或停用自动检查更新", + "Enable or disable automatic update checks", + "手动检查、下载并安装可用更新,然后按需重启", + "Check for, download, and install an available update manually, then restart when needed", + "控制 BitFun 是否在登录系统后自动启动", + "Choose whether BitFun launches automatically after system sign-in", + "在长任务运行时阻止电脑自动睡眠", + "Prevent the computer from sleeping while long-running work is active", + "选择关闭主窗口时退出、最小化到托盘或每次询问", + "Choose whether closing the main window quits, minimizes to tray, or asks each time", + "分别控制任务完成、权限请求和启动提示通知", + "Control completion, permission-request, and startup-tip notifications independently", + "查看、标记已读、忽略或永久隐藏产品公告与提示", + "Review, mark seen, dismiss, or permanently hide product announcements and tips" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.general/" + }, + { + "id": "setting.application.appearance", + "kind": "setting", + "categoryId": "application", + "titleZh": "外观与语言", + "titleEn": "Appearance & language", + "summaryZh": "切换主题与语言,调整字体和动效,并安装或导入外观包。", + "summaryEn": "Switch themes and languages, tune typography and motion, and install or import appearance packs.", + "keywordsZh": [ + "外观", + "主题", + "深色模式", + "浅色模式", + "语言", + "字体", + "动效", + "皮肤" + ], + "keywordsEn": [ + "appearance", + "theme", + "dark mode", + "light mode", + "language", + "font", + "motion", + "skin" + ], + "highlightsZh": [ + "系统、深色与浅色主题", + "界面语言与字号", + "鼠标光效、动效和外观包" + ], + "highlightsEn": [ + "System, dark, and light themes", + "UI language and font size", + "Mouse glow, motion, and appearance packs" + ], + "items": [ + { + "id": "built-in-appearance", + "titleZh": "选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观", + "titleEn": "Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances" + }, + { + "id": "language", + "titleZh": "切换简体中文、繁体中文、英文等受支持界面语言", + "titleEn": "Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages" + }, + { + "id": "ui-font-size", + "titleZh": "分别调整整个界面与聊天区字号,并支持自定义像素值", + "titleEn": "Adjust global UI and chat font sizes independently, including custom pixel values" + }, + { + "id": "visual-effects", + "titleZh": "控制鼠标光效,并让动态背景尊重系统的减少动效偏好", + "titleEn": "Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference" + }, + { + "id": "local-packages", + "titleZh": "导入、预览、应用、导出和删除本地外观包", + "titleEn": "Import, preview, apply, export, and delete local appearance packages" + }, + { + "id": "appearance-market", + "titleZh": "浏览、搜索、筛选并安装或更新 Skin 市场外观", + "titleEn": "Browse, search, filter, install, and update appearances from the Skin market" + }, + { + "id": "market-submissions", + "titleZh": "提交、查看和撤回自己的外观市场投稿", + "titleEn": "Submit, review, and withdraw your appearance-market submissions" + }, + { + "id": "market-review", + "titleZh": "在具备权限时查看并批准或拒绝外观投稿", + "titleEn": "When authorized, inspect and approve or reject appearance submissions" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 外观”", + "选择主题、语言或外观效果" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Appearance", + "Choose a theme, language, or visual effect" + ], + "agentExamplesZh": [ + "切换成深色主题", + "把界面语言改成英文", + "打开外观设置" + ], + "agentExamplesEn": [ + "Switch to the dark theme", + "Change the interface language to English", + "Open Appearance settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.appearance" + }, + "operations": [], + "options": [ + { + "id": "theme", + "titleZh": "主题", + "titleEn": "Theme", + "descriptionZh": "使用系统、BitFun 深色或 BitFun 浅色外观。", + "descriptionEn": "Use the system, BitFun dark, or BitFun light appearance.", + "valueSchema": { + "type": "string", + "enum": [ + "system", + "bitfun-dark", + "bitfun-light" + ] + }, + "handler": { + "kind": "appearanceSelection" + } + }, + { + "id": "language", + "titleZh": "界面语言", + "titleEn": "Interface language", + "descriptionZh": "设置 BitFun 的界面语言。", + "descriptionEn": "Set the BitFun interface language.", + "valueSchema": { + "type": "string", + "enum": [ + "en-US", + "zh-CN", + "zh-TW" + ] + }, + "handler": { + "kind": "language" + } + } + ], + "searchTerms": [ + "setting.application.appearance", + "外观与语言", + "Appearance & language", + "应用设置", + "Application settings", + "外观", + "主题", + "深色模式", + "浅色模式", + "语言", + "字体", + "动效", + "皮肤", + "appearance", + "theme", + "dark mode", + "light mode", + "language", + "font", + "motion", + "skin", + "系统、深色与浅色主题", + "界面语言与字号", + "鼠标光效、动效和外观包", + "System, dark, and light themes", + "UI language and font size", + "Mouse glow, motion, and appearance packs", + "选择跟随系统、浅色、深色、单色、Midnight、中国风、Cyber、Slate 或 Tokyo Night 等内置外观", + "Choose system, light, dark, monochrome, Midnight, China, Cyber, Slate, Tokyo Night, and other built-in appearances", + "切换简体中文、繁体中文、英文等受支持界面语言", + "Switch among Simplified Chinese, Traditional Chinese, English, and other supported UI languages", + "分别调整整个界面与聊天区字号,并支持自定义像素值", + "Adjust global UI and chat font sizes independently, including custom pixel values", + "控制鼠标光效,并让动态背景尊重系统的减少动效偏好", + "Control mouse-glow effects while dynamic backgrounds respect the system reduced-motion preference", + "导入、预览、应用、导出和删除本地外观包", + "Import, preview, apply, export, and delete local appearance packages", + "浏览、搜索、筛选并安装或更新 Skin 市场外观", + "Browse, search, filter, install, and update appearances from the Skin market", + "提交、查看和撤回自己的外观市场投稿", + "Submit, review, and withdraw your appearance-market submissions", + "在具备权限时查看并批准或拒绝外观投稿", + "When authorized, inspect and approve or reject appearance submissions" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.appearance/" + }, + { + "id": "setting.application.pet", + "kind": "setting", + "categoryId": "application", + "titleZh": "桌面伙伴设置", + "titleEn": "Companion settings", + "summaryZh": "启用 Agent 伙伴、选择显示位置,并管理当前角色。", + "summaryEn": "Enable the agent companion, choose where it appears, and manage the active character.", + "keywordsZh": [ + "桌面伙伴设置", + "桌面宠物", + "显示位置", + "Petdex" + ], + "keywordsEn": [ + "companion settings", + "desktop pet", + "display location", + "Petdex" + ], + "highlightsZh": [ + "启用或停用伙伴", + "桌面与输入框显示模式", + "角色选择与 Petdex 导入" + ], + "highlightsEn": [ + "Enable or disable the companion", + "Desktop and composer display modes", + "Character selection and Petdex import" + ], + "items": [ + { + "id": "enabled", + "titleZh": "整体启用或停用 Agent 伙伴", + "titleEn": "Enable or disable the agent companion" + }, + { + "id": "composer-display", + "titleZh": "控制伙伴是否显示在聊天输入框旁", + "titleEn": "Choose whether the companion appears beside the chat composer" + }, + { + "id": "desktop-display", + "titleZh": "控制伙伴是否显示为独立桌面窗口", + "titleEn": "Choose whether the companion appears as a standalone desktop window" + }, + { + "id": "preset-selection", + "titleZh": "从内置与已导入角色中选择当前伙伴", + "titleEn": "Choose the active companion from built-in and imported characters" + }, + { + "id": "import", + "titleZh": "导入本地 Petdex 角色包", + "titleEn": "Import a local Petdex character package" + }, + { + "id": "delete-refresh", + "titleZh": "刷新角色列表并删除不再需要的导入包", + "titleEn": "Refresh the character list and delete imported packages you no longer need" + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 桌面伙伴”", + "选择开关、位置和角色" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Companion", + "Choose its state, location, and character" + ], + "agentExamplesZh": [ + "关闭桌面伙伴", + "把 Agent 伙伴放到输入框里" + ], + "agentExamplesEn": [ + "Turn off the desktop companion", + "Put the agent companion in the composer" + ], + "destination": { + "kind": "settings", + "pageId": "application.pet" + }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用桌面伙伴", + "titleEn": "Enable companion", + "descriptionZh": "显示或隐藏 Agent 伙伴。", + "descriptionEn": "Show or hide the agent companion.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "enable_agent_companion" + ] + } + }, + { + "id": "display-mode", + "titleZh": "显示位置", + "titleEn": "Display location", + "descriptionZh": "在桌面或聊天输入框中显示。", + "descriptionEn": "Show on the desktop or in the chat composer.", + "valueSchema": { + "type": "string", + "enum": [ + "desktop", + "input" + ] + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "agent_companion_display_mode" + ] + } + } + ], + "searchTerms": [ + "setting.application.pet", + "桌面伙伴设置", + "Companion settings", + "应用设置", + "Application settings", + "桌面宠物", + "显示位置", + "Petdex", + "companion settings", + "desktop pet", + "display location", + "启用或停用伙伴", + "桌面与输入框显示模式", + "角色选择与 Petdex 导入", + "Enable or disable the companion", + "Desktop and composer display modes", + "Character selection and Petdex import", + "整体启用或停用 Agent 伙伴", + "Enable or disable the agent companion", + "控制伙伴是否显示在聊天输入框旁", + "Choose whether the companion appears beside the chat composer", + "控制伙伴是否显示为独立桌面窗口", + "Choose whether the companion appears as a standalone desktop window", + "从内置与已导入角色中选择当前伙伴", + "Choose the active companion from built-in and imported characters", + "导入本地 Petdex 角色包", + "Import a local Petdex character package", + "刷新角色列表并删除不再需要的导入包", + "Refresh the character list and delete imported packages you no longer need" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.pet/" + }, + { + "id": "setting.application.input", + "kind": "setting", + "categoryId": "application", + "titleZh": "输入与快捷键", + "titleEn": "Input & shortcuts", + "summaryZh": "配置语音输入、麦克风、识别语言以及键盘快捷键。", + "summaryEn": "Configure voice input, microphone, recognition language, and keyboard shortcuts.", + "keywordsZh": [ + "输入设置", + "语音", + "麦克风", + "快捷键", + "热键", + "键位" + ], + "keywordsEn": [ + "input settings", + "voice", + "microphone", + "shortcut", + "hotkey", + "keybinding" + ], + "highlightsZh": [ + "语音输入与本地模型", + "识别语言和最长录音时间", + "应用与编辑器快捷键" + ], + "highlightsEn": [ + "Voice input and local models", + "Recognition language and maximum recording time", + "App and editor shortcuts" + ], + "items": [ + { + "id": "voice-enabled", + "titleZh": "在聊天输入框启用或停用语音输入", + "titleEn": "Enable or disable voice input in the chat composer", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "language", + "titleZh": "选择自动检测或中文、粤语、英文、日文等识别语言", + "titleEn": "Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "microphone-test", + "titleZh": "选择麦克风并执行语音识别测试", + "titleEn": "Choose a microphone and run a speech-recognition test", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "local-models", + "titleZh": "下载、选择、验证、修复或删除本地语音模型", + "titleEn": "Download, select, verify, repair, or delete local speech models", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "recording-limit", + "titleZh": "设置单次语音输入的最长录音时间", + "titleEn": "Set the maximum duration of one voice-input recording", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "voice" + } + }, + { + "id": "shortcut-browser", + "titleZh": "搜索和查看全部应用、场景、编辑器与终端快捷键", + "titleEn": "Search and browse all app, scene, editor, and terminal shortcuts", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "shortcuts" + } + }, + { + "id": "shortcut-remap", + "titleZh": "录制新快捷键、检测冲突、恢复单项或重置全部自定义键位", + "titleEn": "Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings", + "destination": { + "kind": "settings", + "pageId": "application.input", + "viewId": "shortcuts" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 输入”", + "切换“语音”或“快捷键”视图" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Input", + "Switch between Voice and Shortcuts" + ], + "agentExamplesZh": [ + "打开快捷键设置", + "把语音输入的默认语言设为中文" + ], + "agentExamplesEn": [ + "Open keyboard-shortcut settings", + "Set the voice-input language to Chinese" + ], + "destination": { + "kind": "settings", + "pageId": "application.input" + }, + "operations": [], + "options": [ + { + "id": "voice-enabled", + "titleZh": "启用语音输入", + "titleEn": "Enable voice input", + "descriptionZh": "在聊天输入框显示并启用录音入口。", + "descriptionEn": "Show and enable recording in the chat composer.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "voice_input.enabled" + ] + } + }, + { + "id": "voice-language", + "titleZh": "默认识别语言", + "titleEn": "Default recognition language", + "descriptionZh": "选择自动检测、中文、英文、日文或粤语。", + "descriptionEn": "Choose automatic detection, Chinese, English, Japanese, or Cantonese.", + "valueSchema": { + "type": "string", + "enum": [ + "auto", + "zh", + "en", + "ja", + "yue" + ] + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "voice_input.default_language" + ] + } + }, + { + "id": "max-recording-seconds", + "titleZh": "最长录音时间", + "titleEn": "Maximum recording duration", + "descriptionZh": "单次语音输入允许的最长秒数。", + "descriptionEn": "Maximum seconds allowed for one voice input.", + "valueSchema": { + "type": "integer", + "minimum": 10, + "maximum": 600 + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "voice_input.max_recording_seconds" + ] + } + } + ], + "searchTerms": [ + "setting.application.input", + "输入与快捷键", + "Input & shortcuts", + "应用设置", + "Application settings", + "输入设置", + "语音", + "麦克风", + "快捷键", + "热键", + "键位", + "input settings", + "voice", + "microphone", + "shortcut", + "hotkey", + "keybinding", + "语音输入与本地模型", + "识别语言和最长录音时间", + "应用与编辑器快捷键", + "Voice input and local models", + "Recognition language and maximum recording time", + "App and editor shortcuts", + "在聊天输入框启用或停用语音输入", + "Enable or disable voice input in the chat composer", + "选择自动检测或中文、粤语、英文、日文等识别语言", + "Choose automatic detection or Chinese, Cantonese, English, Japanese, and other recognition languages", + "选择麦克风并执行语音识别测试", + "Choose a microphone and run a speech-recognition test", + "下载、选择、验证、修复或删除本地语音模型", + "Download, select, verify, repair, or delete local speech models", + "设置单次语音输入的最长录音时间", + "Set the maximum duration of one voice-input recording", + "搜索和查看全部应用、场景、编辑器与终端快捷键", + "Search and browse all app, scene, editor, and terminal shortcuts", + "录制新快捷键、检测冲突、恢复单项或重置全部自定义键位", + "Record new shortcuts, detect conflicts, revert one binding, or reset all custom bindings" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.input/" + }, + { + "id": "setting.application.development", + "kind": "setting", + "categoryId": "application", + "titleZh": "终端与编辑器设置", + "titleEn": "Terminal & editor settings", + "summaryZh": "选择默认 Shell,并调整代码编辑器的字体、缩进、换行、格式化与 Minimap。", + "summaryEn": "Choose the default shell and tune editor font, indentation, wrapping, formatting, and minimap behavior.", + "keywordsZh": [ + "开发设置", + "默认 Shell", + "编辑器", + "字体大小", + "缩进", + "自动换行", + "Minimap" + ], + "keywordsEn": [ + "development settings", + "default shell", + "editor", + "font size", + "indentation", + "word wrap", + "minimap" + ], + "highlightsZh": [ + "默认终端 Shell", + "编辑器字号与缩进", + "自动换行、格式化和 Minimap" + ], + "highlightsEn": [ + "Default terminal shell", + "Editor font size and indentation", + "Word wrapping, formatting, and minimap" + ], + "items": [ + { + "id": "default-shell", + "titleZh": "自动检测并选择默认终端 Shell", + "titleEn": "Automatically detect and choose the default terminal shell", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "terminal" + } + }, + { + "id": "terminal-position", + "titleZh": "把终端面板放在右侧或底部", + "titleEn": "Place the terminal panel on the right or at the bottom", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "terminal" + } + }, + { + "id": "editor-appearance", + "titleZh": "设置编辑器字体、字重、字号、行高与光标样式", + "titleEn": "Configure editor font, weight, size, line height, and cursor style", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "indent-wrap", + "titleZh": "设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动", + "titleEn": "Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "editor-display", + "titleZh": "控制 Minimap、空白字符、当前行高亮和滚动边界", + "titleEn": "Control the minimap, whitespace rendering, current-line highlight, and scroll bounds", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + }, + { + "id": "editor-advanced", + "titleZh": "控制语义高亮、括号配色、保存/粘贴时格式化和空白清理", + "titleEn": "Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming", + "destination": { + "kind": "settings", + "pageId": "application.development", + "viewId": "editor" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“应用 > 开发”", + "切换“终端”或“编辑器”视图" + ], + "stepsEn": [ + "Open Settings", + "Go to Application > Development", + "Switch between Terminal and Editor" + ], + "agentExamplesZh": [ + "把编辑器字号改成 15", + "打开终端设置" + ], + "agentExamplesEn": [ + "Set the editor font size to 15", + "Open terminal settings" + ], + "destination": { + "kind": "settings", + "pageId": "application.development" + }, + "operations": [], + "options": [ + { + "id": "editor-font-size", + "titleZh": "编辑器字号", + "titleEn": "Editor font size", + "descriptionZh": "设置代码编辑器的字体大小。", + "descriptionEn": "Set the code editor font size.", + "valueSchema": { + "type": "integer", + "minimum": 10, + "maximum": 32 + }, + "handler": { + "kind": "config", + "path": "editor.font_size" + } + } + ], + "searchTerms": [ + "setting.application.development", + "终端与编辑器设置", + "Terminal & editor settings", + "应用设置", + "Application settings", + "开发设置", + "默认 Shell", + "编辑器", + "字体大小", + "缩进", + "自动换行", + "Minimap", + "development settings", + "default shell", + "editor", + "font size", + "indentation", + "word wrap", + "minimap", + "默认终端 Shell", + "编辑器字号与缩进", + "自动换行、格式化和 Minimap", + "Default terminal shell", + "Editor font size and indentation", + "Word wrapping, formatting, and minimap", + "自动检测并选择默认终端 Shell", + "Automatically detect and choose the default terminal shell", + "把终端面板放在右侧或底部", + "Place the terminal panel on the right or at the bottom", + "设置编辑器字体、字重、字号、行高与光标样式", + "Configure editor font, weight, size, line height, and cursor style", + "设置 Tab 宽度、空格缩进、自动换行、行号与平滑滚动", + "Configure tab size, space indentation, word wrapping, line numbers, and smooth scrolling", + "控制 Minimap、空白字符、当前行高亮和滚动边界", + "Control the minimap, whitespace rendering, current-line highlight, and scroll bounds", + "控制语义高亮、括号配色、保存/粘贴时格式化和空白清理", + "Control semantic highlighting, bracket colors, format-on-save/paste, and whitespace trimming" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.application.development/" + }, + { + "id": "setting.ai.models", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "模型与供应商", + "titleEn": "Models & providers", + "summaryZh": "添加 AI 供应商和模型,选择默认模型,配置网络代理、订阅与流式超时。", + "summaryEn": "Add AI providers and models, choose defaults, and configure proxy, subscription, and streaming timeouts.", + "keywordsZh": [ + "模型设置", + "供应商", + "API Key", + "默认模型", + "代理", + "订阅", + "超时" + ], + "keywordsEn": [ + "model settings", + "provider", + "API key", + "default model", + "proxy", + "subscription", + "timeout" + ], + "highlightsZh": [ + "模型与供应商连接", + "主模型、快速模型和任务模型", + "代理、订阅与流式超时" + ], + "highlightsEn": [ + "Model and provider connections", + "Primary, fast, and task-specific defaults", + "Proxy, subscriptions, and streaming timeouts" + ], + "items": [ + { + "id": "providers", + "titleZh": "添加、编辑和删除内置或自定义 AI 供应商", + "titleEn": "Add, edit, and remove built-in or custom AI providers" + }, + { + "id": "credentials-endpoint", + "titleZh": "配置 API Key、Base URL、请求格式和模型列表", + "titleEn": "Configure API keys, base URLs, request formats, and model lists" + }, + { + "id": "subscription-auth", + "titleZh": "登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户", + "titleEn": "Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts" + }, + { + "id": "default-models", + "titleZh": "选择主模型、快速模型以及图像理解、图像生成和语音识别模型", + "titleEn": "Choose primary, fast, image-understanding, image-generation, and speech-recognition models" + }, + { + "id": "reasoning", + "titleZh": "为模型选择推理预设或自定义推理强度", + "titleEn": "Choose reasoning presets or a custom reasoning effort per model" + }, + { + "id": "proxy", + "titleZh": "配置 AI 请求使用的网络代理与绕过规则", + "titleEn": "Configure network proxies and bypass rules for AI requests" + }, + { + "id": "stream-timeouts", + "titleZh": "设置首 Token 等待和流式空闲超时", + "titleEn": "Set time-to-first-token and streaming idle timeouts" + }, + { + "id": "model-catalog", + "titleZh": "查看 models.dev 目录状态、手动刷新并定位本地缓存", + "titleEn": "Inspect models.dev catalog status, refresh it manually, and reveal its local cache" + }, + { + "id": "advanced-request", + "titleZh": "为供应商添加自定义 Header、请求体字段与 SSL 行为", + "titleEn": "Add custom headers, request-body fields, and SSL behavior per provider" + }, + { + "id": "connection-test", + "titleZh": "保存前测试供应商或模型连接并刷新运行时客户端", + "titleEn": "Test provider or model connectivity before saving and refresh the runtime client" + } + ], + "stepsZh": [ + "打开设置", + "进入“AI > 模型”", + "添加供应商并测试连接,再选择默认模型" + ], + "stepsEn": [ + "Open Settings", + "Go to AI > Models", + "Add and test a provider, then choose defaults" + ], + "agentExamplesZh": [ + "打开模型设置", + "带我配置默认模型", + "我想检查代理设置" + ], + "agentExamplesEn": [ + "Open model settings", + "Take me to default-model setup", + "I want to inspect proxy settings" + ], + "destination": { + "kind": "settings", + "pageId": "ai.models" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.ai.models", + "模型与供应商", + "Models & providers", + "AI 与协作", + "AI & collaboration", + "模型设置", + "供应商", + "API Key", + "默认模型", + "代理", + "订阅", + "超时", + "model settings", + "provider", + "API key", + "default model", + "proxy", + "subscription", + "timeout", + "模型与供应商连接", + "主模型、快速模型和任务模型", + "代理、订阅与流式超时", + "Model and provider connections", + "Primary, fast, and task-specific defaults", + "Proxy, subscriptions, and streaming timeouts", + "添加、编辑和删除内置或自定义 AI 供应商", + "Add, edit, and remove built-in or custom AI providers", + "配置 API Key、Base URL、请求格式和模型列表", + "Configure API keys, base URLs, request formats, and model lists", + "登录、刷新和退出 Codex、Antigravity、Grok、OpenCode 等订阅账户", + "Sign in, refresh, and sign out of Codex, Antigravity, Grok, OpenCode, and other subscription accounts", + "选择主模型、快速模型以及图像理解、图像生成和语音识别模型", + "Choose primary, fast, image-understanding, image-generation, and speech-recognition models", + "为模型选择推理预设或自定义推理强度", + "Choose reasoning presets or a custom reasoning effort per model", + "配置 AI 请求使用的网络代理与绕过规则", + "Configure network proxies and bypass rules for AI requests", + "设置首 Token 等待和流式空闲超时", + "Set time-to-first-token and streaming idle timeouts", + "查看 models.dev 目录状态、手动刷新并定位本地缓存", + "Inspect models.dev catalog status, refresh it manually, and reveal its local cache", + "为供应商添加自定义 Header、请求体字段与 SSL 行为", + "Add custom headers, request-body fields, and SSL behavior per provider", + "保存前测试供应商或模型连接并刷新运行时客户端", + "Test provider or model connectivity before saving and refresh the runtime client" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.ai.models/" + }, + { + "id": "setting.ai.memory", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "记忆设置", + "titleEn": "Memory settings", + "summaryZh": "控制 BitFun 是否从会话中提取和使用长期记忆,以及保留、整理和模型策略。", + "summaryEn": "Control whether BitFun extracts and uses long-term memory from sessions, including retention, consolidation, and model policy.", + "keywordsZh": [ + "记忆设置", + "长期记忆", + "学习", + "召回", + "整理", + "保留时间" + ], + "keywordsEn": [ + "memory settings", + "long-term memory", + "learning", + "recall", + "consolidation", + "retention" + ], + "highlightsZh": [ + "启用记忆生成与召回", + "BTW 会话与外部上下文策略", + "提取、整理模型和后台并发" + ], + "highlightsEn": [ + "Enable memory generation and recall", + "BTW sessions and external-context policy", + "Extraction, consolidation models, and background concurrency" + ], + "items": [ + { + "id": "generation-recall", + "titleZh": "分别控制长期记忆生成与会话召回,也可一键同时启用", + "titleEn": "Control long-term memory generation and recall independently or enable both together" + }, + { + "id": "btw", + "titleZh": "决定 BTW 轻量会话是否参与记忆生成", + "titleEn": "Choose whether lightweight BTW sessions contribute memories" + }, + { + "id": "external-context", + "titleZh": "存在外部工具上下文时选择清除工具结果、允许或跳过会话", + "titleEn": "When external tool context exists, clear tool results, allow it, or skip the session" + }, + { + "id": "rollout-policy", + "titleZh": "设置空闲时长、最大年龄、启动处理上限和扫描上限", + "titleEn": "Set idle time, maximum age, startup rollout limit, and scan limit" + }, + { + "id": "extraction", + "titleZh": "选择记忆提取模型、并发数和单次原始候选上限", + "titleEn": "Choose the extraction model, concurrency, and raw-candidate limit" + }, + { + "id": "retention", + "titleZh": "设置未使用记忆的最长保留天数", + "titleEn": "Set how long unused memories are retained" + }, + { + "id": "consolidation", + "titleZh": "选择记忆整理模型并让它跟随主模型或提取模型", + "titleEn": "Choose the consolidation model or make it follow the primary or extraction model" + }, + { + "id": "maintenance", + "titleZh": "打开记忆目录、恢复默认设置或显式清空全部记忆", + "titleEn": "Open the memory directory, restore defaults, or explicitly erase all memories" + } + ], + "stepsZh": [ + "打开设置", + "进入“AI > 记忆”", + "先启用记忆,再按需要调整高级参数" + ], + "stepsEn": [ + "Open Settings", + "Go to AI > Memory", + "Enable memory first, then tune advanced controls if needed" + ], + "agentExamplesZh": [ + "关闭长期记忆", + "允许 BTW 会话生成记忆", + "打开记忆设置" + ], + "agentExamplesEn": [ + "Turn off long-term memory", + "Allow BTW sessions to generate memories", + "Open Memory settings" + ], + "destination": { + "kind": "settings", + "pageId": "ai.memory" + }, + "operations": [], + "options": [ + { + "id": "enabled", + "titleZh": "启用记忆", + "titleEn": "Enable memory", + "descriptionZh": "同时启用记忆生成和召回。", + "descriptionEn": "Enable both memory generation and recall.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "memories", + "fields": [ + "generate_memories", + "use_memories" + ] + } + }, + { + "id": "btw-sessions", + "titleZh": "BTW 会话生成记忆", + "titleEn": "Generate memory from BTW sessions", + "descriptionZh": "允许轻量 BTW 会话参与记忆提取。", + "descriptionEn": "Allow lightweight BTW sessions to contribute memories.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "memories", + "fields": [ + "generate_for_btw_sessions" + ] + } + }, + { + "id": "external-context-policy", + "titleZh": "外部上下文策略", + "titleEn": "External context policy", + "descriptionZh": "决定存在外部工具上下文时如何生成记忆。", + "descriptionEn": "Choose how memory generation handles external tool context.", + "valueSchema": { + "type": "string", + "enum": [ + "clear_tool_results", + "allow", + "skip_session" + ] + }, + "handler": { + "kind": "mergeConfig", + "path": "memories", + "fields": [ + "external_context_policy" + ] + } + }, + { + "id": "startup-rollout-limit", + "titleZh": "每次启动整理上限", + "titleEn": "Startup rollout limit", + "descriptionZh": "每次启动最多处理的待整理记忆批次。", + "descriptionEn": "Maximum pending memory rollouts processed after startup.", + "valueSchema": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "handler": { + "kind": "mergeConfig", + "path": "memories", + "fields": [ + "max_rollouts_per_startup" + ] + } + } + ], + "searchTerms": [ + "setting.ai.memory", + "记忆设置", + "Memory settings", + "AI 与协作", + "AI & collaboration", + "长期记忆", + "学习", + "召回", + "整理", + "保留时间", + "memory settings", + "long-term memory", + "learning", + "recall", + "consolidation", + "retention", + "启用记忆生成与召回", + "BTW 会话与外部上下文策略", + "提取、整理模型和后台并发", + "Enable memory generation and recall", + "BTW sessions and external-context policy", + "Extraction, consolidation models, and background concurrency", + "分别控制长期记忆生成与会话召回,也可一键同时启用", + "Control long-term memory generation and recall independently or enable both together", + "决定 BTW 轻量会话是否参与记忆生成", + "Choose whether lightweight BTW sessions contribute memories", + "存在外部工具上下文时选择清除工具结果、允许或跳过会话", + "When external tool context exists, clear tool results, allow it, or skip the session", + "设置空闲时长、最大年龄、启动处理上限和扫描上限", + "Set idle time, maximum age, startup rollout limit, and scan limit", + "选择记忆提取模型、并发数和单次原始候选上限", + "Choose the extraction model, concurrency, and raw-candidate limit", + "设置未使用记忆的最长保留天数", + "Set how long unused memories are retained", + "选择记忆整理模型并让它跟随主模型或提取模型", + "Choose the consolidation model or make it follow the primary or extraction model", + "打开记忆目录、恢复默认设置或显式清空全部记忆", + "Open the memory directory, restore defaults, or explicitly erase all memories" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.ai.memory/" + }, + { + "id": "setting.workspace.session", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "会话与工作区设置", + "titleEn": "Session & workspace settings", + "summaryZh": "控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。", + "summaryEn": "Control session-title generation, accelerated workspace search, and project-context behavior.", + "keywordsZh": [ + "会话设置", + "工作区设置", + "标题生成", + "项目搜索", + "索引" + ], + "keywordsEn": [ + "session settings", + "workspace settings", + "title generation", + "project search", + "index" + ], + "highlightsZh": [ + "自动生成会话标题", + "本地工作区加速搜索", + "会话使用的标题模型" + ], + "highlightsEn": [ + "Automatic session titles", + "Accelerated local-workspace search", + "Model used for session titles" + ], + "items": [ + { + "id": "automatic-titles", + "titleZh": "启用或停用根据会话内容自动生成标题", + "titleEn": "Enable or disable automatic titles generated from session content" + }, + { + "id": "title-model", + "titleZh": "让标题模型继承主模型、快速模型或使用指定模型", + "titleEn": "Make title generation inherit the primary or fast model, or use a selected model" + }, + { + "id": "accelerated-search", + "titleZh": "为本地工作区启用 Flashgrep 加速搜索", + "titleEn": "Enable Flashgrep-backed accelerated search for local workspaces" + }, + { + "id": "search-index", + "titleZh": "查看索引状态并在需要时重建工作区索引", + "titleEn": "Inspect index status and rebuild the workspace index when needed" + }, + { + "id": "remote-behavior", + "titleZh": "远程工作区明确降级搜索实现,不把远程路径回退到本机", + "titleEn": "Use an explicit remote-workspace search path without silently falling back to local files" + } + ], + "stepsZh": [ + "打开设置", + "进入“工作区 > 会话与工作区”", + "调整标题或搜索选项" + ], + "stepsEn": [ + "Open Settings", + "Go to Workspace > Session & Workspace", + "Tune title or search controls" + ], + "agentExamplesZh": [ + "关闭自动生成会话标题", + "启用工作区加速搜索" + ], + "agentExamplesEn": [ + "Turn off automatic session titles", + "Enable accelerated workspace search" + ], + "destination": { + "kind": "settings", + "pageId": "workspace.session" + }, + "operations": [], + "options": [ + { + "id": "session-title-generation", + "titleZh": "自动生成会话标题", + "titleEn": "Automatic session titles", + "descriptionZh": "根据会话内容生成易识别的标题。", + "descriptionEn": "Generate a recognizable title from session content.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "enable_session_title_generation" + ] + } + }, + { + "id": "workspace-search", + "titleZh": "工作区加速搜索", + "titleEn": "Accelerated workspace search", + "descriptionZh": "为本地项目启用 Flashgrep 加速搜索。", + "descriptionEn": "Enable Flashgrep-backed search for local projects.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.ai_experience", + "fields": [ + "enable_workspace_search" + ] + } + } + ], + "searchTerms": [ + "setting.workspace.session", + "会话与工作区设置", + "Session & workspace settings", + "AI 与协作", + "AI & collaboration", + "会话设置", + "工作区设置", + "标题生成", + "项目搜索", + "索引", + "session settings", + "workspace settings", + "title generation", + "project search", + "index", + "自动生成会话标题", + "本地工作区加速搜索", + "会话使用的标题模型", + "Automatic session titles", + "Accelerated local-workspace search", + "Model used for session titles", + "启用或停用根据会话内容自动生成标题", + "Enable or disable automatic titles generated from session content", + "让标题模型继承主模型、快速模型或使用指定模型", + "Make title generation inherit the primary or fast model, or use a selected model", + "为本地工作区启用 Flashgrep 加速搜索", + "Enable Flashgrep-backed accelerated search for local workspaces", + "查看索引状态并在需要时重建工作区索引", + "Inspect index status and rebuild the workspace index when needed", + "远程工作区明确降级搜索实现,不把远程路径回退到本机", + "Use an explicit remote-workspace search path without silently falling back to local files" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.workspace.session/" + }, + { + "id": "setting.workspace.worktrees", + "kind": "setting", + "categoryId": "workspace", + "titleZh": "Worktree 设置", + "titleEn": "Worktree settings", + "summaryZh": "配置 Git Worktree 的根目录、分支前缀和自动清理规则,并查看现有隔离工作区。", + "summaryEn": "Configure the root, branch prefix, and cleanup rules for Git worktrees, and inspect existing isolated workspaces.", + "keywordsZh": [ + "Worktree 设置", + "并行分支", + "隔离工作区", + "分支前缀", + "自动清理" + ], + "keywordsEn": [ + "worktree settings", + "parallel branch", + "isolated workspace", + "branch prefix", + "automatic cleanup" + ], + "highlightsZh": [ + "Worktree 根目录与分支前缀", + "自动清理数量", + "现有 Worktree 和关联会话管理" + ], + "highlightsEn": [ + "Worktree root and branch prefix", + "Automatic cleanup count", + "Existing worktree and linked-session management" + ], + "items": [ + { + "id": "isolation", + "titleZh": "控制新会话是否默认使用独立 Git Worktree", + "titleEn": "Choose whether new sessions use isolated Git worktrees by default" + }, + { + "id": "root-path", + "titleZh": "设置受管 Worktree 的统一根目录", + "titleEn": "Set the common root directory for managed worktrees" + }, + { + "id": "branch-prefix", + "titleZh": "设置自动创建分支使用的名称前缀", + "titleEn": "Set the branch-name prefix used for automatically created branches" + }, + { + "id": "copy-changes", + "titleZh": "创建隔离工作区时选择是否复制当前未提交改动", + "titleEn": "Choose whether current uncommitted changes are copied into a new isolated workspace" + }, + { + "id": "auto-cleanup", + "titleZh": "启用自动清理并设置最多保留的受管 Worktree 数量", + "titleEn": "Enable automatic cleanup and set the maximum number of managed worktrees to retain" + }, + { + "id": "management", + "titleZh": "查看 Worktree 生命周期、脏状态、未发布提交与关联会话", + "titleEn": "Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions" + }, + { + "id": "open-restore-delete", + "titleZh": "打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree", + "titleEn": "Open or restore linked sessions and delete or force-delete a worktree after protection checks" + } + ], + "stepsZh": [ + "打开设置", + "进入“工作区 > Worktrees”", + "保存规则或管理现有 Worktree" + ], + "stepsEn": [ + "Open Settings", + "Go to Workspace > Worktrees", + "Save policy or manage existing worktrees" + ], + "agentExamplesZh": [ + "打开 Worktree 设置", + "带我管理并行工作区" + ], + "agentExamplesEn": [ + "Open Worktree settings", + "Take me to parallel-workspace management" + ], + "destination": { + "kind": "settings", + "pageId": "workspace.worktrees" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.workspace.worktrees", + "Worktree 设置", + "Worktree settings", + "项目与开发", + "Projects & development", + "并行分支", + "隔离工作区", + "分支前缀", + "自动清理", + "worktree settings", + "parallel branch", + "isolated workspace", + "branch prefix", + "automatic cleanup", + "Worktree 根目录与分支前缀", + "自动清理数量", + "现有 Worktree 和关联会话管理", + "Worktree root and branch prefix", + "Automatic cleanup count", + "Existing worktree and linked-session management", + "控制新会话是否默认使用独立 Git Worktree", + "Choose whether new sessions use isolated Git worktrees by default", + "设置受管 Worktree 的统一根目录", + "Set the common root directory for managed worktrees", + "设置自动创建分支使用的名称前缀", + "Set the branch-name prefix used for automatically created branches", + "创建隔离工作区时选择是否复制当前未提交改动", + "Choose whether current uncommitted changes are copied into a new isolated workspace", + "启用自动清理并设置最多保留的受管 Worktree 数量", + "Enable automatic cleanup and set the maximum number of managed worktrees to retain", + "查看 Worktree 生命周期、脏状态、未发布提交与关联会话", + "Inspect worktree lifecycle, dirty state, unpublished commits, and linked sessions", + "打开或恢复关联会话,并在保护检查后删除或强制删除 Worktree", + "Open or restore linked sessions and delete or force-delete a worktree after protection checks" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.workspace.worktrees/" + }, + { + "id": "setting.tools.execution", + "kind": "setting", + "categoryId": "assistant", + "titleZh": "执行与权限控制", + "titleEn": "Execution & permissions", + "summaryZh": "管理 Agent 工具权限、并行度、超时、延迟加载、Computer Use 与浏览器控制。", + "summaryEn": "Manage agent tool permissions, concurrency, timeouts, deferred loading, Computer Use, and browser control.", + "keywordsZh": [ + "执行控制", + "工具权限", + "审批", + "并行", + "超时", + "Computer Use", + "浏览器控制", + "JSON 修复" + ], + "keywordsEn": [ + "execution control", + "tool permissions", + "approval", + "parallel", + "timeout", + "computer use", + "browser control", + "JSON repair" + ], + "highlightsZh": [ + "询问、自动批准与完全访问策略", + "子 Agent 并行度和工具超时", + "Computer Use、浏览器连接与工具参数修复" + ], + "highlightsEn": [ + "Ask, auto-approve, and full-access policies", + "Subagent concurrency and tool timeouts", + "Computer Use, browser connection, and tool-argument repair" + ], + "items": [ + { + "id": "permission-mode", + "titleZh": "选择询问、自动批准或完全访问权限模式,并确认高风险警告", + "titleEn": "Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings" + }, + { + "id": "permission-selector", + "titleZh": "控制权限模式选择器是否显示在聊天输入框下方", + "titleEn": "Choose whether the permission-mode selector appears below the chat composer" + }, + { + "id": "global-project-rules", + "titleZh": "创建、排序和保存全局或项目级 Allow、Ask、Deny 规则", + "titleEn": "Create, reorder, and save global or project-level Allow, Ask, and Deny rules" + }, + { + "id": "remembered-grants", + "titleZh": "查看、撤销或清空项目中记住的权限授权与审计记录", + "titleEn": "Review, revoke, or clear remembered project permission grants and audit records" + }, + { + "id": "deferred-tools", + "titleZh": "按需延迟加载大型工具定义以减少 Agent 初始上下文", + "titleEn": "Load large tool definitions on demand to reduce initial agent context" + }, + { + "id": "parallelism", + "titleZh": "设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略", + "titleEn": "Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy" + }, + { + "id": "timeouts", + "titleZh": "设置权限确认等待和单次工具执行超时", + "titleEn": "Set permission-confirmation and per-tool execution timeouts" + }, + { + "id": "review-capacity", + "titleZh": "设置 Deep Review 最大并行评审者和队列等待时间", + "titleEn": "Set the maximum parallel Deep Review workers and queue wait time" + }, + { + "id": "computer-use", + "titleZh": "启用 Computer Use 并查看辅助功能与屏幕录制权限", + "titleEn": "Enable Computer Use and inspect accessibility and screen-recording permissions" + }, + { + "id": "browser-control", + "titleZh": "选择浏览器、配置默认 CDP 并控制启动时自动连接", + "titleEn": "Choose a browser, configure default CDP, and control automatic connection at startup" + }, + { + "id": "json-repair", + "titleZh": "控制是否在安全边界内修复模型生成的非法工具参数 JSON", + "titleEn": "Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > 执行与权限”", + "先确认安全影响,再修改权限或执行参数" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > Execution & Permissions", + "Review the security impact before changing permissions or execution controls" + ], + "agentExamplesZh": [ + "启用 Computer Use", + "把子 Agent 最大并发改为 8", + "打开权限设置" + ], + "agentExamplesEn": [ + "Enable Computer Use", + "Set maximum subagent concurrency to 8", + "Open permission settings" + ], + "destination": { + "kind": "settings", + "pageId": "tools.execution" + }, + "operations": [], + "options": [ + { + "id": "deferred-tool-loading", + "titleZh": "延迟加载工具", + "titleEn": "Deferred tool loading", + "descriptionZh": "按需加载大型工具定义,减少 Agent 初始上下文。", + "descriptionEn": "Load large tool definitions on demand to reduce initial agent context.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "ai.enable_deferred_tool_loading" + } + }, + { + "id": "subagent-batch-policy", + "titleZh": "子 Agent 批量执行策略", + "titleEn": "Subagent batch policy", + "descriptionZh": "选择仅安全任务并行、强制并行或串行执行。", + "descriptionEn": "Choose safe-only parallelism, forced parallelism, or serial execution.", + "valueSchema": { + "type": "string", + "enum": [ + "safe_only", + "force_parallel", + "serial" + ] + }, + "handler": { + "kind": "config", + "path": "ai.subagent_batch_execution_policy" + } + }, + { + "id": "subagent-max-concurrency", + "titleZh": "子 Agent 最大并发", + "titleEn": "Maximum subagent concurrency", + "descriptionZh": "限制同时运行的子 Agent 数量。", + "descriptionEn": "Limit the number of subagents that may run at once.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 32 + }, + "handler": { + "kind": "config", + "path": "ai.subagent_max_concurrency" + } + }, + { + "id": "swarm-max-concurrency", + "titleZh": "Swarm 最大并发", + "titleEn": "Maximum swarm concurrency", + "descriptionZh": "限制 Swarm 中同时执行的工作单元。", + "descriptionEn": "Limit concurrent work units inside a swarm.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 64 + }, + "handler": { + "kind": "config", + "path": "ai.swarm_max_concurrency" + } + }, + { + "id": "tool-timeout-seconds", + "titleZh": "工具执行超时", + "titleEn": "Tool execution timeout", + "descriptionZh": "单次工具调用的超时秒数。", + "descriptionEn": "Timeout in seconds for one tool call.", + "valueSchema": { + "type": "integer", + "minimum": 1, + "maximum": 86400 + }, + "handler": { + "kind": "config", + "path": "ai.tool_execution_timeout_secs" + } + }, + { + "id": "computer-use-enabled", + "titleZh": "Computer Use 桌面控制", + "titleEn": "Computer Use", + "descriptionZh": "允许 Agent 使用已授权的桌面控制能力。", + "descriptionEn": "Allow agents to use authorized desktop-control capabilities.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "ai.computer_use_enabled" + } + }, + { + "id": "browser-auto-connect", + "titleZh": "启动时连接浏览器", + "titleEn": "Connect browser on startup", + "descriptionZh": "BitFun 启动后自动尝试连接浏览器控制。", + "descriptionEn": "Automatically try to connect browser control after BitFun starts.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "ai.browser_control_auto_connect_on_startup" + } + }, + { + "id": "tool-json-repair", + "titleZh": "工具参数 JSON 修复", + "titleEn": "Tool-argument JSON repair", + "descriptionZh": "允许在安全边界内修复模型生成的轻微 JSON 格式错误。", + "descriptionEn": "Allow minor model-generated JSON formatting errors to be repaired within the safety boundary.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "ai.allow_tool_json_repair" + } + } + ], + "searchTerms": [ + "setting.tools.execution", + "执行与权限控制", + "Execution & permissions", + "AI 与协作", + "AI & collaboration", + "执行控制", + "工具权限", + "审批", + "并行", + "超时", + "Computer Use", + "浏览器控制", + "JSON 修复", + "execution control", + "tool permissions", + "approval", + "parallel", + "timeout", + "computer use", + "browser control", + "JSON repair", + "询问、自动批准与完全访问策略", + "子 Agent 并行度和工具超时", + "Computer Use、浏览器连接与工具参数修复", + "Ask, auto-approve, and full-access policies", + "Subagent concurrency and tool timeouts", + "Computer Use, browser connection, and tool-argument repair", + "选择询问、自动批准或完全访问权限模式,并确认高风险警告", + "Choose Ask, Auto-approve, or Full Access permission mode and acknowledge high-risk warnings", + "控制权限模式选择器是否显示在聊天输入框下方", + "Choose whether the permission-mode selector appears below the chat composer", + "创建、排序和保存全局或项目级 Allow、Ask、Deny 规则", + "Create, reorder, and save global or project-level Allow, Ask, and Deny rules", + "查看、撤销或清空项目中记住的权限授权与审计记录", + "Review, revoke, or clear remembered project permission grants and audit records", + "按需延迟加载大型工具定义以减少 Agent 初始上下文", + "Load large tool definitions on demand to reduce initial agent context", + "设置子 Agent 与 Swarm 最大并发及安全、强制并行或串行策略", + "Set subagent and swarm concurrency plus safe-only, forced-parallel, or serial policy", + "设置权限确认等待和单次工具执行超时", + "Set permission-confirmation and per-tool execution timeouts", + "设置 Deep Review 最大并行评审者和队列等待时间", + "Set the maximum parallel Deep Review workers and queue wait time", + "启用 Computer Use 并查看辅助功能与屏幕录制权限", + "Enable Computer Use and inspect accessibility and screen-recording permissions", + "选择浏览器、配置默认 CDP 并控制启动时自动连接", + "Choose a browser, configure default CDP, and control automatic connection at startup", + "控制是否在安全边界内修复模型生成的非法工具参数 JSON", + "Choose whether malformed model-generated tool-argument JSON may be repaired within safety boundaries" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.execution/" + }, + { + "id": "setting.tools.automation", + "kind": "setting", + "categoryId": "automation", + "titleZh": "快捷操作与 Hooks", + "titleEn": "Quick actions & hooks", + "summaryZh": "自定义编码后的快捷操作,并配置在 Agent 生命周期事件上运行的 Hooks。", + "summaryEn": "Customize post-coding quick actions and configure hooks that run on agent lifecycle events.", + "keywordsZh": [ + "自动化设置", + "快捷操作", + "提交", + "创建 PR", + "Hooks", + "生命周期" + ], + "keywordsEn": [ + "automation settings", + "quick action", + "commit", + "create PR", + "hooks", + "lifecycle" + ], + "highlightsZh": [ + "编码后快捷操作", + "内置提交与创建 PR 动作", + "会话、工具与权限事件 Hooks" + ], + "highlightsEn": [ + "Post-coding quick actions", + "Built-in commit and create-PR actions", + "Hooks for session, tool, and permission events" + ], + "items": [ + { + "id": "built-in-actions", + "titleZh": "启用和调整内置的提交与创建 Pull Request 快捷操作", + "titleEn": "Enable and tune the built-in Commit and Create Pull Request quick actions", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "quick-actions" + } + }, + { + "id": "custom-actions", + "titleZh": "添加、编辑和删除自定义编码后快捷操作及 Prompt", + "titleEn": "Add, edit, and delete custom post-coding quick actions and prompts", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "quick-actions" + } + }, + { + "id": "hooks-enabled", + "titleZh": "整体启用或停用 Agent 生命周期 Hooks", + "titleEn": "Enable or disable agent lifecycle hooks globally", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "project-hooks", + "titleZh": "对可信仓库单独启用项目级 .bitfun/config/hooks.json", + "titleEn": "Enable project-level .bitfun/config/hooks.json separately for trusted repositories", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-files", + "titleZh": "定位用户级和项目级 Hooks 配置文件并在修改后即时生效", + "titleEn": "Locate user and project hook configuration files and apply edits without restarting", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-events", + "titleZh": "在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器", + "titleEn": "Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "external-hooks", + "titleZh": "查看外部 AI 应用的只读 Hook 目录并选择导入项", + "titleEn": "Inspect read-only external-AI hook catalogs and choose entries to import", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + }, + { + "id": "hook-import", + "titleZh": "预览、修改和应用 Hook 导入计划,并保留冲突诊断", + "titleEn": "Preview, edit, and apply hook import plans while retaining conflict diagnostics", + "destination": { + "kind": "settings", + "pageId": "tools.automation", + "viewId": "hooks" + } + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > 自动化”", + "在“快捷操作”或“Hooks”中配置" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > Automation", + "Configure Quick Actions or Hooks" + ], + "agentExamplesZh": [ + "打开 Hooks 设置", + "带我编辑编码后的快捷操作" + ], + "agentExamplesEn": [ + "Open Hooks settings", + "Take me to post-coding quick actions" + ], + "destination": { + "kind": "settings", + "pageId": "tools.automation" + }, + "operations": [], + "options": [ + { + "id": "hooks-enabled", + "titleZh": "启用 Hooks", + "titleEn": "Enable hooks", + "descriptionZh": "允许已配置的 Agent 生命周期 Hooks 运行。", + "descriptionEn": "Allow configured agent lifecycle hooks to run.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.hooks", + "fields": [ + "enabled" + ] + } + }, + { + "id": "project-hooks-enabled", + "titleZh": "启用项目 Hooks", + "titleEn": "Enable project hooks", + "descriptionZh": "允许当前项目中的 Hooks 配置生效。", + "descriptionEn": "Allow hook configuration from the current project.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "mergeConfig", + "path": "app.hooks", + "fields": [ + "project_hooks_enabled" + ] + } + } + ], + "searchTerms": [ + "setting.tools.automation", + "快捷操作与 Hooks", + "Quick actions & hooks", + "扩展与自动化", + "Extensions & automation", + "自动化设置", + "快捷操作", + "提交", + "创建 PR", + "Hooks", + "生命周期", + "automation settings", + "quick action", + "commit", + "create PR", + "hooks", + "lifecycle", + "编码后快捷操作", + "内置提交与创建 PR 动作", + "会话、工具与权限事件 Hooks", + "Post-coding quick actions", + "Built-in commit and create-PR actions", + "Hooks for session, tool, and permission events", + "启用和调整内置的提交与创建 Pull Request 快捷操作", + "Enable and tune the built-in Commit and Create Pull Request quick actions", + "添加、编辑和删除自定义编码后快捷操作及 Prompt", + "Add, edit, and delete custom post-coding quick actions and prompts", + "整体启用或停用 Agent 生命周期 Hooks", + "Enable or disable agent lifecycle hooks globally", + "对可信仓库单独启用项目级 .bitfun/config/hooks.json", + "Enable project-level .bitfun/config/hooks.json separately for trusted repositories", + "定位用户级和项目级 Hooks 配置文件并在修改后即时生效", + "Locate user and project hook configuration files and apply edits without restarting", + "在会话、Agent、工具、权限和用户输入等 Codex Hook 事件上运行处理器", + "Run handlers on Codex hook events for sessions, agents, tools, permissions, and user input", + "查看外部 AI 应用的只读 Hook 目录并选择导入项", + "Inspect read-only external-AI hook catalogs and choose entries to import", + "预览、修改和应用 Hook 导入计划,并保留冲突诊断", + "Preview, edit, and apply hook import plans while retaining conflict diagnostics" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.automation/" + }, + { + "id": "setting.tools.mcp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "MCP 服务器", + "titleEn": "MCP servers", + "summaryZh": "添加和管理 Model Context Protocol 服务器,查看工具、资源、提示词与远程授权状态。", + "summaryEn": "Add and manage Model Context Protocol servers, including tools, resources, prompts, and remote authorization state.", + "keywordsZh": [ + "MCP", + "MCP 服务器", + "工具服务器", + "stdio", + "SSE", + "OAuth", + "资源" + ], + "keywordsEn": [ + "MCP", + "MCP server", + "tool server", + "stdio", + "SSE", + "OAuth", + "resource" + ], + "highlightsZh": [ + "添加本地或远程 MCP 服务器", + "查看连接健康与工具清单", + "完成远程 OAuth 授权" + ], + "highlightsEn": [ + "Add local or remote MCP servers", + "Inspect connection health and tool inventory", + "Complete remote OAuth authorization" + ], + "items": [ + { + "id": "json-config", + "titleZh": "用表单或 JSON 查看和保存全部 MCP 服务器配置", + "titleEn": "View and save all MCP server configuration through forms or JSON" + }, + { + "id": "server-types", + "titleZh": "添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器", + "titleEn": "Add local-process, remote HTTP/SSE, or container MCP servers" + }, + { + "id": "lifecycle", + "titleZh": "启动、停止、重启和删除单个 MCP 服务器", + "titleEn": "Start, stop, restart, and delete individual MCP servers" + }, + { + "id": "status", + "titleZh": "查看初始化、连接、健康、重连、鉴权和失败状态", + "titleEn": "Inspect initialization, connection, health, reconnecting, authentication, and failure states" + }, + { + "id": "remote-auth", + "titleZh": "配置远程 Header/环境变量认证或清除已有凭据", + "titleEn": "Configure remote header/environment authentication or clear stored credentials" + }, + { + "id": "oauth", + "titleZh": "发起、轮询、取消或重新连接远程 MCP OAuth", + "titleEn": "Start, poll, cancel, or reconnect remote MCP OAuth" + }, + { + "id": "tools-prompts", + "titleZh": "查看 MCP 工具、Prompt 列表并读取指定 Prompt", + "titleEn": "Browse MCP tools and prompts and load a selected prompt" + }, + { + "id": "resources", + "titleZh": "列出、读取和打开 MCP Resources", + "titleEn": "List, read, and open MCP resources" + }, + { + "id": "mcp-apps", + "titleZh": "打开 MCP App/UI、双向发送消息并回答交互请求", + "titleEn": "Open MCP App/UI surfaces, exchange messages, and answer interaction requests" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > MCP”", + "添加服务器并确认其权限与连接状态" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > MCP", + "Add a server and review its permissions and connection state" + ], + "agentExamplesZh": [ + "打开 MCP 设置", + "带我管理 MCP 服务器" + ], + "agentExamplesEn": [ + "Open MCP settings", + "Take me to MCP server management" + ], + "destination": { + "kind": "settings", + "pageId": "tools.mcp" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.tools.mcp", + "MCP 服务器", + "MCP servers", + "扩展与自动化", + "Extensions & automation", + "MCP", + "工具服务器", + "stdio", + "SSE", + "OAuth", + "资源", + "MCP server", + "tool server", + "resource", + "添加本地或远程 MCP 服务器", + "查看连接健康与工具清单", + "完成远程 OAuth 授权", + "Add local or remote MCP servers", + "Inspect connection health and tool inventory", + "Complete remote OAuth authorization", + "用表单或 JSON 查看和保存全部 MCP 服务器配置", + "View and save all MCP server configuration through forms or JSON", + "添加本地进程、远程 HTTP/SSE 或容器 MCP 服务器", + "Add local-process, remote HTTP/SSE, or container MCP servers", + "启动、停止、重启和删除单个 MCP 服务器", + "Start, stop, restart, and delete individual MCP servers", + "查看初始化、连接、健康、重连、鉴权和失败状态", + "Inspect initialization, connection, health, reconnecting, authentication, and failure states", + "配置远程 Header/环境变量认证或清除已有凭据", + "Configure remote header/environment authentication or clear stored credentials", + "发起、轮询、取消或重新连接远程 MCP OAuth", + "Start, poll, cancel, or reconnect remote MCP OAuth", + "查看 MCP 工具、Prompt 列表并读取指定 Prompt", + "Browse MCP tools and prompts and load a selected prompt", + "列出、读取和打开 MCP Resources", + "List, read, and open MCP resources", + "打开 MCP App/UI、双向发送消息并回答交互请求", + "Open MCP App/UI surfaces, exchange messages, and answer interaction requests" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.mcp/" + }, + { + "id": "setting.tools.acp", + "kind": "setting", + "categoryId": "automation", + "titleZh": "ACP 外部 Agents", + "titleEn": "ACP external agents", + "summaryZh": "配置通过 Agent Client Protocol 接入的外部 Agent,并检查适配器、命令与会话选项。", + "summaryEn": "Configure external agents connected through Agent Client Protocol and inspect adapters, commands, and session options.", + "keywordsZh": [ + "ACP", + "外部 Agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex" + ], + "keywordsEn": [ + "ACP", + "external agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex" + ], + "highlightsZh": [ + "注册外部 Agent", + "探测并安装 CLI 适配器", + "配置 ACP 会话选项" + ], + "highlightsEn": [ + "Register external agents", + "Probe and install CLI adapters", + "Configure ACP session options" + ], + "items": [ + { + "id": "presets", + "titleZh": "使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设", + "titleEn": "Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others" + }, + { + "id": "json-config", + "titleZh": "通过 JSON 查看、添加和保存 ACP Agent 配置", + "titleEn": "View, add, and save ACP agent configuration through JSON" + }, + { + "id": "probe", + "titleZh": "探测 CLI、适配器、路径、版本、连接与权限要求", + "titleEn": "Probe CLI, adapter, path, version, connection, and permission requirements" + }, + { + "id": "install", + "titleZh": "安装外部 Agent CLI 并预下载 ACP 客户端适配器", + "titleEn": "Install external-agent CLIs and predownload ACP client adapters" + }, + { + "id": "remote-detection", + "titleZh": "在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因", + "titleEn": "Detect available external agents in SSH workspaces and show explicit unsupported reasons" + }, + { + "id": "session-model-options", + "titleZh": "为 ACP 会话选择模型并修改客户端声明的配置选项", + "titleEn": "Choose an ACP session model and edit client-declared configuration options" + }, + { + "id": "session-commands", + "titleZh": "查看并执行外部 Agent 暴露的会话命令", + "titleEn": "Browse and run session commands exposed by an external agent" + }, + { + "id": "dialog-permissions", + "titleZh": "开始或取消 ACP 对话,并远程回答外部 Agent 权限请求", + "titleEn": "Start or cancel ACP turns and answer external-agent permission requests remotely" + } + ], + "stepsZh": [ + "打开设置", + "进入“工具 > ACP”", + "添加客户端并通过探测检查可用性" + ], + "stepsEn": [ + "Open Settings", + "Go to Tools > ACP", + "Add a client and probe its availability" + ], + "agentExamplesZh": [ + "打开 ACP 设置", + "带我配置外部 Agent" + ], + "agentExamplesEn": [ + "Open ACP settings", + "Take me to external-agent setup" + ], + "destination": { + "kind": "settings", + "pageId": "tools.acp" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.tools.acp", + "ACP 外部 Agents", + "ACP external agents", + "扩展与自动化", + "Extensions & automation", + "ACP", + "外部 Agent", + "Agent Client Protocol", + "OpenCode", + "Claude Code", + "Codex", + "external agent", + "注册外部 Agent", + "探测并安装 CLI 适配器", + "配置 ACP 会话选项", + "Register external agents", + "Probe and install CLI adapters", + "Configure ACP session options", + "使用 OpenCode、dsh、OMP、Claude Code 和 Codex 等预设", + "Use presets for OpenCode, dsh, OMP, Claude Code, Codex, and others", + "通过 JSON 查看、添加和保存 ACP Agent 配置", + "View, add, and save ACP agent configuration through JSON", + "探测 CLI、适配器、路径、版本、连接与权限要求", + "Probe CLI, adapter, path, version, connection, and permission requirements", + "安装外部 Agent CLI 并预下载 ACP 客户端适配器", + "Install external-agent CLIs and predownload ACP client adapters", + "在 SSH 远程工作区探测可用外部 Agent 并显示不支持原因", + "Detect available external agents in SSH workspaces and show explicit unsupported reasons", + "为 ACP 会话选择模型并修改客户端声明的配置选项", + "Choose an ACP session model and edit client-declared configuration options", + "查看并执行外部 Agent 暴露的会话命令", + "Browse and run session commands exposed by an external agent", + "开始或取消 ACP 对话,并远程回答外部 Agent 权限请求", + "Start or cancel ACP turns and answer external-agent permission requests remotely" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.tools.acp/" + }, + { + "id": "setting.data.usage", + "kind": "setting", + "categoryId": "data", + "titleZh": "Token 用量", + "titleEn": "Token usage", + "summaryZh": "查看请求、输入输出 Token、缓存命中和估算成本等使用统计。", + "summaryEn": "Inspect request counts, input and output tokens, cache hits, and estimated cost statistics.", + "keywordsZh": [ + "Token 用量", + "成本", + "缓存", + "请求统计", + "用量历史" + ], + "keywordsEn": [ + "token usage", + "cost", + "cache", + "request statistics", + "usage history" + ], + "highlightsZh": [ + "按时间查看用量", + "区分输入、输出与缓存 Token", + "理解不同模型和会话的成本" + ], + "highlightsEn": [ + "Review usage over time", + "Separate input, output, and cached tokens", + "Understand cost by model and session" + ], + "items": [ + { + "id": "time-range", + "titleZh": "按最近 24 小时、今天、本周、本月或全部时间查看用量", + "titleEn": "Review usage for the last 24 hours, today, this week, this month, or all time" + }, + { + "id": "granularity", + "titleZh": "按小时或天切换趋势粒度", + "titleEn": "Switch trend granularity between hourly and daily views" + }, + { + "id": "filter", + "titleZh": "按供应商、模型或搜索关键词筛选用量", + "titleEn": "Filter usage by provider, model, or search text" + }, + { + "id": "summary", + "titleZh": "查看请求数、总 Token、缓存 Token 与缓存命中率", + "titleEn": "View request count, total tokens, cached tokens, and cache-hit rate" + }, + { + "id": "distribution", + "titleZh": "按模型、供应商组和请求端点比较分布", + "titleEn": "Compare distributions by model, provider group, and request endpoint" + }, + { + "id": "trend", + "titleZh": "分别查看输入、输出、缓存创建、缓存读取和命中率趋势", + "titleEn": "Track input, output, cache creation, cache read, and hit-rate trends separately" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 用量”", + "选择时间范围并查看统计" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Usage", + "Choose a time range and inspect statistics" + ], + "agentExamplesZh": [ + "打开 Token 用量", + "带我查看使用统计" + ], + "agentExamplesEn": [ + "Open Token usage", + "Show me usage statistics" + ], + "destination": { + "kind": "settings", + "pageId": "data.usage" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.data.usage", + "Token 用量", + "Token usage", + "数据与诊断", + "Data & diagnostics", + "成本", + "缓存", + "请求统计", + "用量历史", + "token usage", + "cost", + "cache", + "request statistics", + "usage history", + "按时间查看用量", + "区分输入、输出与缓存 Token", + "理解不同模型和会话的成本", + "Review usage over time", + "Separate input, output, and cached tokens", + "Understand cost by model and session", + "按最近 24 小时、今天、本周、本月或全部时间查看用量", + "Review usage for the last 24 hours, today, this week, this month, or all time", + "按小时或天切换趋势粒度", + "Switch trend granularity between hourly and daily views", + "按供应商、模型或搜索关键词筛选用量", + "Filter usage by provider, model, or search text", + "查看请求数、总 Token、缓存 Token 与缓存命中率", + "View request count, total tokens, cached tokens, and cache-hit rate", + "按模型、供应商组和请求端点比较分布", + "Compare distributions by model, provider group, and request endpoint", + "分别查看输入、输出、缓存创建、缓存读取和命中率趋势", + "Track input, output, cache creation, cache read, and hit-rate trends separately" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.usage/" + }, + { + "id": "setting.data.archived", + "kind": "setting", + "categoryId": "data", + "titleZh": "已归档会话", + "titleEn": "Archived sessions", + "summaryZh": "查找、恢复或永久删除已归档的会话,管理长期会话历史。", + "summaryEn": "Find, restore, or permanently delete archived sessions and manage long-term conversation history.", + "keywordsZh": [ + "已归档会话", + "会话历史", + "恢复会话", + "取消归档", + "删除历史" + ], + "keywordsEn": [ + "archived sessions", + "session history", + "restore session", + "unarchive", + "delete history" + ], + "highlightsZh": [ + "浏览归档会话", + "恢复到原工作区", + "显式永久删除历史" + ], + "highlightsEn": [ + "Browse archived sessions", + "Restore to the original workspace", + "Explicitly delete history permanently" + ], + "items": [ + { + "id": "browse", + "titleZh": "按工作区浏览分页归档会话及其元数据", + "titleEn": "Browse paged archived sessions and metadata by workspace" + }, + { + "id": "search", + "titleZh": "按标题、内容和工作区搜索已归档会话", + "titleEn": "Search archived sessions by title, content, and workspace" + }, + { + "id": "restore", + "titleZh": "恢复会话、轮次和原工作区视图并取消归档", + "titleEn": "Restore a session, its turns, and original workspace view, then unarchive it" + }, + { + "id": "delete-selected", + "titleZh": "明确确认后永久删除选中的归档会话", + "titleEn": "Permanently delete a selected archived session after explicit confirmation" + }, + { + "id": "delete-all", + "titleZh": "明确确认后永久删除全部归档会话", + "titleEn": "Permanently delete all archived sessions after explicit confirmation" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 已归档会话”", + "选择会话后恢复或删除" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Archived Sessions", + "Choose a session to restore or delete" + ], + "agentExamplesZh": [ + "打开已归档会话", + "带我恢复一个旧会话" + ], + "agentExamplesEn": [ + "Open archived sessions", + "Take me to restore an old session" + ], + "destination": { + "kind": "settings", + "pageId": "data.archived" + }, + "operations": [], + "options": [], + "searchTerms": [ + "setting.data.archived", + "已归档会话", + "Archived sessions", + "数据与诊断", + "Data & diagnostics", + "会话历史", + "恢复会话", + "取消归档", + "删除历史", + "archived sessions", + "session history", + "restore session", + "unarchive", + "delete history", + "浏览归档会话", + "恢复到原工作区", + "显式永久删除历史", + "Browse archived sessions", + "Restore to the original workspace", + "Explicitly delete history permanently", + "按工作区浏览分页归档会话及其元数据", + "Browse paged archived sessions and metadata by workspace", + "按标题、内容和工作区搜索已归档会话", + "Search archived sessions by title, content, and workspace", + "恢复会话、轮次和原工作区视图并取消归档", + "Restore a session, its turns, and original workspace view, then unarchive it", + "明确确认后永久删除选中的归档会话", + "Permanently delete a selected archived session after explicit confirmation", + "明确确认后永久删除全部归档会话", + "Permanently delete all archived sessions after explicit confirmation" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.archived/" + }, + { + "id": "setting.data.diagnostics", + "kind": "setting", + "categoryId": "data", + "titleZh": "日志与诊断", + "titleEn": "Logs & diagnostics", + "summaryZh": "调整日志级别,查看运行日志路径,并导出用于排查问题的诊断包。", + "summaryEn": "Adjust logging level, inspect runtime log locations, and export diagnostic bundles for troubleshooting.", + "keywordsZh": [ + "诊断", + "日志", + "调试", + "日志级别", + "诊断包", + "故障排查" + ], + "keywordsEn": [ + "diagnostics", + "logs", + "debug", + "log level", + "diagnostic bundle", + "troubleshooting" + ], + "highlightsZh": [ + "调整后端日志级别", + "查看当前与上次异常退出日志", + "导出诊断包并控制敏感信息" + ], + "highlightsEn": [ + "Adjust backend log level", + "Inspect current and previous-crash logs", + "Export bundles and control sensitive diagnostics" + ], + "items": [ + { + "id": "log-level", + "titleZh": "设置 Trace、Debug、Info、Warn、Error 或关闭后端日志", + "titleEn": "Set backend logging to Trace, Debug, Info, Warn, Error, or Off" + }, + { + "id": "sensitive-diagnostics", + "titleZh": "选择诊断中是否允许包含敏感上下文,并在导出前明确提示", + "titleEn": "Choose whether diagnostics may include sensitive context, with an explicit warning before export" + }, + { + "id": "log-path", + "titleZh": "查看日志路径并打开日志文件夹", + "titleEn": "Inspect the log path and open the log folder" + }, + { + "id": "export-bundle", + "titleZh": "导出包含系统、配置健康和日志信息的诊断包", + "titleEn": "Export a diagnostics bundle containing system, configuration-health, and log information" + }, + { + "id": "crash-recovery", + "titleZh": "查看上次崩溃、非正常退出、启动恢复和配置恢复信息", + "titleEn": "Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery" + }, + { + "id": "devtools", + "titleZh": "在开发构建中检查 DevTools 是否可用并打开或关闭", + "titleEn": "In development builds, check DevTools availability and open or close them" + }, + { + "id": "element-inspector", + "titleZh": "在开发构建中启用主窗口元素检查并回传选中的元素", + "titleEn": "In development builds, inspect main-window elements and report the selected element" + } + ], + "stepsZh": [ + "打开设置", + "进入“数据 > 日志与诊断”", + "选择日志级别,或按需导出诊断包" + ], + "stepsEn": [ + "Open Settings", + "Go to Data > Logs & Diagnostics", + "Choose a log level or export a bundle when needed" + ], + "agentExamplesZh": [ + "把日志级别改成 debug", + "打开诊断设置", + "带我导出诊断包" + ], + "agentExamplesEn": [ + "Set the log level to debug", + "Open diagnostics settings", + "Take me to export a diagnostic bundle" + ], + "destination": { + "kind": "settings", + "pageId": "data.diagnostics" + }, + "operations": [], + "options": [ + { + "id": "log-level", + "titleZh": "日志级别", + "titleEn": "Log level", + "descriptionZh": "设置后端运行日志的详细程度。", + "descriptionEn": "Set the verbosity of backend runtime logs.", + "valueSchema": { + "type": "string", + "enum": [ + "error", + "warn", + "info", + "debug", + "trace" + ] + }, + "handler": { + "kind": "config", + "path": "app.logging.level" + } + }, + { + "id": "sensitive-diagnostics", + "titleZh": "诊断包包含敏感信息", + "titleEn": "Include sensitive diagnostics", + "descriptionZh": "仅在明确需要并理解隐私风险时启用。", + "descriptionEn": "Enable only when explicitly needed and after reviewing the privacy risk.", + "valueSchema": { + "type": "boolean" + }, + "handler": { + "kind": "config", + "path": "app.logging.include_sensitive_diagnostics" + } + } + ], + "searchTerms": [ + "setting.data.diagnostics", + "日志与诊断", + "Logs & diagnostics", + "数据与诊断", + "Data & diagnostics", + "诊断", + "日志", + "调试", + "日志级别", + "诊断包", + "故障排查", + "diagnostics", + "logs", + "debug", + "log level", + "diagnostic bundle", + "troubleshooting", + "调整后端日志级别", + "查看当前与上次异常退出日志", + "导出诊断包并控制敏感信息", + "Adjust backend log level", + "Inspect current and previous-crash logs", + "Export bundles and control sensitive diagnostics", + "设置 Trace、Debug、Info、Warn、Error 或关闭后端日志", + "Set backend logging to Trace, Debug, Info, Warn, Error, or Off", + "选择诊断中是否允许包含敏感上下文,并在导出前明确提示", + "Choose whether diagnostics may include sensitive context, with an explicit warning before export", + "查看日志路径并打开日志文件夹", + "Inspect the log path and open the log folder", + "导出包含系统、配置健康和日志信息的诊断包", + "Export a diagnostics bundle containing system, configuration-health, and log information", + "查看上次崩溃、非正常退出、启动恢复和配置恢复信息", + "Inspect previous crashes, unclean shutdowns, startup recovery, and configuration recovery", + "在开发构建中检查 DevTools 是否可用并打开或关闭", + "In development builds, check DevTools availability and open or close them", + "在开发构建中启用主窗口元素检查并回传选中的元素", + "In development builds, inspect main-window elements and report the selected element" + ], + "docsUrl": "https://playbook.openbitfun.com/capabilities/setting.data.diagnostics/" + } + ] +} diff --git a/src/web-ui/src/app/global-search/globalSearchActivator.ts b/src/web-ui/src/app/global-search/globalSearchActivator.ts index 731e866186..d1fd710f2f 100644 --- a/src/web-ui/src/app/global-search/globalSearchActivator.ts +++ b/src/web-ui/src/app/global-search/globalSearchActivator.ts @@ -11,6 +11,7 @@ import { globalEventBus } from '@/infrastructure/event-bus'; import { openFileInBestTarget } from '@/shared/utils/tabUtils'; import { useSceneStore } from '@/app/stores/sceneStore'; import { activateProductAction } from './productActionActivator'; +import { activateInteractiveCapability } from './interactiveCapabilityActivator'; import type { GlobalSearchTarget } from './types'; export interface GlobalSearchActivationContext { @@ -81,5 +82,11 @@ export async function activateGlobalSearchTarget( useSettingsStore.getState().openDestination(target.destination); useSceneStore.getState().openScene('settings'); return; + case 'capability': + await activateInteractiveCapability(target.capabilityId, { + t: context.tCommon, + itemId: target.itemId, + }); + return; } } diff --git a/src/web-ui/src/app/global-search/interactiveCapabilityActivator.test.ts b/src/web-ui/src/app/global-search/interactiveCapabilityActivator.test.ts new file mode 100644 index 0000000000..79caf7ab82 --- /dev/null +++ b/src/web-ui/src/app/global-search/interactiveCapabilityActivator.test.ts @@ -0,0 +1,49 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +const mocks = vi.hoisted(() => ({ + openDestination: vi.fn(), + openScene: vi.fn(), + activateProductAction: vi.fn(), +})); + +vi.mock('@/app/scenes/settings/settingsStore', () => ({ + useSettingsStore: { + getState: () => ({ openDestination: mocks.openDestination }), + }, +})); + +vi.mock('@/app/stores/sceneStore', () => ({ + useSceneStore: { + getState: () => ({ openScene: mocks.openScene }), + }, +})); + +vi.mock('./productActionActivator', () => ({ + activateProductAction: mocks.activateProductAction, +})); + +import { activateInteractiveCapability } from './interactiveCapabilityActivator'; + +describe('activateInteractiveCapability', () => { + beforeEach(() => vi.clearAllMocks()); + + it('opens the exact settings subview declared by a documented item', async () => { + await activateInteractiveCapability('setting.application.input', { + itemId: 'shortcut-browser', + }); + + expect(mocks.openDestination).toHaveBeenCalledWith({ + kind: 'settings', + pageId: 'application.input', + viewId: 'shortcuts', + }); + expect(mocks.openScene).toHaveBeenCalledWith('settings'); + }); + + it('rejects stale item IDs instead of silently opening the wrong place', async () => { + await expect(activateInteractiveCapability('setting.application.input', { + itemId: 'missing-item', + })).rejects.toThrow('Unknown documented item'); + expect(mocks.openDestination).not.toHaveBeenCalled(); + }); +}); diff --git a/src/web-ui/src/app/global-search/interactiveCapabilityActivator.ts b/src/web-ui/src/app/global-search/interactiveCapabilityActivator.ts new file mode 100644 index 0000000000..82124a3def --- /dev/null +++ b/src/web-ui/src/app/global-search/interactiveCapabilityActivator.ts @@ -0,0 +1,41 @@ +import { useSettingsStore } from '@/app/scenes/settings/settingsStore'; +import { useSceneStore } from '@/app/stores/sceneStore'; +import { getInteractiveCapability } from './interactiveCapabilityCatalog'; +import { activateProductAction } from './productActionActivator'; + +export interface InteractiveCapabilityActivationOptions { + t?: (key: string, options?: Record) => string; + itemId?: string; +} + +export async function activateInteractiveCapability( + capabilityId: string, + options: InteractiveCapabilityActivationOptions = {}, +): Promise { + const capability = getInteractiveCapability(capabilityId); + if (!capability) throw new Error(`Unknown BitFun capability: ${capabilityId}`); + const item = options.itemId + ? capability.items.find(({ id }) => id === options.itemId) + : undefined; + if (options.itemId && !item) { + throw new Error(`Unknown documented item for ${capabilityId}: ${options.itemId}`); + } + const destination = item?.destination ?? capability.destination; + + switch (destination.kind) { + case 'settings': + useSettingsStore.getState().openDestination(destination); + useSceneStore.getState().openScene('settings'); + return; + case 'action': + await activateProductAction(destination.actionId, { t: options.t }); + return; + case 'scene': + useSceneStore.getState().openScene(destination.sceneId); + return; + case 'event': + window.dispatchEvent(new CustomEvent(destination.eventName, { + detail: destination.detail, + })); + } +} diff --git a/src/web-ui/src/app/global-search/interactiveCapabilityCatalog.ts b/src/web-ui/src/app/global-search/interactiveCapabilityCatalog.ts new file mode 100644 index 0000000000..11fb08530c --- /dev/null +++ b/src/web-ui/src/app/global-search/interactiveCapabilityCatalog.ts @@ -0,0 +1,122 @@ +import type { SceneTabId } from '@/app/components/SceneBar/types'; +import type { SettingsDestination } from '@/app/scenes/settings/settingsTypes'; +import type { ProductActionId } from './productActionCatalog'; +import generatedCatalog from './generated/interactive-capabilities.json'; + +export type InteractiveCapabilityKind = 'feature' | 'setting'; +export type InteractiveCapabilityRisk = 'read' | 'write' | 'ui' | 'execute' | 'destructive'; + +export type InteractiveCapabilityDestination = + | ({ kind: 'settings' } & SettingsDestination) + | { kind: 'action'; actionId: ProductActionId } + | { kind: 'scene'; sceneId: SceneTabId } + | { kind: 'event'; eventName: string; detail?: Record }; + +export interface InteractiveCapabilityValueSchema { + type: 'boolean' | 'string' | 'integer' | 'number' | 'object' | 'array'; + enum?: unknown[]; + minimum?: number; + maximum?: number; +} + +export type InteractiveCapabilityOperationHandler = { + kind: 'productAction'; + actionId: ProductActionId; +}; + +export type InteractiveCapabilityOptionHandler = + | { kind: 'config'; path: string } + | { kind: 'mergeConfig'; path: string; fields: string[] } + | { kind: 'appearanceSelection' } + | { kind: 'language' }; + +export interface InteractiveCapabilityOperation { + id: string; + titleZh: string; + titleEn: string; + descriptionZh: string; + descriptionEn: string; + risk: InteractiveCapabilityRisk; + inputSchema: Record; + handler: InteractiveCapabilityOperationHandler; +} + +export interface InteractiveCapabilityOption { + id: string; + titleZh: string; + titleEn: string; + descriptionZh: string; + descriptionEn: string; + valueSchema: InteractiveCapabilityValueSchema; + handler: InteractiveCapabilityOptionHandler; +} + +export interface InteractiveCapabilityItem { + id: string; + titleZh: string; + titleEn: string; + destination?: InteractiveCapabilityDestination; +} + +export interface InteractiveCapabilityAgentControl { + tool: string; + workflowZh: string[]; + workflowEn: string[]; +} + +export interface InteractiveCapability { + id: string; + kind: InteractiveCapabilityKind; + titleZh: string; + titleEn: string; + summaryZh: string; + summaryEn: string; + categoryId: string; + keywordsZh: string[]; + keywordsEn: string[]; + highlightsZh: string[]; + highlightsEn: string[]; + items: InteractiveCapabilityItem[]; + stepsZh: string[]; + stepsEn: string[]; + agentExamplesZh: string[]; + agentExamplesEn: string[]; + agentControl?: InteractiveCapabilityAgentControl; + destination: InteractiveCapabilityDestination; + operations: InteractiveCapabilityOperation[]; + options: InteractiveCapabilityOption[]; + searchTerms: string[]; + docsUrl: string; +} + +export interface InteractiveCapabilityCatalog { + schemaVersion: number; + product: string; + title: string; + origin: string; + source: string; + digest: string; + counts: { + features: number; + settings: number; + userFacing: number; + documentedItems: number; + }; + categories: Record; + capabilities: InteractiveCapability[]; +} + +export const INTERACTIVE_CAPABILITY_CATALOG = generatedCatalog as InteractiveCapabilityCatalog; + +const capabilityById = new Map( + INTERACTIVE_CAPABILITY_CATALOG.capabilities.map((capability) => [capability.id, capability]), +); + +export function getInteractiveCapability(capabilityId: string): InteractiveCapability | undefined { + return capabilityById.get(capabilityId); +} diff --git a/src/web-ui/src/app/global-search/providers/index.ts b/src/web-ui/src/app/global-search/providers/index.ts index 94281d5614..b75fb162cb 100644 --- a/src/web-ui/src/app/global-search/providers/index.ts +++ b/src/web-ui/src/app/global-search/providers/index.ts @@ -2,13 +2,13 @@ import type { GlobalSearchProvider } from '../types'; import { actionSearchProvider } from './actionSearchProvider'; import { entitySearchProvider } from './entitySearchProvider'; import { fileSearchProvider } from './fileSearchProvider'; +import { interactiveCapabilitySearchProvider } from './interactiveCapabilitySearchProvider'; import { sessionContentSearchProvider } from './sessionContentSearchProvider'; -import { settingsSearchProvider } from './settingsSearchProvider'; export const GLOBAL_SEARCH_PROVIDERS: readonly GlobalSearchProvider[] = [ actionSearchProvider, entitySearchProvider, - settingsSearchProvider, + interactiveCapabilitySearchProvider, sessionContentSearchProvider, fileSearchProvider, ]; @@ -17,6 +17,6 @@ export { actionSearchProvider, entitySearchProvider, fileSearchProvider, + interactiveCapabilitySearchProvider, sessionContentSearchProvider, - settingsSearchProvider, }; diff --git a/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.test.ts b/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.test.ts new file mode 100644 index 0000000000..422aff0efa --- /dev/null +++ b/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.test.ts @@ -0,0 +1,102 @@ +import { describe, expect, it } from 'vitest'; +import { INTERACTIVE_CAPABILITY_CATALOG } from '../interactiveCapabilityCatalog'; +import type { GlobalSearchRequest } from '../types'; +import { interactiveCapabilitySearchProvider } from './interactiveCapabilitySearchProvider'; + +function request(query: string): GlobalSearchRequest { + return { + rawQuery: query, + query, + scope: 'all', + workspaces: [], + currentWorkspace: null, + limitPerGroup: 20, + tCommon: (key) => key, + tSettings: (key) => key, + }; +} + +describe('interactiveCapabilitySearchProvider', () => { + it('uses the curated feature-and-settings contract', () => { + expect(INTERACTIVE_CAPABILITY_CATALOG.capabilities).toHaveLength( + INTERACTIVE_CAPABILITY_CATALOG.counts.userFacing, + ); + expect(new Set(INTERACTIVE_CAPABILITY_CATALOG.capabilities.map(({ id }) => id)).size) + .toBe(INTERACTIVE_CAPABILITY_CATALOG.capabilities.length); + expect(INTERACTIVE_CAPABILITY_CATALOG.capabilities.every(({ kind }) => + kind === 'feature' || kind === 'setting')).toBe(true); + }); + + it('finds a capability by its English terms', async () => { + const result = await interactiveCapabilitySearchProvider.search( + request('terminal'), + new AbortController().signal, + ); + expect(result.items.some((item) => item.target.kind === 'capability' + && item.target.capabilityId === 'feature.terminal')).toBe(true); + }); + + it('finds the same catalog by Chinese terms', async () => { + const result = await interactiveCapabilitySearchProvider.search( + request('终端'), + new AbortController().signal, + ); + expect(result.items.some((item) => item.target.kind === 'capability' + && item.target.capabilityId === 'feature.terminal')).toBe(true); + }); + + it('returns settings from the same semantic provider in the settings group', async () => { + const result = await interactiveCapabilitySearchProvider.search( + request('MCP server'), + new AbortController().signal, + ); + const mcp = result.items.find((item) => item.target.kind === 'capability' + && item.target.capabilityId === 'setting.tools.mcp'); + expect(mcp?.providerId).toBe('interactive-capabilities'); + expect(mcp?.group).toBe('settings'); + }); + + it.each([ + ['快捷键', 'setting.application.input', 'shortcut-browser'], + ['editor font', 'setting.application.development', 'editor-appearance'], + ['Hooks 设置', 'setting.tools.automation', 'hooks-enabled'], + ])('routes %s to the matching settings subview', async (query, capabilityId, itemId) => { + const result = await interactiveCapabilitySearchProvider.search( + request(query), + new AbortController().signal, + ); + const match = result.items.find((item) => item.target.kind === 'capability' + && item.target.capabilityId === capabilityId); + expect(match?.target).toEqual({ kind: 'capability', capabilityId, itemId }); + }); + + it('finds the browser element picker from Chinese and English sub-capability text', async () => { + for (const query of ['元素选择器', 'element picker']) { + const result = await interactiveCapabilitySearchProvider.search( + request(query), + new AbortController().signal, + ); + const browser = result.items.find((item) => item.target.kind === 'capability' + && item.target.capabilityId === 'feature.browser'); + expect(browser).toBeDefined(); + expect(browser?.subtitle.toLowerCase()).toContain( + query === '元素选择器' ? '元素选择器' : 'element picker', + ); + expect(browser?.context).toContain('feature.browser:element-picker'); + } + }); + + it('keeps personal assistants separate from subagent management', async () => { + for (const query of ['育苗场', 'persona documents']) { + const result = await interactiveCapabilitySearchProvider.search( + request(query), + new AbortController().signal, + ); + const assistant = result.items.find((item) => item.target.kind === 'capability' + && item.target.capabilityId === 'feature.personal-assistants'); + expect(assistant).toBeDefined(); + expect(assistant?.target.kind === 'capability' && assistant.target.capabilityId) + .not.toBe('feature.agents'); + } + }); +}); diff --git a/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.ts b/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.ts new file mode 100644 index 0000000000..79885da18d --- /dev/null +++ b/src/web-ui/src/app/global-search/providers/interactiveCapabilitySearchProvider.ts @@ -0,0 +1,77 @@ +import { + INTERACTIVE_CAPABILITY_CATALOG, + type InteractiveCapability, +} from '../interactiveCapabilityCatalog'; +import { scoreTextMatch } from '../searchMatching'; +import type { GlobalSearchProvider } from '../types'; + +const CJK_QUERY = /[\u3400-\u9fff]/u; + +function resultTitle(capability: InteractiveCapability, query: string) { + return CJK_QUERY.test(query) ? capability.titleZh : capability.titleEn; +} + +function matchingItem(capability: InteractiveCapability, query: string) { + const queryTokens = query.trim().split(/[\s._/\\:-]+/u).filter(Boolean); + return capability.items + .map((item) => { + const directScore = scoreTextMatch(query, [item.titleZh, item.titleEn]); + const partialScore = Math.max(0, ...queryTokens.map((token) => + scoreTextMatch(token, [item.titleZh, item.titleEn]))); + return { + item, + score: directScore > 0 ? 100 + directScore : Math.floor(partialScore / 2), + }; + }) + .filter(({ score }) => score > 0) + .sort((left, right) => right.score - left.score)[0]?.item; +} + +function resultSubtitle( + capability: InteractiveCapability, + query: string, + item: ReturnType, +) { + const category = INTERACTIVE_CAPABILITY_CATALOG.categories[capability.categoryId]; + const summary = item + ? (CJK_QUERY.test(query) ? item.titleZh : item.titleEn) + : (CJK_QUERY.test(query) ? capability.summaryZh : capability.summaryEn); + const categoryTitle = CJK_QUERY.test(query) ? category?.titleZh : category?.titleEn; + return [categoryTitle, summary].filter(Boolean).join(' · '); +} + +export const interactiveCapabilitySearchProvider: GlobalSearchProvider = { + id: 'interactive-capabilities', + groups: ['capabilities', 'settings'], + search: (request) => { + if (request.scope === 'content' || !request.query) return { items: [] }; + + const items = INTERACTIVE_CAPABILITY_CATALOG.capabilities + .map((capability) => { + const item = matchingItem(capability, request.query); + return { + id: `capability:${capability.id}`, + providerId: 'interactive-capabilities', + group: capability.kind === 'setting' ? 'settings' as const : 'capabilities' as const, + title: resultTitle(capability, request.query), + subtitle: resultSubtitle(capability, request.query, item), + context: item ? `${capability.id}:${item.id}` : capability.id, + badge: capability.kind, + score: scoreTextMatch(request.query, [ + capability.id, + capability.titleZh, + capability.titleEn, + ...capability.searchTerms, + ]), + target: { + kind: 'capability' as const, + capabilityId: capability.id, + itemId: item?.id, + }, + }; + }) + .filter((item) => item.score > 0); + + return { items }; + }, +}; diff --git a/src/web-ui/src/app/global-search/providers/settingsSearchProvider.test.ts b/src/web-ui/src/app/global-search/providers/settingsSearchProvider.test.ts deleted file mode 100644 index 5710384086..0000000000 --- a/src/web-ui/src/app/global-search/providers/settingsSearchProvider.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import type { GlobalSearchRequest } from '../types'; -import { settingsSearchProvider } from './settingsSearchProvider'; - -function request(query: string): GlobalSearchRequest { - const labels: Record = { - 'navigation.categories.tools': 'Tools & Integrations', - 'navigation.pages.automation.label': 'Automation', - 'navigation.pages.automation.description': 'Quick actions and Agent lifecycle hooks.', - 'navigation.views.quick-actions': 'Quick Actions', - 'navigation.views.hooks': 'Hooks', - 'navigation.pages.mcp.label': 'MCP', - 'navigation.pages.mcp.description': 'Manage MCP servers, connections, and exposed tools.', - 'navigation.pages.acp.label': 'ACP Agents', - 'navigation.pages.acp.description': 'Configure external agents that connect through Agent Client Protocol.', - 'navigation.categories.data': 'Data & Maintenance', - 'navigation.pages.archivedSessions.label': 'Archived Sessions', - 'navigation.pages.archivedSessions.description': 'View, restore, or permanently delete archived sessions.', - }; - return { - rawQuery: query, - query, - scope: 'all', - workspaces: [], - currentWorkspace: null, - limitPerGroup: 10, - tCommon: (key) => key, - tSettings: (key) => labels[key] ?? key, - }; -} - -describe('settingsSearchProvider', () => { - it('targets an internal settings view instead of its parent default view', async () => { - const result = await settingsSearchProvider.search( - request('hooks'), - new AbortController().signal, - ); - const hooks = result.items.find((item) => item.id === 'settings:tools.automation:hooks'); - - expect(hooks?.target).toEqual({ - kind: 'settings', - destination: { pageId: 'tools.automation', viewId: 'hooks' }, - }); - expect(hooks?.score).toBe(100); - }); - - it('targets archived sessions as a standalone settings page', async () => { - const result = await settingsSearchProvider.search( - request('archived sessions'), - new AbortController().signal, - ); - const archived = result.items.find((item) => item.id === 'settings:data.archived'); - - expect(archived?.title).toBe('Archived Sessions'); - expect(archived?.target).toEqual({ - kind: 'settings', - destination: { pageId: 'data.archived' }, - }); - }); - - it.each([ - ['mcp', 'tools.mcp'], - ['acp', 'tools.acp'], - ] as const)('targets %s as a standalone settings page', async (query, pageId) => { - const result = await settingsSearchProvider.search( - request(query), - new AbortController().signal, - ); - const item = result.items.find((candidate) => candidate.id === `settings:${pageId}`); - - expect(item?.target).toEqual({ - kind: 'settings', - destination: { pageId }, - }); - }); -}); diff --git a/src/web-ui/src/app/global-search/providers/settingsSearchProvider.ts b/src/web-ui/src/app/global-search/providers/settingsSearchProvider.ts deleted file mode 100644 index ee76677828..0000000000 --- a/src/web-ui/src/app/global-search/providers/settingsSearchProvider.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { SETTINGS_CATEGORIES } from '@/app/scenes/settings/settingsRegistry'; -import { scoreTextMatch } from '../searchMatching'; -import type { GlobalSearchProvider } from '../types'; - -export const settingsSearchProvider: GlobalSearchProvider = { - id: 'settings', - groups: ['settings'], - search: (request) => { - if (request.scope !== 'all' || !request.query) return { items: [] }; - - const items = SETTINGS_CATEGORIES.flatMap((category) => category.pages.flatMap((page) => { - const categoryTitle = request.tSettings(category.labelKey); - const pageTitle = request.tSettings(page.labelKey); - const description = request.tSettings(page.descriptionKey); - const baseFields = [pageTitle, description, categoryTitle, ...page.keywords]; - - if (!page.views?.length) { - return [{ - id: `settings:${page.id}`, - providerId: 'settings', - group: 'settings' as const, - title: pageTitle, - subtitle: description, - score: scoreTextMatch(request.query, baseFields), - target: { kind: 'settings' as const, destination: { pageId: page.id } }, - }]; - } - - return page.views.map((view) => { - const viewTitle = request.tSettings(view.labelKey); - return { - id: `settings:${page.id}:${view.id}`, - providerId: 'settings', - group: 'settings' as const, - title: viewTitle, - subtitle: `${pageTitle} · ${description}`, - score: scoreTextMatch(request.query, [ - viewTitle, - view.id, - ...view.keywords, - ...baseFields, - ]), - target: { - kind: 'settings' as const, - destination: { pageId: page.id, viewId: view.id }, - }, - }; - }); - })).filter((item) => item.score > 0); - - return { items }; - }, -}; diff --git a/src/web-ui/src/app/global-search/searchMatching.test.ts b/src/web-ui/src/app/global-search/searchMatching.test.ts index f903d0da60..f817957df7 100644 --- a/src/web-ui/src/app/global-search/searchMatching.test.ts +++ b/src/web-ui/src/app/global-search/searchMatching.test.ts @@ -25,4 +25,8 @@ describe('scoreTextMatch', () => { expect(scoreTextMatch('term', ['open terminal'])).toBeGreaterThan(scoreTextMatch('term', ['preterminal panel'])); expect(scoreTextMatch('missing', ['terminal'])).toBe(0); }); + + it('matches natural multi-term queries across bilingual catalog fields', () => { + expect(scoreTextMatch('Hooks 设置', ['Hooks', '自动化设置'])).toBeGreaterThan(0); + }); }); diff --git a/src/web-ui/src/app/global-search/searchMatching.ts b/src/web-ui/src/app/global-search/searchMatching.ts index 8e03ca2c67..1cd82c1314 100644 --- a/src/web-ui/src/app/global-search/searchMatching.ts +++ b/src/web-ui/src/app/global-search/searchMatching.ts @@ -41,9 +41,11 @@ export function scoreTextMatch(query: string, fields: Array 1 + && queryTokens.every((token) => normalizedFields.some((field) => field.includes(token))) + ) { + best = Math.max(best, 72); + } return best; } diff --git a/src/web-ui/src/app/global-search/types.ts b/src/web-ui/src/app/global-search/types.ts index 078a2a271d..9a6062c37f 100644 --- a/src/web-ui/src/app/global-search/types.ts +++ b/src/web-ui/src/app/global-search/types.ts @@ -11,6 +11,7 @@ export type GlobalSearchGroupId = | 'files' | 'workspaces' | 'assistants' + | 'capabilities' | 'settings'; export type GlobalSearchTarget = @@ -36,7 +37,8 @@ export type GlobalSearchTarget = fileName: string; lineNumber?: number; } - | { kind: 'settings'; destination: SettingsDestination }; + | { kind: 'settings'; destination: SettingsDestination } + | { kind: 'capability'; capabilityId: string; itemId?: string }; export interface GlobalSearchItem { id: string; @@ -100,5 +102,6 @@ export const GLOBAL_SEARCH_GROUP_ORDER: readonly GlobalSearchGroupId[] = [ 'files', 'workspaces', 'assistants', + 'capabilities', 'settings', ]; diff --git a/src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts b/src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts index 57698ca972..37c1488a2b 100644 --- a/src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts +++ b/src/web-ui/src/app/scenes/browser/useEmbeddedBrowserWebview.ts @@ -140,6 +140,13 @@ async function setWebviewBounds(label: string, bounds: WebviewBounds): Promise { + const { invoke } = await import('@tauri-apps/api/core'); + await invoke('browser_webview_set_agent_target_state', { + request: { label, active }, + }); +} + async function createBrowserWebview(label: string, url: string, bounds: WebviewBounds): Promise { const [{ invoke }, { Webview }] = await Promise.all([ import('@tauri-apps/api/core'), @@ -283,6 +290,7 @@ export function useEmbeddedBrowserWebview(options: UseEmbeddedBrowserWebviewOpti if (!target) return; try { + await setAgentTargetState(target.label, false).catch(() => {}); await target.close(); } catch (closeError) { if (!isWebviewNotFoundError(closeError)) { @@ -418,6 +426,7 @@ export function useEmbeddedBrowserWebview(options: UseEmbeddedBrowserWebviewOpti if (isVisible) { await handle.show(); await handle.setFocus(); + await setAgentTargetState(handle.label, true); } } catch (loadError) { const message = formatUnknownError(loadError); @@ -457,6 +466,10 @@ export function useEmbeddedBrowserWebview(options: UseEmbeddedBrowserWebviewOpti void syncWebviewBounds() .then(() => webviewRef.current?.show()) .then(() => webviewRef.current?.setFocus()) + .then(() => { + const label = webviewRef.current?.label; + return label ? setAgentTargetState(label, true) : undefined; + }) .catch((syncError) => { log.warn('Activate browser webview failed', syncError); }); @@ -469,9 +482,13 @@ export function useEmbeddedBrowserWebview(options: UseEmbeddedBrowserWebviewOpti label: webviewRef.current.label, }); // #endregion - void webviewRef.current.hide().catch((hideError) => { - log.warn('Hide browser webview on deactivate failed', hideError); - }); + const handle = webviewRef.current; + void setAgentTargetState(handle.label, false) + .catch(() => {}) + .then(() => handle.hide()) + .catch((hideError) => { + log.warn('Hide browser webview on deactivate failed', hideError); + }); } }, [isTauri, isVisible, loadUrl, log, syncWebviewBounds]); diff --git a/src/web-ui/src/app/scenes/ecosystem-compatibility/EcosystemCompatibilityScene.tsx b/src/web-ui/src/app/scenes/ecosystem-compatibility/EcosystemCompatibilityScene.tsx index 2e64af83a5..baaff85c94 100644 --- a/src/web-ui/src/app/scenes/ecosystem-compatibility/EcosystemCompatibilityScene.tsx +++ b/src/web-ui/src/app/scenes/ecosystem-compatibility/EcosystemCompatibilityScene.tsx @@ -309,7 +309,7 @@ const EcosystemCompatibilityScene: React.FC = () => { detail: { clientId: client.id }, })); notification.info(t('run.starting', { name: client.name || client.id }), { duration: 2400 }); - }, [notification, t, workspacePath]); + }, [notification, setOwnerSurface, t, workspacePath]); const handleConfigureSubagent = useCallback((client: AcpClientInfo) => { if (!client.subagent) return; diff --git a/src/web-ui/src/app/scenes/settings/SettingsNavTypography.test.ts b/src/web-ui/src/app/scenes/settings/SettingsNavTypography.test.ts index e354099c55..ba99121d24 100644 --- a/src/web-ui/src/app/scenes/settings/SettingsNavTypography.test.ts +++ b/src/web-ui/src/app/scenes/settings/SettingsNavTypography.test.ts @@ -24,7 +24,7 @@ describe('SettingsNav typography', () => { it('matches the main navigation category and item reading rhythm', () => { const stylesheet = readSettingsNavStylesheet(); - expect(stylesheet).toContain('font-size: var(--bf-appearance-token-font-size-xs);\n font-weight: 500;\n letter-spacing: 0.015em;\n line-height: 1.25;'); + expect(stylesheet).toContain('font-size: calc(var(--bf-appearance-token-font-size-xs) - 1px);\n font-weight: 500;\n letter-spacing: 0.015em;\n line-height: 1.25;'); expect(stylesheet).toContain('font-size: var(--bf-appearance-token-font-size-sm);\n font-weight: 400;\n line-height: 1.25;'); expect(stylesheet).toContain('&.is-active {\n @include nav-font.nav-panel-text-heading;\n\n background: var(--bf-appearance-token-element-bg-soft);\n font-weight: 600;'); }); diff --git a/src/web-ui/src/infrastructure/api/adapters/peer-device-adapter.ts b/src/web-ui/src/infrastructure/api/adapters/peer-device-adapter.ts index 86e8a3e796..95ac819c98 100644 --- a/src/web-ui/src/infrastructure/api/adapters/peer-device-adapter.ts +++ b/src/web-ui/src/infrastructure/api/adapters/peer-device-adapter.ts @@ -74,6 +74,8 @@ const LOCAL_ONLY_COMMANDS = new Set([ 'peer_controller_set_active', 'computer_use_request_permissions', 'computer_use_open_system_settings', + // Native child-WebView lifecycle belongs to this controller window. + 'browser_webview_set_agent_target_state', // Detached dispatch uses this controller's SSH credentials and observer index. 'dispatch_list_targets', 'dispatch_probe_target', diff --git a/src/web-ui/src/infrastructure/i18n/presets/namespaceRegistry.ts b/src/web-ui/src/infrastructure/i18n/presets/namespaceRegistry.ts index eaba55ed24..9ab7953355 100644 --- a/src/web-ui/src/infrastructure/i18n/presets/namespaceRegistry.ts +++ b/src/web-ui/src/infrastructure/i18n/presets/namespaceRegistry.ts @@ -26,7 +26,6 @@ export const ALL_NAMESPACES = [ 'settings/acp-agents', 'settings/agentic-tools', 'settings/ai-features', - 'settings/models', 'settings/appearance', 'settings/application', 'settings/default-model', @@ -37,6 +36,7 @@ export const ALL_NAMESPACES = [ 'settings/mcp', 'settings/mcp-tools', 'settings/memory', + 'settings/models', 'settings/quick-actions', 'settings/review-capacity', 'settings/runtime', diff --git a/src/web-ui/src/locales/en-US/common.json b/src/web-ui/src/locales/en-US/common.json index 3c06b38262..7b9d3d08e7 100644 --- a/src/web-ui/src/locales/en-US/common.json +++ b/src/web-ui/src/locales/en-US/common.json @@ -142,6 +142,7 @@ "files": "Files", "workspaces": "Projects", "assistants": "Assistants", + "capabilities": "Features", "settings": "$t(shared:features.settings)" }, "actions": { diff --git a/src/web-ui/src/locales/zh-CN/common.json b/src/web-ui/src/locales/zh-CN/common.json index aaaec689b2..27503caa51 100644 --- a/src/web-ui/src/locales/zh-CN/common.json +++ b/src/web-ui/src/locales/zh-CN/common.json @@ -142,6 +142,7 @@ "files": "文件", "workspaces": "项目", "assistants": "助理", + "capabilities": "功能", "settings": "$t(shared:features.settings)" }, "actions": { diff --git a/src/web-ui/src/locales/zh-TW/common.json b/src/web-ui/src/locales/zh-TW/common.json index 2b50bcb2dd..cf306bba35 100644 --- a/src/web-ui/src/locales/zh-TW/common.json +++ b/src/web-ui/src/locales/zh-TW/common.json @@ -142,6 +142,7 @@ "files": "檔案", "workspaces": "項目", "assistants": "助理", + "capabilities": "功能", "settings": "$t(shared:features.settings)" }, "actions": { diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000000..5925c9c447 --- /dev/null +++ b/website/README.md @@ -0,0 +1,33 @@ +# BitFun Playbook + +BitFun Playbook is the public, bilingual manual for BitFun's user-facing +features and settings. It does not maintain its own list. The build consumes +`../docs/interactive-capabilities/capabilities.json`, generated from the single +semantic source at `../src/shared/interactive-capabilities/catalog.json`. + +Desktop Tauri commands are audited separately as implementation coverage. They +never become website pages or user-visible search entries. + +The same generated runtime projection powers BitFun search and the +`BitFunControl` agent tool. Search results carry a documented item ID when a +query matches a settings subview, so entries such as Shortcuts, Editor, and +Hooks open the exact view instead of only the parent settings page. Complex or +unsafe workflows remain UI-guided; the agent surface exposes only typed, +reviewed operations and options rather than raw Tauri commands. + +```bash +pnpm run capabilities:generate +pnpm run website:dev +pnpm run website:test +pnpm run website:build +``` + +The color theme defaults to the operating-system preference. The header control +lets readers explicitly choose System, Light, or Dark; an explicit choice is +stored only in that browser. + +Every build writes `dist/release.json`. Deploy using its `releaseId`, which +changes for either catalog or website-source changes, so a presentation-only +update never mutates an older release directory. + +The production origin is . diff --git a/website/package.json b/website/package.json new file mode 100644 index 0000000000..627d8e94b9 --- /dev/null +++ b/website/package.json @@ -0,0 +1,11 @@ +{ + "name": "bitfun-playbook", + "private": true, + "type": "module", + "scripts": { + "build": "node scripts/build.mjs", + "dev": "node scripts/serve.mjs --watch --port 4174", + "preview": "node scripts/serve.mjs --port 4174", + "test": "node --test scripts/site-ui.test.mjs" + } +} diff --git a/website/scripts/build.mjs b/website/scripts/build.mjs new file mode 100644 index 0000000000..531da99920 --- /dev/null +++ b/website/scripts/build.mjs @@ -0,0 +1,127 @@ +#!/usr/bin/env node + +import { createHash } from 'node:crypto'; +import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const buildScriptPath = fileURLToPath(import.meta.url); +const websiteRoot = path.resolve(path.dirname(buildScriptPath), '..'); +const repositoryRoot = path.resolve(websiteRoot, '..'); +const sourceRoot = path.join(websiteRoot, 'src'); +const outputRoot = path.join(websiteRoot, 'dist'); +const catalogPath = path.join(repositoryRoot, 'docs/interactive-capabilities/capabilities.json'); + +function escapeHtml(value) { + return String(value) + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); +} + +function embeddedJson(value) { + return JSON.stringify(value).replaceAll('<', '\\u003c'); +} + +function renderPage(template, { title, description, url, pageData, assetVersion }) { + return template + .replaceAll('__PAGE_TITLE__', escapeHtml(title)) + .replaceAll('__PAGE_DESCRIPTION__', escapeHtml(description)) + .replaceAll('__PAGE_URL__', escapeHtml(url)) + .replaceAll('__ASSET_VERSION__', escapeHtml(assetVersion)) + .replace('__PAGE_DATA__', embeddedJson(pageData)); +} + +async function main() { + const catalog = JSON.parse(await readFile(catalogPath, 'utf8')); + const template = await readFile(path.join(sourceRoot, 'index.html'), 'utf8'); + const appSource = await readFile(path.join(sourceRoot, 'app.js'), 'utf8'); + const stylesSource = await readFile(path.join(sourceRoot, 'styles.css'), 'utf8'); + const buildSource = await readFile(buildScriptPath); + const logoPath = path.join(repositoryRoot, 'src/apps/desktop/icons/Logo-ICON.png'); + const logoSource = await readFile(logoPath); + const socialImage = path.join(sourceRoot, 'og.png'); + let socialSource = Buffer.alloc(0); + try { + socialSource = await readFile(socialImage); + } catch (error) { + if (error?.code !== 'ENOENT') throw error; + } + const assetVersion = createHash('sha256') + .update(catalog.digest) + .update(template) + .update(appSource) + .update(stylesSource) + .update(buildSource) + .update(logoSource) + .update(socialSource) + .digest('hex') + .slice(0, 12); + + await rm(outputRoot, { recursive: true, force: true }); + await mkdir(path.join(outputRoot, 'assets'), { recursive: true }); + await cp(path.join(sourceRoot, 'app.js'), path.join(outputRoot, 'assets/app.js')); + await cp(path.join(sourceRoot, 'styles.css'), path.join(outputRoot, 'assets/styles.css')); + await cp(logoPath, path.join(outputRoot, 'assets/bitfun.png')); + + try { + await cp(socialImage, path.join(outputRoot, 'og.png')); + } catch (error) { + if (error?.code !== 'ENOENT') throw error; + } + + await mkdir(path.join(outputRoot, 'data'), { recursive: true }); + await writeFile( + path.join(outputRoot, 'data/capabilities.json'), + `${JSON.stringify(catalog)}\n`, + ); + await writeFile( + path.join(outputRoot, 'release.json'), + `${JSON.stringify({ + releaseId: assetVersion, + assetVersion, + catalogDigest: catalog.digest, + }, null, 2)}\n`, + ); + + const homeDescription = `Learn ${catalog.counts.features} BitFun features and ${catalog.counts.settings} settings pages in Chinese or English.`; + await writeFile(path.join(outputRoot, 'index.html'), renderPage(template, { + title: 'BitFun Playbook — Features, settings, and practical guides', + description: homeDescription, + url: `${catalog.origin}/`, + assetVersion, + pageData: { kind: 'index', digest: catalog.digest }, + })); + + for (const capability of catalog.capabilities) { + const directory = path.join(outputRoot, 'capabilities', capability.id); + await mkdir(directory, { recursive: true }); + await writeFile(path.join(directory, 'index.html'), renderPage(template, { + title: `${capability.titleEn} / ${capability.titleZh} — BitFun Playbook`, + description: capability.summaryEn, + url: capability.docsUrl, + assetVersion, + pageData: { kind: 'capability', capabilityId: capability.id, digest: catalog.digest }, + })); + } + + const sitemap = catalog.capabilities + .map(({ docsUrl }) => ` ${escapeHtml(docsUrl)}`) + .join('\n'); + await writeFile( + path.join(outputRoot, 'sitemap.xml'), + `\n\n ${catalog.origin}/\n${sitemap}\n\n`, + ); + await writeFile( + path.join(outputRoot, 'robots.txt'), + `User-agent: *\nAllow: /\nSitemap: ${catalog.origin}/sitemap.xml\n`, + ); + + process.stdout.write( + `Built BitFun Playbook ${assetVersion} with ${catalog.counts.features} feature guides + ${catalog.counts.settings} settings guides (${catalog.digest.slice(0, 12)} catalog).\n`, + ); +} + +await main(); diff --git a/website/scripts/serve.mjs b/website/scripts/serve.mjs new file mode 100644 index 0000000000..3e5c12601f --- /dev/null +++ b/website/scripts/serve.mjs @@ -0,0 +1,70 @@ +#!/usr/bin/env node + +import { createReadStream, existsSync, statSync, watch } from 'node:fs'; +import { spawnSync } from 'node:child_process'; +import { createServer } from 'node:http'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const websiteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const repositoryRoot = path.resolve(websiteRoot, '..'); +const outputRoot = path.join(websiteRoot, 'dist'); +const args = process.argv.slice(2); +const portIndex = args.indexOf('--port'); +const port = Number(portIndex >= 0 ? args[portIndex + 1] : 4174); +const watchMode = args.includes('--watch'); +const contentTypes = new Map([ + ['.css', 'text/css; charset=utf-8'], + ['.html', 'text/html; charset=utf-8'], + ['.js', 'text/javascript; charset=utf-8'], + ['.json', 'application/json; charset=utf-8'], + ['.png', 'image/png'], + ['.txt', 'text/plain; charset=utf-8'], + ['.xml', 'application/xml; charset=utf-8'], +]); + +function build() { + const result = spawnSync(process.execPath, ['scripts/build.mjs'], { + cwd: websiteRoot, + stdio: 'inherit', + }); + if (result.status !== 0) process.exit(result.status ?? 1); +} + +function resolveRequest(requestUrl) { + const pathname = decodeURIComponent(new URL(requestUrl, `http://localhost:${port}`).pathname); + const requested = path.resolve(outputRoot, `.${pathname}`); + if (!requested.startsWith(`${outputRoot}${path.sep}`) && requested !== outputRoot) return null; + if (existsSync(requested) && statSync(requested).isFile()) return requested; + const index = path.join(requested, 'index.html'); + if (existsSync(index)) return index; + return path.join(outputRoot, 'index.html'); +} + +build(); + +if (watchMode) { + let timer; + const rebuild = () => { + clearTimeout(timer); + timer = setTimeout(build, 120); + }; + watch(path.join(websiteRoot, 'src'), { recursive: true }, rebuild); + watch(path.join(repositoryRoot, 'docs/interactive-capabilities'), { recursive: true }, rebuild); +} + +createServer((request, response) => { + const file = resolveRequest(request.url ?? '/'); + if (!file || !existsSync(file)) { + response.writeHead(404).end('Not found'); + return; + } + response.writeHead(200, { + 'Cache-Control': file.endsWith('.html') ? 'no-cache' : 'public, max-age=300', + 'Content-Type': contentTypes.get(path.extname(file)) ?? 'application/octet-stream', + 'X-Content-Type-Options': 'nosniff', + }); + createReadStream(file).pipe(response); +}).listen(port, '127.0.0.1', () => { + process.stdout.write(`BitFun Playbook: http://127.0.0.1:${port}/\n`); +}); diff --git a/website/scripts/site-ui.test.mjs b/website/scripts/site-ui.test.mjs new file mode 100644 index 0000000000..2111d6256d --- /dev/null +++ b/website/scripts/site-ui.test.mjs @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +import assert from 'node:assert/strict'; +import { execFile } from 'node:child_process'; +import { readFile } from 'node:fs/promises'; +import path from 'node:path'; +import { promisify } from 'node:util'; +import { fileURLToPath } from 'node:url'; +import test from 'node:test'; + +const execFileAsync = promisify(execFile); +const websiteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const repositoryRoot = path.resolve(websiteRoot, '..'); +const sourceRoot = path.join(websiteRoot, 'src'); + +await execFileAsync(process.execPath, [path.join(websiteRoot, 'scripts/build.mjs')], { + cwd: repositoryRoot, +}); + +const [appSource, stylesSource, templateSource, builtIndex, releaseSource] = await Promise.all([ + readFile(path.join(sourceRoot, 'app.js'), 'utf8'), + readFile(path.join(sourceRoot, 'styles.css'), 'utf8'), + readFile(path.join(sourceRoot, 'index.html'), 'utf8'), + readFile(path.join(websiteRoot, 'dist/index.html'), 'utf8'), + readFile(path.join(websiteRoot, 'dist/release.json'), 'utf8'), +]); + +function cssBlock(selector) { + const escaped = selector.replaceAll(/[.*+?^${}()|[\]\\]/gu, '\\$&'); + const match = stylesSource.match(new RegExp(`${escaped}\\s*\\{([^}]*)\\}`, 'u')); + assert.ok(match, `missing CSS block: ${selector}`); + return match[1]; +} + +function customProperties(block) { + return Object.fromEntries( + [...block.matchAll(/(--[a-z-]+)\s*:\s*([^;]+);/gu)] + .map(([, key, value]) => [key, value.trim()]), + ); +} + +test('theme contract defaults to system and exposes all three choices', () => { + assert.match(templateSource, /localStorage\.getItem\('bitfun-playbook-theme'\)/u); + assert.match(templateSource, /let theme = 'system'/u); + assert.match(templateSource, /prefers-color-scheme: dark/u); + assert.match(appSource, /const THEME_CHOICES = \['system', 'light', 'dark'\]/u); + assert.match(appSource, /data-theme-choice="\$\{theme\}"/u); + assert.match(appSource, /addEventListener\('change'/u); + assert.match(stylesSource, /html\[data-theme='dark'\]/u); + assert.match(stylesSource, /html\[data-theme='system'\]/u); + + const explicitDark = customProperties(cssBlock("html[data-theme='dark']")); + const systemDark = customProperties(cssBlock("html[data-theme='system']")); + assert.deepEqual(systemDark, explicitDark, 'system-dark tokens must match explicit dark mode'); +}); + +test('hero title, search, and statistics remain in layout flow', () => { + assert.match(appSource, /

\$\{text\([\s\S]*?[\s\S]*?/u); + assert.match(appSource, /
[\s\S]*? + ${footer()} + `, 'index-page'); + bindCommonEvents(); + document.querySelector('#search-form')?.addEventListener('submit', (event) => event.preventDefault()); + const searchInput = document.querySelector('#capability-search'); + let composing = false; + const applySearchInput = () => { + state.query = searchInput.value; + const url = new URL(location.href); + if (state.query) url.searchParams.set('q', state.query); + else url.searchParams.delete('q'); + history.replaceState(null, '', url); + updateIndexResults(); + }; + searchInput?.addEventListener('compositionstart', () => { + composing = true; + }); + searchInput?.addEventListener('compositionend', () => { + composing = false; + applySearchInput(); + }); + searchInput?.addEventListener('input', (event) => { + if (!composing && !event.isComposing) applySearchInput(); + }); + document.querySelectorAll('[data-kind]').forEach((button) => { + button.addEventListener('click', () => { + state.kind = button.dataset.kind; + renderIndex(); + }); + }); + document.querySelectorAll('[data-category]').forEach((button) => { + button.addEventListener('click', () => { + state.category = button.dataset.category; + renderIndex(); + }); + }); +} + +function destinationLabel(capability) { + if (capability.destination.kind === 'settings') { + return text('BitFun 设置中的对应页面', 'The matching page in BitFun Settings'); + } + return text('BitFun 中的对应功能入口', 'The matching feature entry in BitFun'); +} + +function schemaLabel(schema) { + if (schema.enum) return schema.enum.map(String).join(' / '); + if (schema.type === 'boolean') return text('开 / 关', 'On / Off'); + if (schema.minimum !== undefined || schema.maximum !== undefined) { + return `${schema.minimum ?? '…'}–${schema.maximum ?? '…'}`; + } + return schema.type; +} + +function operationCards(capability) { + if (capability.agentControl) { + const workflow = localized(capability.agentControl, 'workflow'); + return `
    ${workflow.map((step, index) => ` +
  1. ${index + 1}

    ${escapeHtml(capability.agentControl.tool)} · ${escapeHtml(step)}

  2. `).join('')}
`; + } + if (!capability.operations.length) { + return `
${text( + '这个功能通过“打开”进入界面,具体操作在页面里完成。', + 'Use Open to enter this feature, then complete its actions in the interface.', + )}
`; + } + return `
${capability.operations.map((operation) => ` +
+

${escapeHtml(localized(operation, 'title'))}

+

${escapeHtml(localized(operation, 'description'))}

+
`).join('')}
`; +} + +function optionRows(capability) { + if (!capability.options.length) { + return `
${text( + '这个页面的配置需要在 BitFun 界面中确认和完成。Agent 可以先替你打开到这里。', + 'These controls require confirmation in the BitFun interface. An agent can still open this page for you.', + )}
`; + } + return `
${capability.options.map((option) => ` +
+

${escapeHtml(localized(option, 'title'))}

+

${escapeHtml(localized(option, 'description'))}

+ ${escapeHtml(schemaLabel(option.valueSchema))} +
`).join('')}
`; +} + +function renderCapability(capability) { + const category = state.catalog.categories[capability.categoryId]; + const steps = localized(capability, 'steps'); + const examples = localized(capability, 'agentExamples'); + root.innerHTML = pageFrame(` +
+ +
+
+
${kindLabel(capability.kind)}${escapeHtml(categoryTitle(category))}
+

${escapeHtml(localized(capability, 'title'))}

+

${escapeHtml(alternate(capability, 'title'))}

+

${escapeHtml(localized(capability, 'summary'))}

+
${text('在哪里找到', 'Where to find it')}${destinationLabel(capability)}
+ +
+ +

${text('完整功能清单', 'Everything included')}

+
    ${capability.items.map((item) => `
  • ${escapeHtml(localized(item, 'title'))}${escapeHtml(alternate(item, 'title'))}
  • `).join('')}
+
+ +
+ +

${text('怎么用', 'How to use it')}

+
    ${steps.map((step, index) => `
  1. ${index + 1}

    ${escapeHtml(step)}

  2. `).join('')}
+
+ + ${capability.kind === 'feature' ? ` +
+ +

${text('Agent 可以直接执行', 'What an agent can execute')}

+ ${operationCards(capability)} +
` : ` +
+ +

${text('可配置选项', 'Configurable options')}

+ ${optionRows(capability)} +
`} + +
+ +

${text('可以直接对 Agent 说', 'Try saying this to an agent')}

+
${examples.map((example) => ` + `).join('')}
+
+
+ + +
+
+ ${footer()} + `, 'detail-page'); + bindCommonEvents(); + const focusedItemId = new URLSearchParams(location.search).get('focus'); + const focusedItem = focusedItemId + ? document.querySelector(`[data-inventory-item="${CSS.escape(focusedItemId)}"]`) + : null; + if (focusedItem) { + focusedItem.classList.add('focused'); + requestAnimationFrame(() => focusedItem.scrollIntoView({ block: 'center', behavior: 'smooth' })); + } + const copyPrompt = async (button, prompt) => { + await navigator.clipboard.writeText(prompt); + const label = button.querySelector('small'); + if (label) label.textContent = text('已复制', 'Copied'); + else button.textContent = text('已复制', 'Copied'); + }; + document.querySelectorAll('[data-copy-prompt]').forEach((button) => { + button.addEventListener('click', () => void copyPrompt(button, button.dataset.copyPrompt)); + }); + document.querySelector('[data-copy-first]')?.addEventListener('click', (event) => { + void copyPrompt(event.currentTarget, examples[0]); + }); +} + +function bindCommonEvents() { + const sidebarNav = document.querySelector('[data-sidebar-scroll]'); + const saveSidebarScroll = () => { + if (sidebarNav) writeSessionPreference(SIDEBAR_SCROLL_STORAGE_KEY, String(sidebarNav.scrollTop)); + }; + sidebarNav?.addEventListener('scroll', saveSidebarScroll, { passive: true }); + document.querySelectorAll('.sidebar-home, [data-sidebar-item]').forEach((link) => { + link.addEventListener('click', saveSidebarScroll); + }); + const storedSidebarScroll = readSessionPreference(SIDEBAR_SCROLL_STORAGE_KEY); + requestAnimationFrame(() => { + if (!sidebarNav) return; + const savedScrollTop = Number(storedSidebarScroll); + if (storedSidebarScroll !== null && Number.isFinite(savedScrollTop) && savedScrollTop >= 0) { + sidebarNav.scrollTop = savedScrollTop; + } + const activeItem = sidebarNav.querySelector('[aria-current="page"]'); + if (!activeItem) return; + const navRect = sidebarNav.getBoundingClientRect(); + const itemRect = activeItem.getBoundingClientRect(); + if (itemRect.top < navRect.top || itemRect.bottom > navRect.bottom) { + sidebarNav.scrollTop += itemRect.top - navRect.top - (navRect.height - itemRect.height) / 2; + } + }); + const setSidebarOpen = (open) => { + document.body.classList.toggle('sidebar-open', open); + document.querySelector('#sidebar-toggle')?.setAttribute('aria-expanded', String(open)); + if (open) document.querySelector('#sidebar-search')?.focus(); + }; + document.querySelector('#sidebar-toggle')?.addEventListener('click', () => setSidebarOpen(true)); + document.querySelector('#sidebar-close')?.addEventListener('click', () => setSidebarOpen(false)); + document.querySelector('#sidebar-backdrop')?.addEventListener('click', () => setSidebarOpen(false)); + document.querySelector('#sidebar-search')?.addEventListener('input', (event) => { + const needle = normalize(event.target.value); + const tokens = needle.split(/\s+/u).filter(Boolean); + document.querySelectorAll('[data-sidebar-item]').forEach((item) => { + item.hidden = tokens.length > 0 && !tokens.every((token) => item.dataset.sidebarSearch.includes(token)); + }); + document.querySelectorAll('[data-sidebar-group]').forEach((group) => { + group.hidden = !group.querySelector('[data-sidebar-item]:not([hidden])'); + }); + document.querySelectorAll('[data-sidebar-section]').forEach((section) => { + section.hidden = !section.querySelector('[data-sidebar-item]:not([hidden])'); + }); + const hasResults = !!document.querySelector('[data-sidebar-item]:not([hidden])'); + const empty = document.querySelector('#sidebar-empty'); + if (empty) empty.hidden = hasResults; + }); + document.querySelector('#language-toggle')?.addEventListener('click', () => { + saveSidebarScroll(); + document.body.classList.remove('sidebar-open'); + state.language = state.language === 'zh' ? 'en' : 'zh'; + writePreference('bitfun-playbook-language', state.language); + render(); + }); + document.querySelectorAll('[data-theme-choice]').forEach((button) => { + button.addEventListener('click', () => applyTheme(button.dataset.themeChoice)); + }); +} + +function render() { + document.documentElement.lang = state.language === 'zh' ? 'zh-CN' : 'en'; + if (pageData.kind === 'capability') { + const capability = state.catalog.capabilities.find(({ id }) => id === pageData.capabilityId); + if (capability) renderCapability(capability); + else renderIndex(); + } else { + renderIndex(); + } +} + +document.addEventListener('keydown', (event) => { + if (event.key === 'Escape' && document.body.classList.contains('sidebar-open')) { + document.body.classList.remove('sidebar-open'); + document.querySelector('#sidebar-toggle')?.setAttribute('aria-expanded', 'false'); + document.querySelector('#sidebar-toggle')?.focus(); + return; + } + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') { + event.preventDefault(); + if (pageData.kind === 'capability') location.href = '/'; + else document.querySelector('#capability-search')?.focus(); + } +}); + +window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + if (state.theme === 'system') applyTheme('system', false); +}); + +applyTheme(state.theme, false); + +try { + const response = await fetch('/data/capabilities.json'); + if (!response.ok) throw new Error(`Catalog request failed: ${response.status}`); + state.catalog = await response.json(); + render(); +} catch (error) { + root.innerHTML = `

BitFun Playbook

${escapeHtml(error.message)}

`; +} diff --git a/website/src/index.html b/website/src/index.html new file mode 100644 index 0000000000..e1abe224c3 --- /dev/null +++ b/website/src/index.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + __PAGE_TITLE__ + + + +
+
+ B + Loading BitFun Playbook… +
+
+ + + diff --git a/website/src/og.png b/website/src/og.png new file mode 100644 index 0000000000..7d1a51a7bd Binary files /dev/null and b/website/src/og.png differ diff --git a/website/src/styles.css b/website/src/styles.css new file mode 100644 index 0000000000..9dea92e808 --- /dev/null +++ b/website/src/styles.css @@ -0,0 +1,365 @@ +:root { + color-scheme: light; + --paper: #f6f5f0; + --ink: #171714; + --muted: #6c6b64; + --line: #dcdad1; + --panel: #fbfaf6; + --accent: #f2663b; + --accent-soft: #f7ded4; + --agent-panel: #bdd663; + --agent-panel-ink: #29380b; + --agent-panel-muted: #667338; + --agent-panel-border: #171714; + --grid-line: rgba(23, 23, 20, 0.035); + --panel-translucent: rgba(251, 250, 246, 0.86); + --surface-hover: rgba(23, 23, 20, 0.06); + --sidebar-link: #4c4b46; + --accent-ink: #7e321c; + --setting-soft: #dfeacf; + --setting-ink: #405616; + --kbd-bg: #fff; + --focused-bg: #fff3eb; + --backdrop: rgba(23, 23, 20, 0.38); + --shadow: #171714; + --drawer-shadow: rgba(23, 23, 20, 0.18); + --placeholder: #99978d; + --brand-bg: #171714; + --brand-ink: #f6f5f0; + --sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; + --mono: 'SFMono-Regular', Consolas, 'Liberation Mono', ui-monospace, monospace; +} + +html[data-theme='dark'] { + color-scheme: dark; + --paper: #131411; + --ink: #f1efe7; + --muted: #aaa99f; + --line: #36382f; + --panel: #1b1c18; + --accent: #ff7449; + --accent-soft: #48291f; + --agent-panel: #20271a; + --agent-panel-ink: #e3eccb; + --agent-panel-muted: #a4af88; + --agent-panel-border: #52613a; + --grid-line: rgba(241, 239, 231, 0.035); + --panel-translucent: rgba(27, 28, 24, 0.9); + --surface-hover: rgba(241, 239, 231, 0.07); + --sidebar-link: #c8c6bc; + --accent-ink: #ffb79d; + --setting-soft: #314023; + --setting-ink: #d3ec9d; + --kbd-bg: #252620; + --focused-bg: #3b251d; + --backdrop: rgba(0, 0, 0, 0.62); + --shadow: #050604; + --drawer-shadow: rgba(0, 0, 0, 0.42); + --placeholder: #7f8178; +} + +@media (prefers-color-scheme: dark) { + html[data-theme='system'] { + color-scheme: dark; + --paper: #131411; + --ink: #f1efe7; + --muted: #aaa99f; + --line: #36382f; + --panel: #1b1c18; + --accent: #ff7449; + --accent-soft: #48291f; + --agent-panel: #20271a; + --agent-panel-ink: #e3eccb; + --agent-panel-muted: #a4af88; + --agent-panel-border: #52613a; + --grid-line: rgba(241, 239, 231, 0.035); + --panel-translucent: rgba(27, 28, 24, 0.9); + --surface-hover: rgba(241, 239, 231, 0.07); + --sidebar-link: #c8c6bc; + --accent-ink: #ffb79d; + --setting-soft: #314023; + --setting-ink: #d3ec9d; + --kbd-bg: #252620; + --focused-bg: #3b251d; + --backdrop: rgba(0, 0, 0, 0.62); + --shadow: #050604; + --drawer-shadow: rgba(0, 0, 0, 0.42); + --placeholder: #7f8178; + } +} + +* { box-sizing: border-box; } +[hidden] { display: none !important; } +html { scroll-behavior: smooth; } +body { + margin: 0; + background: + linear-gradient(var(--grid-line) 1px, transparent 1px), + linear-gradient(90deg, var(--grid-line) 1px, transparent 1px), + var(--paper); + background-size: 24px 24px; + color: var(--ink); + font-family: var(--sans); + -webkit-font-smoothing: antialiased; +} + +a { color: inherit; } +button, input, textarea, select { font: inherit; } +code, kbd, pre { font-family: var(--mono); } +.page-shell { min-height: 100vh; } +.site-header { width: min(1480px, calc(100% - 40px)); margin-inline: auto; } +.docs-shell { width: min(1480px, calc(100% - 40px)); margin-inline: auto; display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 44px; align-items: start; } +.docs-content { min-width: 0; padding-left: 44px; border-left: 1px solid var(--line); } +.docs-content main, .docs-content .site-footer { width: min(100%, 1240px); margin-inline: auto; } + +.site-header { + height: 88px; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid var(--line); +} +.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; } +.brand-mark { + width: 40px; height: 40px; display: grid; place-items: center; + border-radius: 11px; background: var(--brand-bg); color: var(--brand-ink); + font-weight: 700; font-size: 20px; transform: rotate(-4deg); +} +.brand > span:last-child { display: grid; line-height: 1; gap: 5px; } +.brand strong { font-size: 17px; letter-spacing: -0.03em; } +.brand small { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; color: var(--muted); } +.header-actions { display: flex; align-items: center; gap: 22px; } +.header-link { font-size: 13px; font-weight: 600; text-decoration: none; } +.language-toggle, .copy-button, .sidebar-toggle { + border: 1px solid var(--ink); background: transparent; color: inherit; + border-radius: 999px; padding: 8px 13px; cursor: pointer; font-size: 12px; font-weight: 700; +} +.language-toggle:hover, .copy-button:hover, .sidebar-toggle:hover { background: var(--ink); color: var(--paper); } +.sidebar-toggle { display: none; align-items: center; gap: 7px; } +.theme-control { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel-translucent); } +.theme-control button { display: inline-flex; align-items: center; gap: 5px; min-height: 30px; border: 0; border-radius: 999px; padding: 5px 9px; background: transparent; color: var(--muted); cursor: pointer; font-size: 10px; font-weight: 700; } +.theme-control button:hover { color: var(--ink); } +.theme-control button.active { background: var(--ink); color: var(--paper); } +.theme-control button > span:first-child { font-size: 13px; line-height: 1; } + +.docs-sidebar { + position: sticky; top: 20px; height: calc(100vh - 40px); min-height: 520px; + display: flex; flex-direction: column; padding: 20px 14px 24px 0; overflow: hidden; +} +.sidebar-mobile-head { display: none; align-items: center; justify-content: space-between; padding: 0 4px 16px; } +.sidebar-mobile-head strong { font-size: 14px; } +.sidebar-mobile-head button { width: 34px; height: 34px; border: 1px solid var(--line); border-radius: 9px; background: transparent; cursor: pointer; font-size: 22px; } +.sidebar-search { display: flex; align-items: center; gap: 8px; margin-bottom: 18px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-translucent); } +.sidebar-search:focus-within { border-color: var(--ink); box-shadow: 2px 2px 0 var(--shadow); } +.sidebar-search > span { color: var(--accent); font-size: 18px; transform: rotate(-14deg); } +.sidebar-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font-size: 12px; } +.docs-sidebar nav { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 8px; scrollbar-width: thin; } +.sidebar-home, .sidebar-links a { display: flex; align-items: center; text-decoration: none; border-radius: 8px; } +.sidebar-home { gap: 8px; margin-bottom: 22px; padding: 9px 10px; color: var(--muted); font-size: 12px; font-weight: 650; } +.sidebar-home:hover, .sidebar-home.active { background: var(--ink); color: var(--paper); } +.sidebar-section + .sidebar-section { margin-top: 28px; } +.sidebar-kind-heading { display: flex; align-items: center; justify-content: space-between; padding: 0 8px 12px; border-bottom: 1px solid var(--line); } +.sidebar-kind-heading h2 { margin: 0; font: 700 11px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; } +.sidebar-kind-heading span { color: var(--muted); font: 500 10px/1 var(--mono); } +.sidebar-group { margin-top: 18px; } +.sidebar-group h3 { margin: 0 8px 7px; color: var(--muted); font-size: 10px; font-weight: 650; letter-spacing: 0.04em; } +.sidebar-links { display: grid; gap: 2px; } +.sidebar-links a { min-height: 32px; padding: 7px 9px; color: var(--sidebar-link); font-size: 12px; line-height: 1.45; } +.sidebar-links a:hover { background: var(--surface-hover); color: var(--ink); } +.sidebar-links a.active { position: relative; background: var(--accent-soft); color: var(--accent-ink); font-weight: 750; } +.sidebar-links a.active::before { content: ''; position: absolute; left: 0; width: 3px; height: 16px; border-radius: 99px; background: var(--accent); } +.sidebar-empty { padding: 24px 8px; color: var(--muted); font-size: 12px; line-height: 1.6; } +.sidebar-backdrop { display: none; } + +.hero { padding: 88px 0 78px; } +.eyebrow, .section-label { + margin: 0 0 20px; font: 500 11px/1 var(--mono); letter-spacing: 0.12em; color: var(--muted); +} +.hero h1 { + display: grid; gap: clamp(8px, 1.1vw, 16px); max-width: 940px; margin: 0; + font-size: clamp(52px, 6.4vw, 96px); line-height: 0.94; letter-spacing: -0.065em; font-weight: 600; +} +.hero h1 > span, .hero h1 em { display: block; } +.hero h1 em { font-family: Georgia, 'Songti SC', 'STSong', serif; font-weight: 400; line-height: 1.03; letter-spacing: -0.045em; color: var(--accent); } +.hero-copy { max-width: 650px; margin: 34px 0 38px; font-size: 18px; line-height: 1.7; color: var(--muted); } +.hero-actions { display: grid; grid-template-columns: minmax(420px, 1fr) auto; align-items: end; gap: clamp(24px, 3vw, 44px); } +.search-box { + width: 100%; min-width: 0; height: 68px; display: flex; align-items: center; gap: 14px; + padding: 0 18px 0 22px; border: 1px solid var(--ink); border-radius: 16px; + background: var(--panel); box-shadow: 6px 6px 0 var(--shadow); +} +.search-box:focus-within { box-shadow: 6px 6px 0 var(--accent); } +.search-glyph { font-size: 29px; transform: rotate(-15deg); } +.search-box input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font-size: 17px; color: var(--ink); } +.search-box input::placeholder { color: var(--placeholder); } +.search-box kbd { border: 1px solid var(--line); border-radius: 6px; padding: 5px 7px; background: var(--kbd-bg); color: var(--muted); font-size: 11px; } +.hero-stat { display: flex; align-items: baseline; justify-self: end; gap: 9px; padding: 0 2px 7px 0; white-space: nowrap; transform: rotate(-1deg); } +.hero-stat strong { font: 500 38px/1 var(--mono); color: var(--accent); } +.hero-stat span { font-size: 11px; line-height: 1.35; color: var(--muted); } +.hero-stat i { width: 1px; height: 30px; margin: 0 7px; background: var(--line); transform: rotate(8deg); } + +.catalog-section { border-top: 1px solid var(--line); padding: 56px 0 96px; } +.catalog-toolbar { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 28px; } +.catalog-toolbar .section-label { margin-bottom: 10px; } +.catalog-toolbar h2 { margin: 0; font-size: 34px; letter-spacing: -0.045em; } +.catalog-toolbar > p { margin: 0; color: var(--muted); font-size: 13px; } +.kind-switch { display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel-translucent); } +.kind-switch button { + border: 0; border-radius: 8px; padding: 10px 16px; background: transparent; color: var(--muted); + cursor: pointer; font-size: 13px; font-weight: 600; +} +.kind-switch button span { margin-left: 5px; font: 500 10px/1 var(--mono); } +.kind-switch button.active { background: var(--ink); color: var(--paper); } +.category-rail { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 14px; scrollbar-width: thin; } +.category-pill { + flex: 0 0 auto; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); + padding: 9px 13px; color: var(--muted); cursor: pointer; font-size: 12px; +} +.category-pill span { margin-left: 5px; font-family: var(--mono); font-size: 10px; } +.category-pill.active, .category-pill:hover { border-color: var(--ink); background: var(--ink); color: var(--paper); } +.capability-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 20px; } +.capability-card { + min-height: 260px; display: flex; flex-direction: column; padding: 22px; border: 1px solid var(--line); + border-radius: 14px; background: var(--panel-translucent); text-decoration: none; + transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease; +} +.capability-card:hover { transform: translateY(-3px); border-color: var(--ink); box-shadow: 4px 4px 0 var(--shadow); } +.card-topline { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 10px; letter-spacing: 0.04em; } +.kind-badge { display: inline-flex; align-items: center; width: fit-content; border-radius: 5px; padding: 5px 7px; background: var(--accent-soft); color: var(--accent-ink); font: 700 10px/1 var(--mono); } +.kind-setting .kind-badge { background: var(--setting-soft); color: var(--setting-ink); } +.category-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.capability-card strong { margin-top: 28px; font-size: 21px; line-height: 1.3; letter-spacing: -0.03em; } +.secondary-title { margin-top: 5px; color: var(--muted); font-size: 12px; } +.capability-card > p { margin: 18px 0 24px; color: var(--muted); font-size: 13px; line-height: 1.65; } +.matched-item { display: flex; align-items: flex-start; gap: 8px; margin: -8px 0 18px; padding: 10px; border-radius: 8px; background: var(--accent-soft); color: var(--accent-ink); font-size: 11px; line-height: 1.45; } +.matched-item i { flex: 0 0 auto; font: 700 9px/1.5 var(--mono); font-style: normal; letter-spacing: 0.05em; text-transform: uppercase; } +.card-link { margin-top: auto; padding-top: 15px; border-top: 1px solid var(--line); font-size: 12px; font-weight: 700; } +.card-link span { float: right; color: var(--accent); } +.empty-state { grid-column: 1 / -1; text-align: center; padding: 80px 20px; border: 1px dashed var(--line); border-radius: 14px; } +.empty-state > span { font-size: 50px; color: var(--accent); } +.empty-state h3 { margin: 14px 0 6px; } +.empty-state p, .result-note { color: var(--muted); } +.result-note { text-align: center; margin-top: 26px; font-size: 12px; } + +.breadcrumb { display: flex; gap: 10px; padding-top: 40px; color: var(--muted); font-size: 12px; } +.breadcrumb a { text-decoration: none; border-bottom: 1px solid var(--line); } +.detail-layout { display: grid; grid-template-columns: minmax(0, 760px) minmax(260px, 1fr); gap: 96px; padding: 80px 0 100px; } +.detail-category { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 12px; } +.detail-main > h1 { margin: 20px 0 4px; font-size: clamp(44px, 6vw, 78px); line-height: 0.98; letter-spacing: -0.065em; } +.detail-alt-title { margin: 0; color: var(--accent); font-family: Georgia, serif; font-size: 28px; } +.detail-summary { margin: 32px 0; max-width: 700px; color: var(--muted); font-size: 18px; line-height: 1.75; } +.entry-callout { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 34px; padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); } +.entry-callout span { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; } +.entry-callout strong { font-size: 13px; text-align: right; } +.content-section { padding-top: 64px; margin-top: 64px; border-top: 1px solid var(--line); } +.content-section .section-label { margin-bottom: 10px; } +.content-section h2, .detail-aside h2 { margin: 0 0 24px; font-size: 28px; letter-spacing: -0.04em; } +.highlight-list { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0; list-style: none; } +.highlight-list li { display: flex; align-items: start; gap: 12px; min-height: 82px; padding: 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); font-size: 14px; line-height: 1.55; scroll-margin-top: 32px; } +.highlight-list li span { color: var(--accent); font-weight: 800; } +.inventory-list li > div { display: grid; gap: 7px; } +.inventory-list li small { color: var(--muted); font-family: Georgia, serif; font-size: 12px; line-height: 1.45; } +.inventory-list li.focused { border-color: var(--accent); background: var(--focused-bg); box-shadow: 4px 4px 0 var(--accent); animation: focus-pulse 1.4s ease-out 1; } +@keyframes focus-pulse { 0% { transform: scale(0.985); } 45% { transform: scale(1.012); } 100% { transform: scale(1); } } +.step-list { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; } +.step-list li { display: grid; grid-template-columns: 42px 1fr; align-items: center; gap: 14px; padding: 18px 0; border-bottom: 1px solid var(--line); } +.step-list li > span { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; background: var(--ink); color: var(--paper); font: 600 12px/1 var(--mono); } +.step-list p { margin: 0; font-size: 15px; line-height: 1.6; } +.manual-empty { padding: 22px; border: 1px dashed var(--line); border-radius: 12px; color: var(--muted); font-size: 14px; line-height: 1.65; } +.operation-list { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } +.operation-list article { padding: 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); } +.operation-list code, .option-table code { color: var(--accent); font-size: 10px; } +.operation-list h3, .option-table h3 { margin: 15px 0 7px; font-size: 15px; } +.operation-list p, .option-table p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.6; } +.option-table { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; } +.option-table article { display: grid; grid-template-columns: minmax(150px, 0.8fr) minmax(220px, 1.4fr) 130px; align-items: center; gap: 20px; padding: 18px; background: var(--panel); } +.option-table article + article { border-top: 1px solid var(--line); } +.option-table h3 { margin: 0 0 7px; } +.option-table article > span { justify-self: end; padding: 6px 8px; border-radius: 6px; background: var(--paper); color: var(--muted); font: 500 10px/1.3 var(--mono); text-align: right; } +.prompt-list { display: grid; gap: 9px; } +.prompt-list button { display: flex; align-items: center; justify-content: space-between; gap: 18px; width: 100%; padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); color: var(--ink); cursor: pointer; text-align: left; } +.prompt-list button:hover { border-color: var(--ink); box-shadow: 3px 3px 0 var(--shadow); } +.prompt-list span { font-size: 14px; line-height: 1.5; } +.prompt-list small { color: var(--muted); font: 600 10px/1 var(--mono); text-transform: uppercase; } +.detail-aside { position: sticky; top: 40px; align-self: start; padding: 28px; border: 1px solid var(--agent-panel-border); border-radius: 16px; background: var(--agent-panel); color: var(--agent-panel-ink); box-shadow: 7px 7px 0 var(--shadow); transform: rotate(1deg); } +.detail-aside ol { padding-left: 20px; font-size: 13px; line-height: 1.7; } +.detail-aside li + li { margin-top: 10px; } +.manual-aside .section-label { color: var(--agent-panel-muted); } +.manual-aside > p:not(.section-label) { color: var(--agent-panel-ink); font-size: 14px; line-height: 1.65; } +.manual-aside .copy-button { width: 100%; margin-top: 18px; border-color: var(--agent-panel-ink); color: var(--agent-panel-ink); } +.manual-aside .copy-button:hover { background: var(--agent-panel-ink); color: var(--agent-panel); } +.back-link { display: block; margin-top: 18px; color: var(--agent-panel-ink); font-size: 12px; text-align: center; } +.site-footer { min-height: 100px; display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--line); color: var(--muted); font-size: 11px; } +.site-footer code { font-size: 10px; } +.loading-shell, .fatal-error { min-height: 100vh; display: grid; place-content: center; justify-items: center; gap: 16px; } +.loading-mark { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 14px; background: var(--ink); color: var(--paper); font-size: 26px; font-weight: 700; } + +@media (max-width: 1180px) { + .docs-shell { grid-template-columns: 230px minmax(0, 1fr); gap: 28px; } + .docs-content { padding-left: 28px; } + .detail-layout { grid-template-columns: minmax(0, 1fr) 270px; gap: 46px; } + .hero-actions { grid-template-columns: 1fr; } + .search-box { max-width: 800px; } + .hero-stat { justify-self: start; } +} + +@media (max-width: 980px) { + .site-header, .docs-shell { width: min(100% - 32px, 1240px); } + .docs-shell { display: block; } + .docs-content { padding-left: 0; border-left: 0; } + .sidebar-toggle { display: inline-flex; } + .docs-sidebar { + position: fixed; inset: 0 auto 0 0; z-index: 80; width: min(340px, calc(100vw - 44px)); height: 100dvh; min-height: 0; + padding: 18px 14px 24px 18px; border-right: 1px solid var(--ink); background: var(--paper); + box-shadow: 12px 0 0 var(--drawer-shadow); transform: translateX(calc(-100% - 18px)); + transition: transform 180ms cubic-bezier(0.23, 1, 0.32, 1); + } + .sidebar-mobile-head { display: flex; } + .sidebar-backdrop { position: fixed; inset: 0; z-index: 70; width: 100%; height: 100%; border: 0; background: var(--backdrop); opacity: 0; pointer-events: none; transition: opacity 180ms ease; } + body.sidebar-open { overflow: hidden; } + body.sidebar-open .docs-sidebar { transform: translateX(0); } + body.sidebar-open .sidebar-backdrop { display: block; opacity: 1; pointer-events: auto; } + .capability-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .hero-stat { margin-top: 6px; } + .detail-layout { grid-template-columns: 1fr; gap: 54px; } + .detail-aside { position: static; max-width: 520px; } + .option-table article { grid-template-columns: 1fr; gap: 10px; } + .option-table article > span { justify-self: start; text-align: left; } +} + +@media (max-width: 600px) { + .site-header, .docs-shell { width: min(100% - 28px, 1240px); } + .site-header { height: 72px; } + .header-actions { gap: 8px; } + .header-link { display: none; } + .theme-control button { width: 29px; min-height: 29px; justify-content: center; padding: 4px; } + .theme-control button > span:last-child { display: none; } + .hero { padding: 58px 0; } + .hero h1 { gap: 8px; font-size: clamp(44px, 15vw, 64px); line-height: 0.98; } + .hero h1 em { line-height: 1.06; } + .hero-copy { font-size: 15px; } + .hero-stat { flex-wrap: wrap; gap: 7px 9px; } + .hero-stat i { display: none; } + .search-box { height: 60px; padding-inline: 15px; box-shadow: 4px 4px 0 var(--shadow); } + .search-box kbd { display: none; } + .catalog-toolbar { align-items: start; flex-direction: column; } + .kind-switch { display: flex; width: 100%; } + .kind-switch button { flex: 1; padding-inline: 8px; } + .capability-grid { grid-template-columns: 1fr; } + .capability-card { min-height: 230px; } + .detail-layout { padding-top: 52px; } + .detail-main > h1 { font-size: 46px; } + .entry-callout { align-items: start; flex-direction: column; } + .entry-callout strong { text-align: left; } + .highlight-list, .operation-list { grid-template-columns: 1fr; } + .site-footer { align-items: start; flex-direction: column; justify-content: center; gap: 8px; } +} + +@media (max-width: 420px) { + .brand > span:last-child { display: none; } + .language-toggle, .sidebar-toggle { padding-inline: 10px; } +} + +@media (prefers-reduced-motion: reduce) { + * { scroll-behavior: auto !important; transition: none !important; } +}