diff --git a/.agents/notes/implemented/feature/2026-10-09-forge-panel.i18n.yaml b/.agents/notes/implemented/feature/2026-10-09-forge-panel.i18n.yaml
index 53d2b74f3a..f779b7be73 100644
--- a/.agents/notes/implemented/feature/2026-10-09-forge-panel.i18n.yaml
+++ b/.agents/notes/implemented/feature/2026-10-09-forge-panel.i18n.yaml
@@ -9,8 +9,8 @@
en: 344bcc7e9825bbc8
zh: c1d0f4b54f5b3786
/agent-note-change-request-panel-and-worktree-sessions/decision:
- en: 6a0dc836205863ba
- zh: 3d4feb0385953dda
+ en: 66bde24e7c601eb6
+ zh: 5091591f3dc1ac85
/agent-note-change-request-panel-and-worktree-sessions/deferred:
en: 32ef8af85f4d2f66
zh: b82b67f94346399e
@@ -18,5 +18,5 @@
en: e471e16b6b6450ca
zh: 5fbc9242edc8d112
/agent-note-change-request-panel-and-worktree-sessions/consequences:
- en: 81790c448f0a7d3b
- zh: ec63ccb2ad315ff8
+ en: 0b785a2204963c4f
+ zh: be4bd8db40b801a1
diff --git a/.agents/notes/implemented/feature/2026-10-09-forge-panel.md b/.agents/notes/implemented/feature/2026-10-09-forge-panel.md
index 1285ba6cdf..2b852ad824 100644
--- a/.agents/notes/implemented/feature/2026-10-09-forge-panel.md
+++ b/.agents/notes/implemented/feature/2026-10-09-forge-panel.md
@@ -10,7 +10,9 @@ English | [中文](2026-10-09-forge-panel.zh.md)
## Decision
-[`dsh-experimental-client-ui-forge`](../../../../packages/experimental/client-ui-forge/README.md) is a two-face package. Its Host half, the `forgePanel` Remote, assembles everything the panel shows for one Session into one streamed state; the forge registry and the binding service keep only their domain operations. Its Client half is a right-sidebar tab, a Session header button that shows or hides it, a New Session option, a creation card above the composer, a toast, and the [Session list icons and hover card section](2026-10-20-forge-session-list.md). Every surface calls a bound item a change request, the forge registry's term, whatever its code host calls it. The [forge bundle](../../../../packages/experimental/forge-bundle/README.md) ships the panel, the forge registry, the GitHub provider, the bindings, and an isolated worktree service as one default-disabled Plugins page entry.
+[`dsh-experimental-client-ui-forge`](../../../../packages/experimental/client-ui-forge/README.md) is a two-face package. Its Host half, the `forgePanel` Remote, assembles everything the panel shows for one Session into one streamed state; the forge registry and the binding service keep only their domain operations. Its Client half is a right-sidebar tab, a Session header button that shows or hides it, a New Session option, a creation card above the composer, a toast, and the [Session list icons and hover card section](2026-10-20-forge-session-list.md). Every surface calls a bound item a change request, the forge registry's term, whatever its code host calls it. The [forge bundle](../../../../packages/experimental/forge-bundle/README.md) ships the panel, the forge registry, the GitHub provider, the bindings, the worktree model tool, and an isolated worktree service for the panel as one default-disabled Plugins page entry.
+
+Review and worktree controls serve one code-change workflow. One Plugins entry lets users enable that workflow without having to distinguish the underlying package split. Packages and the two worktree services remain independent so each owns its before-Session or in-conversation creation flow.
The Remote inspects the checkout through the Session's subprocess provider under its [resolved permissions and query restrictions](../bug-fix/2026-10-28-forge-git-session-permissions.md), so it reads what the Session's commands see. Inspection reads the top-level, Git, and common Git directories, the branch or the abbreviated HEAD commit, the upstream, the remotes, and the size of the branch's changes against its fork point. It runs when a Session is followed, after each `working-directory/change`, `tool/result`, and `sandbox/mode` event, and on refresh, one at a time with one trailing rerun.
@@ -89,4 +91,4 @@ The changes view offers no scope for one commit or for the last turn yet; both w
## Consequences
-The panel shows current status only while it is open; checks that finish while nothing is mounted produce no notification. Changes made outside the Session appear after Refresh or the next tool result. Every inspection spawns up to twelve short Git processes in the Session's execution world with one remote, and two more for each further remote it tries for a fork point. A worktree exists only for a Session that requested it before its first step, and a failed or cancelled attempt can leave its branch or checkout behind. A message that enters while the Agent runs a turn or other maintenance gets no hold, so its worktree is created within the first turn and a removed worktree is not checked. While a message waits, the Agent stays idle in maintenance: the composer offers no stop, and callers waiting for the Agent to become idle wait as well. Restoring loses changes that were never committed. A base branch that requires a merge queue cannot merge from the panel. With Git Worktrees also enabled, two independent worktree services exist; the model's tool never sees the panel's service. A local or change request diff over `maxDiffBytes`, or one the host refuses, shows no files. Expanding unchanged lines of a change request reads each file from the code host once.
+The panel shows current status only while it is open; checks that finish while nothing is mounted produce no notification. Changes made outside the Session appear after Refresh or the next tool result. Every inspection spawns up to twelve short Git processes in the Session's execution world with one remote, and two more for each further remote it tries for a fork point. A worktree exists only for a Session that requested it before its first step, and a failed or cancelled attempt can leave its branch or checkout behind. A message that enters while the Agent runs a turn or other maintenance gets no hold, so its worktree is created within the first turn and a removed worktree is not checked. While a message waits, the Agent stays idle in maintenance: the composer offers no stop, and callers waiting for the Agent to become idle wait as well. Restoring loses changes that were never committed. A base branch that requires a merge queue cannot merge from the panel. The bundle mounts two independent worktree services; the model's tool never sees the panel's service. A local or change request diff over `maxDiffBytes`, or one the host refuses, shows no files. Expanding unchanged lines of a change request reads each file from the code host once.
diff --git a/.agents/notes/implemented/feature/2026-10-09-forge-panel.zh.md b/.agents/notes/implemented/feature/2026-10-09-forge-panel.zh.md
index 432f2b10a8..660bd81d38 100644
--- a/.agents/notes/implemented/feature/2026-10-09-forge-panel.zh.md
+++ b/.agents/notes/implemented/feature/2026-10-09-forge-panel.zh.md
@@ -10,7 +10,9 @@ Status: implemented
## Decision
-[`dsh-experimental-client-ui-forge`](../../../../packages/experimental/client-ui-forge/README.zh.md) 是一个双端包。宿主端的 `forgePanel` Remote 把面板为一个 Session 展示的全部内容组装成一条流式状态;forge 注册表与绑定服务只保留各自的领域操作。客户端包括一个右侧边栏标签页、一个显示或隐藏它的 Session 标题栏按钮、一个新会话选项、一张位于输入框上方的创建卡片、一个 toast,以及[会话列表中的图标与悬浮卡片部分](2026-10-20-forge-session-list.zh.md)。所有界面都把已绑定的条目称为变更请求(forge 注册表的术语),不随代码托管平台的叫法变化。[forge 套件](../../../../packages/experimental/forge-bundle/README.zh.md)把面板、forge 注册表、GitHub 提供方、绑定服务与一个隔离的 worktree 服务作为插件页中默认禁用的一个条目发布。
+[`dsh-experimental-client-ui-forge`](../../../../packages/experimental/client-ui-forge/README.zh.md) 是一个双端包。宿主端的 `forgePanel` Remote 把面板为一个 Session 展示的全部内容组装成一条流式状态;forge 注册表与绑定服务只保留各自的领域操作。客户端包括一个右侧边栏标签页、一个显示或隐藏它的 Session 标题栏按钮、一个新会话选项、一张位于输入框上方的创建卡片、一个 toast,以及[会话列表中的图标与悬浮卡片部分](2026-10-20-forge-session-list.zh.md)。所有界面都把已绑定的条目称为变更请求(forge 注册表的术语),不随代码托管平台的叫法变化。[forge 套件](../../../../packages/experimental/forge-bundle/README.zh.md)把面板、forge 注册表、GitHub 提供方、绑定服务、工作树模型工具与面板使用的一个隔离 worktree 服务作为插件页中默认禁用的一个条目发布。
+
+评审与工作树控件服务于同一个代码修改流程。统一插件入口让用户可以一次启用这些能力,无需根据底层包的拆分判断应该开启哪张卡片。包与两套工作树服务仍保持独立,分别负责会话开始前和对话中创建工作树的流程。
Remote 通过 Session 的子进程提供方,按其[解析出的权限与查询限制](../bug-fix/2026-10-28-forge-git-session-permissions.zh.md)检查检出,因此它读到的与 Session 命令看到的相同。检查读取顶层目录、Git 目录与公共 Git 目录、分支或缩写的 HEAD 提交、上游与远端,以及分支相对于其分叉点的变更规模。它在 Session 被关注时、每个 `working-directory/change`、`tool/result` 与 `sandbox/mode` 事件之后以及刷新时运行,一次只运行一个,最多再追加一次。
@@ -89,4 +91,4 @@ Session 所在的 worktree 可能在 Session 之外被删除。每次检查都
## Consequences
-面板只在打开时显示当前状态;没有任何界面挂载时检查结束不会有通知。Session 之外的改动要等到刷新或下一个工具结果才会出现。只有一个远端时,每次检查最多在 Session 的执行环境中启动十二个短暂的 Git 进程;为寻找分叉点每多尝试一个远端,就多启动两个。只有在第一步之前提出请求的 Session 才会有 worktree,失败或被取消的尝试可能留下它的分支或检出。Agent 正在运行一轮或其他维护任务时进入的消息不会被暂留,因此它的 worktree 在第一轮之内创建,已删除的 worktree 也不会被检查。消息等待期间,Agent 以空闲状态处于维护任务中:输入框不提供停止,等待 Agent 空闲的调用方也会一并等待。恢复会丢失从未提交的修改。要求合并队列的基准分支无法从面板合并。同时启用 Git Worktrees 时会存在两个互不影响的 worktree 服务;模型的工具看不到面板的服务。本地或变更请求的 diff 超过 `maxDiffBytes`,或被托管平台拒绝时,不显示任何文件。展开变更请求中未变更的行时,每个文件只从托管平台读取一次。
+面板只在打开时显示当前状态;没有任何界面挂载时检查结束不会有通知。Session 之外的改动要等到刷新或下一个工具结果才会出现。只有一个远端时,每次检查最多在 Session 的执行环境中启动十二个短暂的 Git 进程;为寻找分叉点每多尝试一个远端,就多启动两个。只有在第一步之前提出请求的 Session 才会有 worktree,失败或被取消的尝试可能留下它的分支或检出。Agent 正在运行一轮或其他维护任务时进入的消息不会被暂留,因此它的 worktree 在第一轮之内创建,已删除的 worktree 也不会被检查。消息等待期间,Agent 以空闲状态处于维护任务中:输入框不提供停止,等待 Agent 空闲的调用方也会一并等待。恢复会丢失从未提交的修改。要求合并队列的基准分支无法从面板合并。组合包挂载两个互不影响的 worktree 服务;模型的工具看不到面板的服务。本地或变更请求的 diff 超过 `maxDiffBytes`,或被托管平台拒绝时,不显示任何文件。展开变更请求中未变更的行时,每个文件只从托管平台读取一次。
diff --git a/apps/web/tests/additional-locales.e2e.ts b/apps/web/tests/additional-locales.e2e.ts
index 007aab3e14..2cd04ce30a 100644
--- a/apps/web/tests/additional-locales.e2e.ts
+++ b/apps/web/tests/additional-locales.e2e.ts
@@ -59,3 +59,37 @@ it.each(languages)('selects %s from the browser, localizes metadata and persists
expect(tripwire.warnings).toEqual([])
expect(tripwire.pageErrors).toEqual([])
})
+
+const forgePreviews = [
+ ['de', 'de-DE', 'Plugins', 'Eine Unterhaltung mit verknüpftem GitHub-Pull-Request, Prüfungen, Reviews, Codeunterschieden und einem separaten Arbeitsbaum'],
+ ['es', 'es-MX', 'Complementos', 'Una conversación vinculada a un pull request de GitHub, con comprobaciones, revisiones, diferencias de código y un árbol de trabajo aislado'],
+ ['fr', 'fr-CA', 'Plugins', 'Une conversation liée à une pull request GitHub, avec vérifications, revues, différences de code et un arbre de travail isolé'],
+ ['ja', 'ja-JP', 'プラグイン', 'GitHub のプルリクエストに関連付けられた会話、チェックとレビューの状況、コードの差分、独立したワークツリー'],
+ ['pt', 'pt-BR', 'Plug-ins', 'Uma conversa vinculada a um pull request do GitHub, com verificações, revisões, diferenças de código e uma árvore de trabalho isolada'],
+ ['ru', 'ru-RU', 'Плагины', 'Беседа, связанная с pull request GitHub: проверки, рецензии, различия в коде и отдельное рабочее дерево'],
+] as const
+
+it.each(forgePreviews)('reads the Forge preview in %s before activation', async (id, tag, plugins, alt) => {
+ const resources: { scaffold?: WebScaffold; browser?: Browser } = {}
+ onTestFinished(async () => {
+ try { await resources.browser?.close() } finally { await resources.scaffold?.close() }
+ })
+ const scaffold = await launchWebScaffold()
+ resources.scaffold = scaffold
+ const browser = await chromium.launch()
+ resources.browser = browser
+ const page = await browser.newPage({ locale: tag, viewport: { width: 1440, height: 960 } })
+ const tripwire = watchConsole(page)
+ onTestFailed(() => saveFailureShot(page, `forge-preview-${id}`))
+ await page.goto(scaffold.authenticatedUrl)
+ await expect.poll(() => page.locator('html').getAttribute('lang')).toBe(id)
+ await page.getByRole('button', { name: plugins, exact: true }).click()
+ const card = page.locator('[data-plugin-package="@deepseek-ai/dsh-experimental-forge-bundle"]')
+ expect(await card.getByRole('switch').getAttribute('aria-checked')).toBe('false')
+ await card.getByRole('button').click()
+ const image = page.locator('[data-detail-document]').getByRole('img', { name: alt, exact: true })
+ await image.waitFor()
+ await image.evaluate(async (node: HTMLImageElement) => { await node.decode() })
+ expect(await image.evaluate((node: HTMLImageElement) => [node.naturalWidth, node.naturalHeight])).toEqual([640, 300])
+ expect(tripwire.pageErrors).toEqual([])
+})
diff --git a/apps/web/tests/expected/plugin-config/official.expected.md b/apps/web/tests/expected/plugin-config/official.expected.md
index 1060826d8a..70fbddd1f1 100644
--- a/apps/web/tests/expected/plugin-config/official.expected.md
+++ b/apps/web/tests/expected/plugin-config/official.expected.md
@@ -44,7 +44,7 @@
- switch "启用 自动授权审查"
- listitem:
- button "查看 变更请求与工作树": 变更请求与工作树
- - text: 实验性 跟踪每个会话的变更请求及其检查与评审,新会话也可以在 Git 工作树中开始;GitHub 通过 gh 命令行访问。
+ - text: 实验性 在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。
- status
- switch "启用 变更请求与工作树"
- heading "已安装插件" [level=3]
diff --git a/apps/web/tests/expected/plugin-manager/forge-preview.expected.md b/apps/web/tests/expected/plugin-manager/forge-preview.expected.md
new file mode 100644
index 0000000000..afcab828fc
--- /dev/null
+++ b/apps/web/tests/expected/plugin-manager/forge-preview.expected.md
@@ -0,0 +1,54 @@
+- button "返回插件": 插件
+- status
+- switch "启用 变更请求与工作树"
+- heading "变更请求与工作树" [level=3]
+- text: v{{version}} 实验性
+- paragraph:
+ - code: "@deepseek-ai/dsh-experimental-forge-bundle"
+- paragraph: 在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。
+- region "详细介绍":
+ - paragraph:
+ - img "会话关联 GitHub PR,跟踪检查、评审与代码差异,并用工作树隔离任务改动"
+- heading "包含的组件" [level=4]
+- text: 共 7 个 · 7 已停用
+- list:
+ - listitem:
+ - text: 工作树服务 创建命名的 Git 工作树,并切换当前会话的工作目录。
+ - code: worktree
+ - code: "@deepseek-ai/dsh-experimental-worktree"
+ - text: 已关闭
+ - listitem:
+ - text: Git 工作树 要求在新分支上工作时,智能体会创建单独的 Git 工作树并在其中继续,你当前的工作树保持原样。
+ - code: tool-worktree
+ - code: "@deepseek-ai/dsh-experimental-tool-worktree"
+ - text: 已关闭
+ - listitem:
+ - text: 变更请求 通过一个与提供方无关的服务注册代码托管提供方,并轮询变更请求状态。
+ - code: forge
+ - code: "@deepseek-ai/dsh-experimental-forge"
+ - text: 已关闭
+ - listitem:
+ - text: GitHub 变更请求 通过宿主上的 GitHub CLI 为 forge 注册表读取 GitHub 变更请求。
+ - code: forge-github
+ - code: "@deepseek-ai/dsh-experimental-forge-github"
+ - text: 已关闭
+ - listitem:
+ - text: 会话变更请求 把变更请求绑定到创建、推送或跟踪它们的会话,并监听其状态。
+ - code: forge-session
+ - code: "@deepseek-ai/dsh-experimental-forge-session"
+ - text: 已关闭
+ - listitem:
+ - text: 工作树服务 创建命名的 Git 工作树,并切换当前会话的工作目录。
+ - code: forge-worktree
+ - code: "@deepseek-ai/dsh-experimental-worktree"
+ - text: 已关闭
+ - listitem:
+ - text: 变更请求面板 在侧栏标签页中显示会话的变更请求,并让新会话可以在工作树中开始。
+ - code: forge-panel
+ - code: "@deepseek-ai/dsh-experimental-client-ui-forge"
+ - text: 已关闭
+- heading "来源信息" [level=4]
+- term: 代码来源
+- definition: 内置
+- term: 当前版本
+- definition: {{version}}
diff --git a/apps/web/tests/expected/plugin-manager/live-enabled.expected.md b/apps/web/tests/expected/plugin-manager/live-enabled.expected.md
index 561ee7ae23..5f30f09e75 100644
--- a/apps/web/tests/expected/plugin-manager/live-enabled.expected.md
+++ b/apps/web/tests/expected/plugin-manager/live-enabled.expected.md
@@ -44,7 +44,7 @@
- switch "启用 自动授权审查"
- listitem:
- button "查看 变更请求与工作树": 变更请求与工作树
- - text: 实验性 跟踪每个会话的变更请求及其检查与评审,新会话也可以在 Git 工作树中开始;GitHub 通过 gh 命令行访问。
+ - text: 实验性 在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。
- status
- switch "启用 变更请求与工作树"
- heading "已安装插件" [level=3]
diff --git a/apps/web/tests/expected/plugin-manager/manager.expected.md b/apps/web/tests/expected/plugin-manager/manager.expected.md
index 88dd772e51..69c0998762 100644
--- a/apps/web/tests/expected/plugin-manager/manager.expected.md
+++ b/apps/web/tests/expected/plugin-manager/manager.expected.md
@@ -44,7 +44,7 @@
- switch "启用 自动授权审查"
- listitem:
- button "查看 变更请求与工作树": 变更请求与工作树
- - text: 实验性 跟踪每个会话的变更请求及其检查与评审,新会话也可以在 Git 工作树中开始;GitHub 通过 gh 命令行访问。
+ - text: 实验性 在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。
- status
- switch "启用 变更请求与工作树"
- heading "已安装插件" [level=3]
diff --git a/apps/web/tests/forge-panel.e2e.ts b/apps/web/tests/forge-panel.e2e.ts
index 76da6c115e..2c5487b1d1 100644
--- a/apps/web/tests/forge-panel.e2e.ts
+++ b/apps/web/tests/forge-panel.e2e.ts
@@ -447,6 +447,8 @@ it.skipIf(MODE === 'record')('automatically shows a numbered PR when gh JSON omi
const { settled } = await sendPrompt(page, scaffold)
const sessionId = await settled
const events = await readPersistedEvents(scaffold, sessionId)
+ const request = events.find(event => event.type === 'request/header')
+ expect(request?.data.header.tools?.filter(tool => tool.name === 'create_worktree')).toHaveLength(1)
const toolOutput = events.flatMap(event => event.type === 'tool/result'
? event.data.message.content.flatMap(block => block.type === 'text' ? [block.text] : []) : []).join('\n')
expect(toolOutput).toContain('Add the pull request panel')
diff --git a/apps/web/tests/plugin-config.e2e.ts b/apps/web/tests/plugin-config.e2e.ts
index 8bba474e11..7152ad1ef8 100644
--- a/apps/web/tests/plugin-config.e2e.ts
+++ b/apps/web/tests/plugin-config.e2e.ts
@@ -9,6 +9,7 @@ import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import type { Browser, Locator, Page } from 'playwright'
import { chromium } from 'playwright'
+import { HIDDEN_BUNDLES } from '@deepseek-ai/dsh-official-bundles'
import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest'
import { join } from 'node:path'
import {
@@ -115,17 +116,14 @@ describe('web e2e: plugin configuration pages', () => {
// The More list omits the shipped bundles whose own rows do not run (the visibility rule lives in
// ui-plugin-manager), so it holds fewer cards than the installed optional-bundle list.
const bundles = await scaffold.ctx.pluginManager.listBundles()
- const hiddenBundles = new Set([
- '@deepseek-ai/dsh-experimental-terminal-bundle',
- '@deepseek-ai/dsh-experimental-liveshare',
- ])
expect(await panel.locator('[data-plugin-group="more"] [data-plugin-package]').count())
- .toBe(bundles.filter(bundle => !hiddenBundles.has(bundle.name)
+ .toBe(bundles.filter(bundle => !HIDDEN_BUNDLES.has(bundle.name)
+ && bundle.name !== '@deepseek-ai/dsh-experimental-liveshare'
&& bundle.official && (bundle.listedByDefault !== false || bundle.enabled || bundle.installed)).length)
expect(await basic.count()).toBe(0)
expect(await extensions.count()).toBe(0)
expect(await panel.locator('[data-plugin-group="bundles"]').count()).toBe(0)
- await panel.getByRole('button', { name: '查看 Git 工作树', exact: true }).click()
+ await panel.getByRole('button', { name: '查看 开发者工具', exact: true }).click()
await panel.locator('[data-plugin-detail]').waitFor()
await panel.getByRole('button', { name: '返回 实验性插件', exact: true }).click()
await panel.getByRole('heading', { name: '实验性插件', exact: true, level: 1 }).waitFor()
diff --git a/apps/web/tests/plugin-manager.e2e.ts b/apps/web/tests/plugin-manager.e2e.ts
index 93db3c1179..527a1bcc73 100644
--- a/apps/web/tests/plugin-manager.e2e.ts
+++ b/apps/web/tests/plugin-manager.e2e.ts
@@ -10,6 +10,7 @@ import { chromium } from 'playwright'
import { FiberState } from '@deepseek-ai/cordis'
import { readProfileManifest } from '@deepseek-ai/dsh-app-boot'
import { createUserMessage } from '@deepseek-ai/dsh-llm'
+import { HIDDEN_BUNDLES } from '@deepseek-ai/dsh-official-bundles'
import { afterAll, beforeAll, describe, expect, it, onTestFailed, onTestFinished, vi } from 'vitest'
import { join } from 'node:path'
import {
@@ -853,7 +854,7 @@ describe('web e2e: plugin manager', () => {
// the eligible installed optional-bundle list.
expect(await panel.locator('[data-plugin-group="more"] [data-plugin-package="@deepseek-ai/dsh-experimental-liveshare"]').count()).toBe(0)
expect(await panel.locator('[data-plugin-group="more"] [data-plugin-package]').count())
- .toBe(bundles.filter(bundle => bundle.name !== '@deepseek-ai/dsh-experimental-terminal-bundle'
+ .toBe(bundles.filter(bundle => !HIDDEN_BUNDLES.has(bundle.name)
&& bundle.name !== '@deepseek-ai/dsh-experimental-liveshare'
&& bundle.official && (bundle.listedByDefault !== false || bundle.enabled || bundle.installed)).length)
expect(bundles.find(bundle => bundle.name === '@deepseek-ai/dsh-cua-bundle'))
@@ -876,7 +877,6 @@ describe('web e2e: plugin manager', () => {
['@deepseek-ai/dsh-experimental-forge-bundle', 1],
['@deepseek-ai/dsh-personalized-recommendations', 1],
['@deepseek-ai/dsh-experimental-inspector-profile', 1],
- ['@deepseek-ai/dsh-experimental-tool-worktree', 1],
['@deepseek-ai/dsh-experimental-cot-translation-bundle', 1],
['@deepseek-ai/dsh-experimental-session-titles-bundle', 1],
['@deepseek-ai/dsh-experimental-badge-skill-bundle', 1],
@@ -1063,6 +1063,51 @@ describe('web e2e: plugin manager', () => {
expect(tripwire.pageErrors).toEqual([])
})
+ it('introduces code review and worktrees with localized artwork before activation', async () => {
+ onTestFailed(() => saveFailureShot(page, 'web-e2e-forge-preview'))
+ const panel = await openPluginsPanel()
+ await panel.getByRole('button', { name: '查看 变更请求与工作树', exact: true }).click()
+ const detail = panel.locator('[data-plugin-detail]')
+ expect(await detail.getByRole('switch').getAttribute('aria-checked')).toBe('false')
+ const sources: (string | null)[] = []
+ let english = false
+ try {
+ for (const [language, alt] of [
+ ['zh', '会话关联 GitHub PR,跟踪检查、评审与代码差异,并用工作树隔离任务改动'],
+ ['en', 'A conversation linked to a GitHub pull request, with checks, reviews, code diffs, and an isolated worktree'],
+ ] as const) {
+ if (language === 'en') {
+ await setLanguage(language)
+ english = true
+ }
+ const document = detail.locator('[data-detail-document]')
+ const image = document.getByRole('img', { name: alt, exact: true })
+ await image.waitFor()
+ await image.evaluate(async (node: HTMLImageElement) => { await node.decode() })
+ expect(await image.evaluate((node: HTMLImageElement) => [node.naturalWidth, node.naturalHeight])).toEqual([640, 300])
+ sources.push(await image.getAttribute('src'))
+ for (const width of [1680, 390]) {
+ await page.setViewportSize({ width, height: 1000 })
+ expect(await image.evaluate((node: HTMLImageElement) => {
+ const bounds = node.getBoundingClientRect()
+ return bounds.width > 0 && bounds.left >= 0 && bounds.right <= window.innerWidth
+ && window.document.documentElement.scrollWidth <= window.innerWidth
+ })).toBe(true)
+ }
+ await page.setViewportSize({ width: 1680, height: 1000 })
+ }
+ expect(sources[0]).not.toBe(sources[1])
+ } finally {
+ await page.setViewportSize({ width: 1680, height: 1000 })
+ if (english) await setLanguage('zh')
+ }
+ await compareOrRefreshGolden(join(SNAPSHOT_DIR, 'forge-preview.expected.md'),
+ await captureStableAria(page, '[data-plugin-panel]', scaffold.workspaceCwd, {
+ replacements: [[badgeVersion, '{{version}}']],
+ }), MODE)
+ expect(tripwire.pageErrors).toEqual([])
+ })
+
it('localizes independent exports and falls back per field without activating the plugins', async () => {
onTestFinished(closeSettings)
onTestFailed(() => saveFailureShot(page, 'web-e2e-plugin-manager-exports'))
@@ -1531,7 +1576,7 @@ describe('web e2e: plugin manager', () => {
await assertFixtureInventory(SNAPSHOT_DIR, [
'manager.expected.md', 'live-enabled.expected.md', 'missing-bundle.expected.md', 'exports.expected.md', 'exports-en.expected.md', 'icons.expected.md', 'loading.expected.md', 'refresh.expected.md',
'ime-enter.expected.md', 'header-responsive.expected.md', 'header-natural-motion.expected.md', 'preview.expected.md',
- 'touch-tooltips.expected.md',
+ 'touch-tooltips.expected.md', 'forge-preview.expected.md',
])
})
})
diff --git a/apps/web/tests/worktree-opt-in.e2e.ts b/apps/web/tests/worktree-opt-in.e2e.ts
index 37b94a16ec..341d72c68f 100644
--- a/apps/web/tests/worktree-opt-in.e2e.ts
+++ b/apps/web/tests/worktree-opt-in.e2e.ts
@@ -1,4 +1,4 @@
-/** Git Worktrees opt-in through the shipped plugin manager, profile, and Loader. */
+/** Unified review and worktree opt-in through the shipped plugin manager, profile, and Loader. */
import { execFile } from 'node:child_process'
import { readFile, writeFile } from 'node:fs/promises'
@@ -6,16 +6,19 @@ import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { promisify } from 'node:util'
import { FiberState } from '@deepseek-ai/cordis'
+import { ToolCallId } from '@deepseek-ai/dsh-llm'
import type {} from '@deepseek-ai/dsh-experimental-worktree'
+import type {} from '@deepseek-ai/dsh-experimental-client-ui-forge'
import { chromium } from 'playwright'
import { expect, it, onTestFailed, onTestFinished } from 'vitest'
import { launchWebScaffold, watchConsole } from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, PLUGIN_TOGGLE_SETTLE_MS, saveFailureShot } from './support.ts'
-const BUNDLE = '@deepseek-ai/dsh-experimental-tool-worktree'
+const BUNDLE = '@deepseek-ai/dsh-experimental-forge-bundle'
+const STANDALONE = '@deepseek-ai/dsh-experimental-tool-worktree'
const exec = promisify(execFile)
-it('persists the Git Worktrees switch and removes its capability while retaining checkouts', async () => {
+it('persists the unified review and worktree switch and retains checkouts after disabling', async () => {
const scaffold = await launchWebScaffold({
extraOverlayPath: fileURLToPath(new URL('./pin-browse-picker.overlay.yml', import.meta.url)),
})
@@ -70,13 +73,15 @@ it('persists the Git Worktrees switch and removes its capability while retaining
}
let panel = await openPlugins()
let card = panel.locator(`[data-plugin-group="more"] [data-plugin-package="${BUNDLE}"]`)
- await card.getByRole('button', { name: 'View Git worktrees', exact: true }).waitFor()
+ await card.getByRole('button', { name: 'View Change requests & worktrees', exact: true }).waitFor()
+ expect(await panel.locator(`[data-plugin-package="${STANDALONE}"]`).count()).toBe(0)
expect(await card.getByText('Experimental', { exact: true }).count()).toBe(1)
- let toggle = card.getByRole('switch', { name: 'Enable Git worktrees', exact: true })
+ let toggle = card.getByRole('switch', { name: 'Enable Change requests & worktrees', exact: true })
expect(await toggle.getAttribute('aria-checked')).toBe('false')
expect(await selectedBundles()).not.toContain(BUNDLE)
expect(rows()).toEqual([])
expect(scaffold.ctx.get('worktrees')).toBeUndefined()
+ expect(scaffold.ctx.get('forgePanel')).toBeUndefined()
expect(tools()).toContain('working_directory')
expect(tools()).not.toContain('create_worktree')
@@ -85,14 +90,21 @@ it('persists the Git Worktrees switch and removes its capability while retaining
await expect.poll(() => toggle.getAttribute('aria-checked'), { timeout: PLUGIN_TOGGLE_SETTLE_MS }).toBe('true')
expect(await selectedBundles()).toContain(BUNDLE)
expect(tools()).toContain('create_worktree')
- const created = await scaffold.ctx.worktrees.create(agent, { name: 'gui-opt-in' })
+ expect(scaffold.ctx.get('forgePanel')).toBeDefined()
+ const created = { path: join(repository, '.agents/worktrees/gui-opt-in'), baseCommit: (await git('rev-parse', 'HEAD')).stdout.trim() }
+ const result = await scaffold.ctx.tools.execute({
+ agent, signal: new AbortController().signal,
+ calls: [{ type: 'tool-call', id: ToolCallId('gui-opt-in'), name: 'create_worktree', arguments: JSON.stringify({ name: 'gui-opt-in' }) }],
+ })
+ expect(result.results[0]?.result.isError).not.toBe(true)
+ expect(result.results[0]?.result.value).toEqual({ ...created, branch: 'gui-opt-in', repositoryRoot: repository })
expect(await readFile(join(created.path, 'retained.txt'), 'utf8')).toBe('retained checkout\n')
expect(scaffold.ctx.workingDirectory.get(agent.session)).toBe(created.path)
await page.reload({ waitUntil: 'load' })
panel = await openPlugins()
card = panel.locator(`[data-plugin-group="more"] [data-plugin-package="${BUNDLE}"]`)
- toggle = card.getByRole('switch', { name: 'Enable Git worktrees', exact: true })
+ toggle = card.getByRole('switch', { name: 'Enable Change requests & worktrees', exact: true })
await expect.poll(() => toggle.getAttribute('aria-checked')).toBe('true')
expect(tools()).toContain('create_worktree')
await toggle.click()
@@ -100,6 +112,7 @@ it('persists the Git Worktrees switch and removes its capability while retaining
await expect.poll(() => toggle.getAttribute('aria-checked'), { timeout: PLUGIN_TOGGLE_SETTLE_MS }).toBe('false')
expect(await selectedBundles()).not.toContain(BUNDLE)
expect(scaffold.ctx.get('worktrees')).toBeUndefined()
+ expect(scaffold.ctx.get('forgePanel')).toBeUndefined()
expect(tools()).not.toContain('create_worktree')
expect(tools()).toContain('working_directory')
expect(await readFile(join(created.path, 'retained.txt'), 'utf8')).toBe('retained checkout\n')
@@ -108,7 +121,7 @@ it('persists the Git Worktrees switch and removes its capability while retaining
await page.reload({ waitUntil: 'load' })
panel = await openPlugins()
- await expect.poll(() => panel.getByRole('switch', { name: 'Enable Git worktrees', exact: true })
+ await expect.poll(() => panel.getByRole('switch', { name: 'Enable Change requests & worktrees', exact: true })
.getAttribute('aria-checked')).toBe('false')
expect(tools()).not.toContain('create_worktree')
expect(await selectedBundles()).not.toContain(BUNDLE)
diff --git a/docs/subsystems/forge.i18n.yaml b/docs/subsystems/forge.i18n.yaml
index 92bc2298cd..379e181766 100644
--- a/docs/subsystems/forge.i18n.yaml
+++ b/docs/subsystems/forge.i18n.yaml
@@ -3,8 +3,8 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/forge.md
/forges:
- en: 1b51f9d385dafe76
- zh: 4bb73627aa69d652
+ en: 3ee521b77b4601e2
+ zh: 4170c33e49248f8f
/forges/providers-and-change-requests:
en: 4ec7d1892b4067db
zh: 6bb70d21ae3d7a89
diff --git a/docs/subsystems/forge.md b/docs/subsystems/forge.md
index 2a3cdf2087..f56d88b848 100644
--- a/docs/subsystems/forge.md
+++ b/docs/subsystems/forge.md
@@ -2,7 +2,7 @@
English | [中文](forge.zh.md)
-The experimental forge capability seam reads change requests, meaning pull requests and merge requests, from code hosts. [`dsh-experimental-forge`](../../packages/experimental/forge/README.md) is the Service Definition and provides `ctx.forge`; [`dsh-experimental-forge-github`](../../packages/experimental/forge-github/README.md) is the Service Provider for GitHub hosts; [`dsh-experimental-forge-session`](../../packages/experimental/forge-session/README.md) is the Consumer that binds change requests to Sessions and provides `ctx.forgeSession`; [`dsh-experimental-client-ui-forge`](../../packages/experimental/client-ui-forge/README.md) is the GUI Consumer that provides `ctx.forgePanel`. The default-disabled [forge bundle](../../packages/experimental/forge-bundle/README.md) composes all four, with an isolated [worktree service](../../packages/experimental/worktree/README.md) for the panel, from the Plugins page; otherwise they load only through explicit composition.
+The experimental forge capability seam reads change requests, meaning pull requests and merge requests, from code hosts. [`dsh-experimental-forge`](../../packages/experimental/forge/README.md) is the Service Definition and provides `ctx.forge`; [`dsh-experimental-forge-github`](../../packages/experimental/forge-github/README.md) is the Service Provider for GitHub hosts; [`dsh-experimental-forge-session`](../../packages/experimental/forge-session/README.md) is the Consumer that binds change requests to Sessions and provides `ctx.forgeSession`; [`dsh-experimental-client-ui-forge`](../../packages/experimental/client-ui-forge/README.md) is the GUI Consumer that provides `ctx.forgePanel`. The default-disabled [forge bundle](../../packages/experimental/forge-bundle/README.md) composes all four, with the [worktree model tool](../../packages/experimental/tool-worktree/README.md) and an isolated [worktree service](../../packages/experimental/worktree/README.md) for the panel, from the Plugins page; otherwise they load only through explicit composition.
## Providers and change requests
diff --git a/docs/subsystems/forge.zh.md b/docs/subsystems/forge.zh.md
index 5c78d7bb02..bbcf8ace8f 100644
--- a/docs/subsystems/forge.zh.md
+++ b/docs/subsystems/forge.zh.md
@@ -2,7 +2,7 @@
[English](forge.md) | 中文
-实验性的 forge 能力 seam 从代码托管平台读取变更请求(change request,即 pull request 与 merge request)。[`dsh-experimental-forge`](../../packages/experimental/forge/README.zh.md) 是 Service Definition,提供 `ctx.forge`;[`dsh-experimental-forge-github`](../../packages/experimental/forge-github/README.zh.md) 是服务 GitHub 主机的 Service Provider;[`dsh-experimental-forge-session`](../../packages/experimental/forge-session/README.zh.md) 是把变更请求绑定到 Session 的 Consumer,提供 `ctx.forgeSession`;[`dsh-experimental-client-ui-forge`](../../packages/experimental/client-ui-forge/README.zh.md) 是提供 `ctx.forgePanel` 的 GUI Consumer。默认禁用的 [forge Bundle](../../packages/experimental/forge-bundle/README.zh.md) 可从插件页面组合这四个包,并为面板附带一个隔离的 [worktree 服务](../../packages/experimental/worktree/README.zh.md);除此之外,它们只能通过显式组合加载。
+实验性的 forge 能力 seam 从代码托管平台读取变更请求(change request,即 pull request 与 merge request)。[`dsh-experimental-forge`](../../packages/experimental/forge/README.zh.md) 是 Service Definition,提供 `ctx.forge`;[`dsh-experimental-forge-github`](../../packages/experimental/forge-github/README.zh.md) 是服务 GitHub 主机的 Service Provider;[`dsh-experimental-forge-session`](../../packages/experimental/forge-session/README.zh.md) 是把变更请求绑定到 Session 的 Consumer,提供 `ctx.forgeSession`;[`dsh-experimental-client-ui-forge`](../../packages/experimental/client-ui-forge/README.zh.md) 是提供 `ctx.forgePanel` 的 GUI Consumer。默认禁用的 [forge Bundle](../../packages/experimental/forge-bundle/README.zh.md) 可从插件页面组合这四个包,同时加载[工作树模型工具](../../packages/experimental/tool-worktree/README.zh.md),并为面板附带一个隔离的 [worktree 服务](../../packages/experimental/worktree/README.zh.md);除此之外,它们只能通过显式组合加载。
## 提供方与变更请求
diff --git a/docs/subsystems/worktrees.i18n.yaml b/docs/subsystems/worktrees.i18n.yaml
index f771dd3cf2..23dde9244e 100644
--- a/docs/subsystems/worktrees.i18n.yaml
+++ b/docs/subsystems/worktrees.i18n.yaml
@@ -3,8 +3,8 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/worktrees.md
/git-worktrees:
- en: 21ec4a3b825d7e81
- zh: c841c5ca4b4e8959
+ en: 3a3d69d2b12a78f9
+ zh: a7a7d12487968bbc
/git-worktrees/creation-and-retention:
en: 53f643c5d30e00b2
zh: ba9e52efc62c7656
diff --git a/docs/subsystems/worktrees.md b/docs/subsystems/worktrees.md
index 8d4fec853a..aefa3e4a3c 100644
--- a/docs/subsystems/worktrees.md
+++ b/docs/subsystems/worktrees.md
@@ -2,7 +2,7 @@
English | [中文](worktrees.zh.md)
-The experimental [`dsh-experimental-worktree`](../../packages/experimental/worktree/README.md) service provides `ctx.worktrees`. Its [`create_worktree`](../../packages/experimental/tool-worktree/README.md) consumer creates a new Git branch and checkout, then selects it through the [working-directory service](working-directory.md). The [Git Worktrees optional bundle](../../packages/experimental/tool-worktree/README.md#use-this-package) loads both packages through the GUI plugin manager. It ships switched off; explicit compositions can also mount the two packages.
+The experimental [`dsh-experimental-worktree`](../../packages/experimental/worktree/README.md) service provides `ctx.worktrees`. Its [`create_worktree`](../../packages/experimental/tool-worktree/README.md) consumer creates a new Git branch and checkout, then selects it through the [working-directory service](working-directory.md). The [Change requests & worktrees bundle](../../packages/experimental/forge-bundle/README.md#use-this-package) loads both packages through the GUI plugin manager and ships switched off. Other profiles can select the [standalone worktree bundle](../../packages/experimental/tool-worktree/README.md#use-this-package) or mount the two packages explicitly.
## Creation and retention
diff --git a/docs/subsystems/worktrees.zh.md b/docs/subsystems/worktrees.zh.md
index e6a7c71ecc..0f7c7b1b02 100644
--- a/docs/subsystems/worktrees.zh.md
+++ b/docs/subsystems/worktrees.zh.md
@@ -2,7 +2,7 @@
[English](worktrees.md) | 中文
-实验性的 [`dsh-experimental-worktree`](../../packages/experimental/worktree/README.zh.md) 服务提供 `ctx.worktrees`。其消费方 [`create_worktree`](../../packages/experimental/tool-worktree/README.zh.md) 创建新的 Git 分支与检出目录,再通过[工作目录服务](working-directory.zh.md)选中它。[Git 工作树可选 bundle](../../packages/experimental/tool-worktree/README.zh.md#use-this-package)通过 GUI 插件管理器一起加载这两个包。它随安装提供,但默认关闭;显式组合也可以挂载这两个包。
+实验性的 [`dsh-experimental-worktree`](../../packages/experimental/worktree/README.zh.md) 服务提供 `ctx.worktrees`。其消费方 [`create_worktree`](../../packages/experimental/tool-worktree/README.zh.md) 创建新的 Git 分支与检出目录,再通过[工作目录服务](working-directory.zh.md)选中它。[变更请求与工作树组合包](../../packages/experimental/forge-bundle/README.zh.md#use-this-package)通过 GUI 插件管理器一起加载这两个包,随安装提供但默认关闭。其他 profile 可以选择[独立工作树组合包](../../packages/experimental/tool-worktree/README.zh.md#use-this-package),或显式挂载这两个包。
## 创建与保留
diff --git a/docs/tool-catalog.i18n.yaml b/docs/tool-catalog.i18n.yaml
index 68f3651eaf..22deacea2a 100644
--- a/docs/tool-catalog.i18n.yaml
+++ b/docs/tool-catalog.i18n.yaml
@@ -9,8 +9,8 @@
en: 6cc2cd9ced70bb09
zh: 1c0e6cb4ba2ed637
/tool-schema-catalog/tool-package-map:
- en: 4aa572ac1710a97a
- zh: e11431504a2a7398
+ en: f790063d536da1bf
+ zh: 6933b54fc70cd470
/tool-schema-catalog/deepseek-ai-dsh-plugin-manager:
en: e0143916bb634762
zh: e0143916bb634762
@@ -321,8 +321,8 @@
en: d5f5679abe86e316
zh: d5f5679abe86e316
/tool-schema-catalog/deepseek-ai-dsh-experimental-tool-worktree/create-worktree:
- en: d8fe3c566ba2147c
- zh: baf372cb9242670c
+ en: 41950f76db71e7f7
+ zh: 654d2e5505ff3d3c
/tool-schema-catalog/deepseek-ai-dsh-tool-workflow:
en: bb38a9d29f46563c
zh: bb38a9d29f46563c
diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md
index 1d7900cf6b..9da0029e4f 100644
--- a/docs/tool-catalog.md
+++ b/docs/tool-catalog.md
@@ -46,7 +46,7 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-experimental-tool-agent-team` | `interrupt_agent`, `list_agents`, `send_message`, `spawn_teammate`, `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update`, `wait_agent` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `an exact live Team member Agent` | `tool/call`, `team/member`, `team/task`, `agent/inbox/spliced`, `user/message on inbox claim`, `tool/result` | - | All nine tools are scoped to implicit Team Leads and durable teammates. The shipped dsh-base bundle keeps the package disabled; the documented Agent Teams profile patch enables it while disabling the legacy continuable-child control names. |
| `@deepseek-ai/dsh-tool-todo` | `todo_write` | `ctx.tools`, `owning Agent session` | `tool/call`, `todo/write`, `tool/result` | - | todo_write is session-owned state; UIs render the latest todo/write event as a checklist. `allowParallelInProgress` is required with no default, so the catalog states its choice: `true`, whose description invites several `in_progress` items. A deployment choosing `false` receives the same tool with a description asking for exactly one active task. |
| `@deepseek-ai/dsh-tool-working-directory` | `working_directory` | `ctx.tools`, `ctx.workingDirectory` | `tool/call`, `working-directory/change`, `user context for directory changes`, `tool/result` | - | Reads or changes the calling Session directory. Existing shells and processes retain their own directories; origin metadata and permission roots stay fixed. |
-| `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | Explicit experimental composition only. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout. |
+| `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | Enabled through the Change requests & worktrees bundle on Web and Desktop; other profiles can select the standalone bundle. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout. |
| `@deepseek-ai/dsh-tool-workflow` | `workflow` | `ctx.tools`, `ctx.workflowEngine`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents the script children)` | `tool/call`, `tool/result` | - | - |
| `@deepseek-ai/dsh-tool-workspace-dependencies` | `load_workspace_dependencies` | `ctx.tools` | `tool/call`, `tool/result` | - | - |
| `@deepseek-ai/dsh-tool-web` | `web_fetch`, `web_search` | `ctx.tools`, `ctx.web`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | web_search and web_fetch keep provider selection behind ctx.web so model-visible schemas stay stable across backend swaps. |
@@ -2629,7 +2629,7 @@ Create a new Git branch and worktree from a local commit, branch, or tag, then c
Source: [`packages/experimental/tool-worktree/src/index.ts`](../packages/experimental/tool-worktree/src/index.ts)
-Explicit experimental composition only. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout.
+Enabled through the Change requests & worktrees bundle on Web and Desktop; other profiles can select the standalone bundle. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout.
diff --git a/docs/tool-catalog.zh.md b/docs/tool-catalog.zh.md
index cc5c16d779..19e6f8beb5 100644
--- a/docs/tool-catalog.zh.md
+++ b/docs/tool-catalog.zh.md
@@ -50,7 +50,7 @@
| `@deepseek-ai/dsh-experimental-tool-agent-team` | `interrupt_agent`、`list_agents`、`send_message`、`spawn_teammate`、`team_task_create`、`team_task_get`、`team_task_list`、`team_task_update`、`wait_agent` | `ctx.tools`、`ctx.systemPrompt`、`ctx.agentTeams`、`an exact live Team member Agent` | `tool/call`、`team/member`、`team/task`、`agent/inbox/spliced`、`user/message on inbox claim`、`tool/result` | - | 这 9 个工具限定于隐式 Team Lead 与持久 teammate 作用域。随产品发布的 dsh-base bundle 默认禁用该包;文档中的 Agent Teams profile patch 会启用它,并禁用旧 continuable child 的同名控制工具。 |
| `@deepseek-ai/dsh-tool-todo` | `todo_write` | `ctx.tools`、`owning Agent session` | `tool/call`、`todo/write`、`tool/result` | - | todo_write 是会话所有的状态;UI 将最新的 todo/write 事件渲染为检查清单。`allowParallelInProgress` 是没有默认值的必填项,因此本目录明确选择 `true`,对应描述允许同时存在多个 `in_progress` 项。选择 `false` 的部署会获得同一工具,但描述会要求只能有 1 个活动任务。 |
| `@deepseek-ai/dsh-tool-working-directory` | `working_directory` | `ctx.tools`, `ctx.workingDirectory` | `tool/call`, `working-directory/change`, `user context for directory changes`, `tool/result` | - | 读取或改变调用方 Session 的目录。已有 shell 和进程保留自己的目录;原始元数据和权限根目录保持不变。 |
-| `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | 仅通过显式实验组合加载。在现有写权限下从固定的本地提交创建新分支与检出目录,再改变 Session 工作目录。离开时保留分支与检出目录。 |
+| `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | 在 Web 和 Desktop 上通过变更请求与工作树组合包启用;其他 profile 可以选择独立组合包。在现有写权限下从固定的本地提交创建新分支与检出目录,再改变 Session 工作目录。离开时保留分支与检出目录。 |
| `@deepseek-ai/dsh-tool-workflow` | `workflow` | `ctx.tools`、`ctx.workflowEngine`、`ctx.systemPrompt`、`a calling Agent (exec.agent parents the script children)` | `tool/call`、`tool/result` | - | - |
| `@deepseek-ai/dsh-tool-workspace-dependencies` | `load_workspace_dependencies` | `ctx.tools` | `tool/call`, `tool/result` | - | - |
| `@deepseek-ai/dsh-tool-web` | `web_fetch`、`web_search` | `ctx.tools`、`ctx.web`、`ctx.systemPrompt` | `tool/call`、`tool/result` | - | web_search 和 web_fetch 将提供方选择置于 ctx.web 之后,使模型可见 schema 在更换后端时保持稳定。 |
@@ -2636,7 +2636,7 @@ todo_write 是会话所有的状态;UI 将最新的 todo/write 事件渲染为
来源:[`packages/experimental/tool-worktree/src/index.ts`](../packages/experimental/tool-worktree/src/index.ts)
-仅通过显式实验组合加载。在现有写权限下从固定的本地提交创建新分支与检出目录,再改变 Session 工作目录。离开时保留分支与检出目录。
+在 Web 和 Desktop 上通过变更请求与工作树组合包启用;其他 profile 可以选择独立组合包。在现有写权限下从固定的本地提交创建新分支与检出目录,再改变 Session 工作目录。离开时保留分支与检出目录。
diff --git a/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.i18n.yaml b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.i18n.yaml
new file mode 100644
index 0000000000..a5bd96e947
--- /dev/null
+++ b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.i18n.yaml
@@ -0,0 +1,16 @@
+# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
+# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
+# After editing either side, bring the other along and re-record with:
+# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md
+/:
+ en: e25e3adac59e3584
+ zh: 1a16ac4c16ab3a0d
+/one-plugin-entry-for-change-requests-and-worktrees:
+ en: 2eb2f0805d09f0c4
+ zh: a7b02646515b39df
+/one-plugin-entry-for-change-requests-and-worktrees/change:
+ en: b814d167dea20941
+ zh: a8e3c416acd4fb65
+/one-plugin-entry-for-change-requests-and-worktrees/migration:
+ en: 08b0e3bae9e9697e
+ zh: 62f66d48328f1037
diff --git a/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md
new file mode 100644
index 0000000000..3b8bf683bd
--- /dev/null
+++ b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md
@@ -0,0 +1,29 @@
+---
+kind: upgrade-guide
+description: "The Plugins page replaces the standalone Git worktrees card with Change requests & worktrees."
+---
+
+# One plugin entry for change requests and worktrees
+
+English | [中文](guide.zh.md)
+
+## Change
+
+Web and Desktop use **Change requests & worktrees** to enable the review panel, the new-Session worktree option, and the model's `create_worktree` tool together. The separate **Git worktrees** card is hidden. Profiles that already enabled the Forge bundle also gain the model tool.
+
+Existing profiles are not migrated automatically. A selected `@deepseek-ai/dsh-experimental-tool-worktree` bundle stays active even though its card is hidden, so turning off Forge does not disable that standalone tool. Selecting both it and `@deepseek-ai/dsh-experimental-forge-bundle` inserts duplicate `worktree` and `tool-worktree` ids, making those component controls read-only. Remove the standalone selection before using the unified switch.
+
+## Migration
+
+1. Stop Web or quit Desktop. Back up `$DSH_HOME/profiles//package.json` and its sibling `cordis.patch.yml`. Use `~/.dsh` when `DSH_HOME` is unset; the standard profile names are `web` and `desktop`. For a custom profile, use its name.
+2. Edit `dsh.profile.bundles` in that `package.json`. Remove every `@deepseek-ai/dsh-experimental-tool-worktree` entry. To keep worktree support through the unified switch, add `@deepseek-ai/dsh-experimental-forge-bundle` once; if it is already selected, keep that entry. To disable both features, remove both bundle names. Preserve all other entries and fields.
+3. Keep existing `cordis.patch.yml` overrides: the `worktree`, `tool-worktree`, and `optional-forge-panel` ids are unchanged. To use the Forge panel without exposing the model tool, add or update this entry in the existing patch list:
+
+ ```yaml
+ - id: tool-worktree
+ disabled: true
+ ```
+
+4. Restart the application. In Plugins, confirm that **Change requests & worktrees** reflects your selection. With no disabling row override, enabling it provides the panel and `create_worktree`; turning it off removes both. Confirm that the profile lists no standalone worktree bundle. Existing worktrees, branches, and Session records are retained.
+
+Headless profiles and custom compositions that need only the standalone tool can keep it; do not also select the Forge bundle. In Web or Desktop, that standalone selection remains hidden and must be managed through the profile file.
diff --git a/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.zh.md b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.zh.md
new file mode 100644
index 0000000000..118f00bd22
--- /dev/null
+++ b/docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.zh.md
@@ -0,0 +1,29 @@
+---
+kind: upgrade-guide
+description: "插件页将独立的 Git 工作树卡片合入变更请求与工作树。"
+---
+
+# 变更请求与工作树使用同一个插件入口
+
+[English](guide.md) | 中文
+
+## 变更
+
+Web 和 Desktop 通过**变更请求与工作树**同时启用评审面板、新会话的工作树选项和模型的 `create_worktree` 工具。独立的 **Git 工作树**卡片被隐藏。已经启用 Forge 组合包的 profile 也会新增模型工具。
+
+已有 profile 不会自动迁移。选中的 `@deepseek-ai/dsh-experimental-tool-worktree` 组合包仍会运行,即使其卡片已隐藏,因此关闭 Forge 不会停用这个独立工具。同时选择它和 `@deepseek-ai/dsh-experimental-forge-bundle` 会插入重复的 `worktree` 与 `tool-worktree` id,使对应组件控件变为只读。使用统一开关前,请移除独立组合包的选择。
+
+## 迁移
+
+1. 停止 Web 或退出 Desktop。备份 `$DSH_HOME/profiles//package.json` 及同目录下的 `cordis.patch.yml`。未设置 `DSH_HOME` 时使用 `~/.dsh`;标准 profile 名称为 `web` 和 `desktop`。自定义 profile 使用其自身名称。
+2. 编辑该 `package.json` 的 `dsh.profile.bundles`。移除所有 `@deepseek-ai/dsh-experimental-tool-worktree` 条目。若要通过统一开关保留工作树功能,添加一次 `@deepseek-ai/dsh-experimental-forge-bundle`;若已选中它,则保留该条目。若要关闭两项功能,则移除这两个组合包名称。保留其他所有条目和字段。
+3. 保留现有的 `cordis.patch.yml` 覆盖配置:`worktree`、`tool-worktree` 和 `optional-forge-panel` 的 id 均未改变。若只使用 Forge 面板,不向模型提供工作树工具,在现有 patch 列表中添加或更新以下条目:
+
+ ```yaml
+ - id: tool-worktree
+ disabled: true
+ ```
+
+4. 重启应用。在插件页确认**变更请求与工作树**的状态符合你的选择。没有禁用插件行的覆盖配置时,启用它会提供面板与 `create_worktree`,关闭后两者均移除。确认 profile 不再列出独立的工作树组合包。已有工作树、分支和 Session 记录均保留。
+
+仅需要独立工具的 Headless profile 和自定义组合可以继续保留它,但不要同时选择 Forge 组合包。在 Web 或 Desktop 中,该独立选择仍然隐藏,需要通过 profile 文件管理。
diff --git a/packages/client/ui-plugin-manager/tests/components.client.spec.tsx b/packages/client/ui-plugin-manager/tests/components.client.spec.tsx
index adacb15d71..29dd9ffd63 100644
--- a/packages/client/ui-plugin-manager/tests/components.client.spec.tsx
+++ b/packages/client/ui-plugin-manager/tests/components.client.spec.tsx
@@ -300,30 +300,30 @@ describe('PluginManagerPage', () => {
})
it('keeps the Installed tab panel through loading and the More list out of the tabs, and returns a More plugin opened from Discover to Discover', () => {
- const worktree = '@deepseek-ai/dsh-experimental-tool-worktree'
+ const inspector = '@deepseek-ai/dsh-experimental-inspector-profile'
const { navigation, set } = renderTab({ status: 'loading', packages: [] }, {}, {
'plugins.tab:discover': (_view, owner) => (
-
+
),
}, {}, [{ id: 'discover', label: 'Discover' }])
const installed = screen.getByRole('tab', { name: en.installedTab })
expect(document.getElementById(installed.getAttribute('aria-controls') as string)?.getAttribute('role')).toBe('tabpanel')
set({ status: 'ready', packages: [] })
expect(screen.getByRole('tabpanel', { name: en.installedTab }).textContent).toBe(en.empty)
- set({ packages: [pkg({ name: worktree, official: true, optional: true, installed: false, enabled: false })] })
+ set({ packages: [pkg({ name: inspector, official: true, optional: true, installed: false, enabled: false })] })
act(() => { navigation.actions.setView({ kind: 'more' }) })
expect(screen.queryByRole('tablist')).toBeNull()
expect(screen.queryByRole('tabpanel')).toBeNull()
act(() => { navigation.actions.setView({ kind: 'list' }) })
fireEvent.click(screen.getByRole('tab', { name: 'Discover' }))
fireEvent.click(screen.getByRole('button', { name: 'Discover open' }))
- expect(document.querySelector(`[data-plugin-detail="${worktree}"]`)).not.toBeNull()
+ expect(document.querySelector(`[data-plugin-detail="${inspector}"]`)).not.toBeNull()
// An official plugin of the More list opened from Discover returns to Discover, not to the More list.
fireEvent.click(screen.getByRole('button', { name: en.backToList }))
expect(navigation.getSnapshot()).toEqual({ tab: 'discover', view: { kind: 'list' } })
fireEvent.click(screen.getByRole('tab', { name: en.installedTab }))
act(() => { navigation.actions.setView({ kind: 'more' }) })
- fireEvent.click(screen.getByRole('button', { name: en.openDetail.replace('{name}', worktree) }))
+ fireEvent.click(screen.getByRole('button', { name: en.openDetail.replace('{name}', inspector) }))
fireEvent.click(screen.getByRole('button', { name: en.backToPackage.replace('{name}', en.moreTitle) }))
expect(screen.getByRole('heading', { name: en.moreTitle, level: 1 })).toBeTruthy()
})
@@ -1237,7 +1237,7 @@ describe('PluginManagerPage', () => {
.toEqual(['more'])
const more = document.querySelector('[data-plugin-group="more"]') as HTMLElement
expect(within(more).getAllByRole('listitem').map(card => card.getAttribute('data-plugin-package')))
- .toEqual([team, '@acme/new-official', '@deepseek-ai/dsh-experimental-tool-worktree', '@deepseek-ai/dsh-experimental-badge-skill-bundle', '@deepseek-ai/dsh-subagent-codex', '@deepseek-ai/dsh-subagent-claude-code'])
+ .toEqual([team, '@acme/new-official', '@deepseek-ai/dsh-experimental-badge-skill-bundle', '@deepseek-ai/dsh-subagent-codex', '@deepseek-ai/dsh-subagent-claude-code'])
expect(document.querySelector('[data-plugin-package="dsh-better-sidebar"]')).toBeNull()
fireEvent.click(screen.getByRole('button', { name: en.openDetail.replace('{name}', team) }))
fireEvent.click(screen.getByRole('button', { name: en.backToPackage.replace('{name}', en.moreTitle) }))
@@ -1255,6 +1255,20 @@ describe('PluginManagerPage', () => {
expect(screen.getByRole('heading', { name: en.basicTitle })).toBeTruthy()
})
+ it.each([false, true])('shows one forge card and hides the standalone worktree card when enabled is %s', (enabled) => {
+ const forge = '@deepseek-ai/dsh-experimental-forge-bundle'
+ const worktree = '@deepseek-ai/dsh-experimental-tool-worktree'
+ renderTab({ packages: [
+ pkg({ name: forge, official: true, enabled }),
+ pkg({ name: worktree, official: true, enabled }),
+ ] })
+ expect(document.querySelectorAll(`[data-plugin-package="${forge}"]`)).toHaveLength(1)
+ expect(document.querySelector(`[data-plugin-package="${worktree}"]`)).toBeNull()
+ fireEvent.click(screen.getByRole('button', { name: en.moreAction }))
+ expect(document.querySelectorAll(`[data-plugin-package="${forge}"]`)).toHaveLength(1)
+ expect(document.querySelector(`[data-plugin-package="${worktree}"]`)).toBeNull()
+ })
+
it.each([
'@deepseek-ai/dsh-cua-bundle',
'@deepseek-ai/dsh-experimental-session-search',
@@ -1361,7 +1375,7 @@ describe('PluginManagerPage', () => {
})
it.each([
- '@deepseek-ai/dsh-experimental-tool-worktree',
+ '@deepseek-ai/dsh-experimental-inspector-profile',
'@deepseek-ai/dsh-personalized-recommendations',
])('pins enabled %s onto the main list and removes it when disabled', (first) => {
const team = '@deepseek-ai/dsh-experimental-agent-team-profile'
diff --git a/packages/experimental/forge-bundle/README.i18n.yaml b/packages/experimental/forge-bundle/README.i18n.yaml
index 159422daed..9894b7f03c 100644
--- a/packages/experimental/forge-bundle/README.i18n.yaml
+++ b/packages/experimental/forge-bundle/README.i18n.yaml
@@ -9,26 +9,26 @@
en: 567570af44a77fa2
zh: 3d7722fe3ade65d6
/deepseek-ai-dsh-experimental-forge-bundle/summary:
- en: f6ce7db50e10af0b
- zh: 415f509876e88d8a
+ en: 8d8189bb9a91f049
+ zh: 27f02215d6919b3d
/deepseek-ai-dsh-experimental-forge-bundle/table-of-contents:
en: d152484eb41ac6b4
zh: 2f8a621b991260a1
/deepseek-ai-dsh-experimental-forge-bundle/use-this-package:
- en: 227f8ec88513be9e
- zh: be16cbbb4f3912e2
+ en: 33679bed06be4e74
+ zh: 77dcfac9570d1fbc
/deepseek-ai-dsh-experimental-forge-bundle/understand-the-implementation:
- en: 6effcbf40264388b
- zh: b4f093955671c650
+ en: 5cb4136ef2058890
+ zh: 5142828996eef6c7
/deepseek-ai-dsh-experimental-forge-bundle/further-exploration:
en: ab1f524b8ad79c55
zh: 137cfcb6d192c269
/deepseek-ai-dsh-experimental-forge-bundle/model-experience:
- en: 0e8d555c9ba51844
- zh: 1aeda456da13a9bd
+ en: 48e871ea5f1238c8
+ zh: 6d40dddf8de9d610
/deepseek-ai-dsh-experimental-forge-bundle/model-experience/kv-cache-effect:
- en: 06c8b68589e27fc7
- zh: 092fd7649b34bc04
+ en: 0192ab064b8000a7
+ zh: 1a1de04f87631b9a
/deepseek-ai-dsh-experimental-forge-bundle/known-limitations-and-deferred-work:
en: ab489084b24ecb16
zh: 6be1686e9741dffa
diff --git a/packages/experimental/forge-bundle/README.md b/packages/experimental/forge-bundle/README.md
index 57341e2660..236c5a3a6e 100644
--- a/packages/experimental/forge-bundle/README.md
+++ b/packages/experimental/forge-bundle/README.md
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
## Summary
-Show the change requests of each Session with their checks and reviews, and let a new Session start in its own Git worktree. Enable Change requests & worktrees on the Web or Desktop Plugins page; shipped profiles leave it disabled. GitHub status comes from the `gh` CLI signed in on the Host; without it, the panel still shows the branch and the worktree option still works.
+Review each Session's change requests, checks, and diffs, start a new Session in a Git worktree, or ask the model to create one during a conversation. Enable Change requests & worktrees on the Web or Desktop Plugins page; shipped profiles leave it disabled. GitHub status comes from the Host's signed-in `gh` CLI; local worktree creation does not require GitHub authentication.
## Table of Contents
@@ -27,6 +27,8 @@ Show the change requests of each Session with their checks and reviews, and let
Open Plugins and enable Change requests & worktrees in the Official group. In a Git workspace, check Worktree in the composer before the first message to start the Session in a new worktree. In a Session whose directory is inside a Git checkout, the header button opens the panel. GitHub pull requests that the Session creates with `gh pr create`, opens with `gh pr view`, `gh pr edit`, or `gh pr checkout`, or works on as its branch or updates with a later `git push`, appear as change requests without further steps. Run `gh auth login --hostname ` in a terminal to sign in; the panel shows the command when sign-in is missing. The [panel package](../client-ui-forge/README.md#use-this-package) describes each control.
+The same switch enables the model's [`create_worktree`](../tool-worktree/README.md) tool. Turning it off removes both the panel and the tool while retaining existing checkouts and branches. For profiles that already selected the standalone worktree bundle, follow the [upgrade guide](../../../docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md) before enabling this bundle.
+
-----
@@ -35,7 +37,7 @@ Open Plugins and enable Change requests & worktrees in the Official group. In a
Maintainer details — click to expand
-The bundle patch inserts the forge registry, the GitHub provider, and the Session bindings as Host rows, and a group that isolates the `worktrees` service, holding a worktree service row and the panel's two-face package, whose Client half the Web and Desktop clients load while the row is enabled. The isolation lets the bundle coexist with the Git Worktrees bundle, whose model tool keeps its own service. The rows need the Session projection registry, working-directory, filesystem, subprocess, and sandbox services that every base-backed profile composes.
+The bundle mounts the forge registry, GitHub provider, Session bindings, and the worktree model tool. The tool uses the top-level `worktree` service; the panel keeps its isolated `forge-worktree` service inside `optional-forge-panel`. Their configuration ids and creation flows stay independent. The panel records worktrees requested before a Session starts; model-created worktrees do not acquire the panel's recovery records. The rows use the Session projection, working-directory, filesystem, subprocess, and sandbox services from base-backed profiles.
@@ -51,11 +53,11 @@ The bundle patch inserts the forge registry, the GitHub provider, and the Sessio
## Model Experience
-None, as the composed packages add no model tool or prompt; the directory notice of a Session that starts in a worktree reaches the model through the working-directory service, as described by the [panel](../client-ui-forge/README.md#model-experience).
+Indirectly, through the [`create_worktree`](../tool-worktree/README.md#model-experience) tool and the [panel’s directory notice](../client-ui-forge/README.md#model-experience) for Sessions that start in a worktree.
#### KV Cache effect
-None from the bundle; see the [panel](../client-ui-forge/README.md#model-experience) for the worktree notice.
+Enabling or disabling the bundle changes the model's tool schema list. Calls append tool results and directory context; see the [tool's cache behavior](../tool-worktree/README.md#model-experience).
## Known Limitations and Deferred Work
diff --git a/packages/experimental/forge-bundle/README.zh.md b/packages/experimental/forge-bundle/README.zh.md
index d65111cc34..955dc43598 100644
--- a/packages/experimental/forge-bundle/README.zh.md
+++ b/packages/experimental/forge-bundle/README.zh.md
@@ -9,7 +9,7 @@ kind: "package-bundle"
## 概述
-展示每个 Session 的变更请求及其检查与评审状态,并让新 Session 在自己的 Git worktree 中开始。在 Web 或 Desktop 的插件页面启用“变更请求与工作树”;发布的 profile 默认禁用该功能。GitHub 状态来自宿主上已登录的 `gh` 命令行;没有它时,面板仍会显示分支,工作树选项也照常可用。
+查看每个 Session 的变更请求、检查与代码差异,在 Git 工作树中开始新 Session,或在对话中让模型创建工作树。在 Web 或 Desktop 的插件页面启用“变更请求与工作树”;发布的 profile 默认禁用该功能。GitHub 状态来自宿主上已登录的 `gh` 命令行;创建本地工作树无需 GitHub 认证。
## 目录
@@ -27,6 +27,8 @@ kind: "package-bundle"
打开插件页面,在官方分组中启用“变更请求与工作树”。在 Git 工作区中,发出第一条消息之前在输入框中勾选“工作树”,Session 就会在新的 worktree 中开始。Session 的目录位于 Git 检出中时,标题栏按钮会打开面板。Session 用 `gh pr create` 创建、用 `gh pr view`、`gh pr edit` 或 `gh pr checkout` 打开的 GitHub pull request,以及 Session 所在分支上或之后 `git push` 更新的 pull request,无需额外操作即会作为变更请求出现。在终端运行 `gh auth login --hostname ` 登录;缺少登录时,面板会显示这条命令。[面板包](../client-ui-forge/README.zh.md#use-this-package)说明了每个控件。
+同一个开关也启用模型的 [`create_worktree`](../tool-worktree/README.zh.md) 工具。关闭后面板和工具一起移除,已有检出目录与分支仍然保留。已选中独立工作树组合包的 profile,请在启用本组合包前按[升级指南](../../../docs/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.zh.md)调整配置。
+
-----
@@ -35,7 +37,7 @@ kind: "package-bundle"
维护者细节——点击展开
-Bundle patch 以宿主行插入 forge 注册表、GitHub 提供方与 Session 绑定,并插入一个隔离 `worktrees` 服务的分组,其中包含一个 worktree 服务行与面板的双端包;该行启用期间,Web 与 Desktop 客户端会加载其客户端部分。隔离让本套件可以与 Git Worktrees 套件共存,后者的模型工具保有自己的服务。这些行依赖每个基于 base 的 profile 都会组合的 Session 投影注册表、工作目录、文件系统、子进程与沙箱服务。
+组合包挂载 Forge 注册表、GitHub 提供方、Session 绑定和工作树模型工具。工具使用顶层 `worktree` 服务;面板在 `optional-forge-panel` 内保留隔离的 `forge-worktree` 服务。两者的配置 id 和创建流程各自独立。面板记录 Session 开始前请求的工作树;模型创建的工作树不会获得面板的恢复记录。这些行使用基于 base 的 profile 提供的 Session 投影、工作目录、文件系统、子进程和沙箱服务。
@@ -51,11 +53,11 @@ Bundle patch 以宿主行插入 forge 注册表、GitHub 提供方与 Session
## 模型体验
-无:组合的包不增加模型工具或提示词;以 worktree 开始的 Session 的目录通知通过工作目录服务告知模型,详见[面板](../client-ui-forge/README.zh.md#model-experience)。
+间接影响:通过 [`create_worktree`](../tool-worktree/README.zh.md#model-experience) 工具,以及以工作树开始的 Session 的[面板目录通知](../client-ui-forge/README.zh.md#model-experience)。
#### KV Cache 影响
-Bundle 本身没有影响;worktree 通知见[面板](../client-ui-forge/README.zh.md#model-experience)。
+启用或关闭组合包会改变模型的工具 schema 列表。调用追加工具结果和目录上下文;参见[工具的缓存行为](../tool-worktree/README.zh.md#model-experience)。
## 已知限制与待办工作
diff --git a/packages/experimental/forge-bundle/cordis.patch.yml b/packages/experimental/forge-bundle/cordis.patch.yml
index d6008c8b4c..112caefaa4 100644
--- a/packages/experimental/forge-bundle/cordis.patch.yml
+++ b/packages/experimental/forge-bundle/cordis.patch.yml
@@ -1,4 +1,8 @@
- insert:
+ - id: worktree
+ name: '@deepseek-ai/dsh-experimental-worktree'
+ - id: tool-worktree
+ name: '@deepseek-ai/dsh-experimental-tool-worktree'
- id: forge
name: '@deepseek-ai/dsh-experimental-forge'
- id: forge-github
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.de.md b/packages/experimental/forge-bundle/docs/DETAIL.de.md
new file mode 100644
index 0000000000..c8ea4413c3
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.de.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.es.md b/packages/experimental/forge-bundle/docs/DETAIL.es.md
new file mode 100644
index 0000000000..94ccb3ba95
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.es.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.fr.md b/packages/experimental/forge-bundle/docs/DETAIL.fr.md
new file mode 100644
index 0000000000..93f4c53d34
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.fr.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.ja.md b/packages/experimental/forge-bundle/docs/DETAIL.ja.md
new file mode 100644
index 0000000000..386c9264f0
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.ja.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.md b/packages/experimental/forge-bundle/docs/DETAIL.md
new file mode 100644
index 0000000000..1da1b27021
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.pt.md b/packages/experimental/forge-bundle/docs/DETAIL.pt.md
new file mode 100644
index 0000000000..c08124a106
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.pt.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.ru.md b/packages/experimental/forge-bundle/docs/DETAIL.ru.md
new file mode 100644
index 0000000000..78dc6bf6ab
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.ru.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/DETAIL.zh.md b/packages/experimental/forge-bundle/docs/DETAIL.zh.md
new file mode 100644
index 0000000000..6114b4065e
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/DETAIL.zh.md
@@ -0,0 +1 @@
+
diff --git a/packages/experimental/forge-bundle/docs/preview.svg b/packages/experimental/forge-bundle/docs/preview.svg
new file mode 100644
index 0000000000..dd278ed0ce
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/preview.svg
@@ -0,0 +1,28 @@
+
diff --git a/packages/experimental/forge-bundle/docs/preview.zh.svg b/packages/experimental/forge-bundle/docs/preview.zh.svg
new file mode 100644
index 0000000000..fc880256f9
--- /dev/null
+++ b/packages/experimental/forge-bundle/docs/preview.zh.svg
@@ -0,0 +1,28 @@
+
diff --git a/packages/experimental/forge-bundle/locale/de.json b/packages/experimental/forge-bundle/locale/de.json
index b3a7562daa..3bcf081796 100644
--- a/packages/experimental/forge-bundle/locale/de.json
+++ b/packages/experimental/forge-bundle/locale/de.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Änderungsanfragen und Arbeitsbäume",
- "description": "Verfolgen Sie die Änderungsanfragen jeder Sitzung mit ihren Prüfungen und Reviews und starten Sie neue Sitzungen in einem Git-Arbeitsbaum; nutzt die gh CLI für GitHub."
+ "description": "Verknüpfte GitHub-Pull-Requests neben der Unterhaltung verfolgen: Prüfungen und Reviews ansehen, Code vergleichen und Feedback an den Agenten senden. Lokale Änderungen prüfen und Aufgaben mit separaten Arbeitsbäumen isolieren. GitHub-Funktionen erfordern eine installierte gh-CLI und eine Anmeldung auf dem Host.",
+ "detail": "docs/DETAIL.de.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/en.json b/packages/experimental/forge-bundle/locale/en.json
index f61d885db9..e52e41ba9f 100644
--- a/packages/experimental/forge-bundle/locale/en.json
+++ b/packages/experimental/forge-bundle/locale/en.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Change requests & worktrees",
- "description": "Track each Session's change requests with their checks and reviews, and start new Sessions in a Git worktree; uses the gh CLI for GitHub."
+ "description": "Keep linked GitHub pull requests beside your conversation: follow checks and reviews, inspect diffs, and send feedback to the agent. Review local changes and use a separate worktree to isolate each task. GitHub features require the gh CLI installed and signed in on the host.",
+ "detail": "docs/DETAIL.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/es.json b/packages/experimental/forge-bundle/locale/es.json
index ecd059085e..254ebd65d6 100644
--- a/packages/experimental/forge-bundle/locale/es.json
+++ b/packages/experimental/forge-bundle/locale/es.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Solicitudes de cambio y árboles de trabajo",
- "description": "Siga las solicitudes de cambio de cada sesión con sus comprobaciones y revisiones, e inicie nuevas sesiones en un árbol de trabajo de Git; usa la CLI gh para GitHub."
+ "description": "Sigue los pull requests de GitHub vinculados a la conversación: consulta comprobaciones y revisiones, compara código y envía comentarios al agente. Revisa cambios locales y aísla cada tarea en un árbol de trabajo separado. Las funciones de GitHub requieren instalar la CLI gh e iniciar sesión en el equipo anfitrión.",
+ "detail": "docs/DETAIL.es.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/fr.json b/packages/experimental/forge-bundle/locale/fr.json
index d86288f126..109301d5ff 100644
--- a/packages/experimental/forge-bundle/locale/fr.json
+++ b/packages/experimental/forge-bundle/locale/fr.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Demandes de modification et arbres de travail",
- "description": "Suivez les demandes de modification de chaque session avec leurs vérifications et revues, et démarrez de nouvelles sessions dans un arbre de travail Git ; utilise la CLI gh pour GitHub."
+ "description": "Suivez les pull requests GitHub liées à votre conversation : consultez les vérifications et les revues, comparez le code et transmettez vos remarques à l’agent. Examinez les modifications locales et isolez chaque tâche dans un arbre de travail séparé. Les fonctions GitHub nécessitent la CLI gh installée et une connexion sur l’hôte.",
+ "detail": "docs/DETAIL.fr.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/ja.json b/packages/experimental/forge-bundle/locale/ja.json
index 0885da3f0a..126a8643d2 100644
--- a/packages/experimental/forge-bundle/locale/ja.json
+++ b/packages/experimental/forge-bundle/locale/ja.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "変更リクエストとワークツリー",
- "description": "各セッションの変更リクエストとそのチェックやレビューを追跡し、新しいセッションを Git ワークツリーで開始できます。GitHub には gh CLI を使用します。"
+ "description": "会話のサイドバーで関連付けられた GitHub PR をまとめて確認できます。チェックやレビューの状況、コードの差分を確認し、修正案をエージェントに渡せます。ローカルの変更確認や、独立したワークツリーによるタスクの分離にも対応します。GitHub 機能にはホストでの gh CLI のインストールとログインが必要です。",
+ "detail": "docs/DETAIL.ja.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/pt.json b/packages/experimental/forge-bundle/locale/pt.json
index 48821e9b5f..e7208c7c9e 100644
--- a/packages/experimental/forge-bundle/locale/pt.json
+++ b/packages/experimental/forge-bundle/locale/pt.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Solicitações de alteração e árvores de trabalho",
- "description": "Acompanhe as solicitações de alteração de cada sessão com suas verificações e revisões e inicie novas sessões em uma árvore de trabalho Git; usa a CLI gh para o GitHub."
+ "description": "Acompanhe os pull requests do GitHub vinculados à conversa: consulte verificações e revisões, compare código e envie comentários ao agente. Revise alterações locais e isole cada tarefa em uma árvore de trabalho separada. Os recursos do GitHub exigem a CLI gh instalada e uma sessão iniciada no host.",
+ "detail": "docs/DETAIL.pt.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/ru.json b/packages/experimental/forge-bundle/locale/ru.json
index 750ed7ace0..2541e956ca 100644
--- a/packages/experimental/forge-bundle/locale/ru.json
+++ b/packages/experimental/forge-bundle/locale/ru.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "Запросы на изменение и рабочие деревья",
- "description": "Отслеживайте запросы на изменение каждого сеанса вместе с их проверками и ревью и начинайте новые сеансы в рабочем дереве Git; для GitHub используется gh CLI."
+ "description": "Следите за связанными с беседой pull request GitHub: проверками, рецензиями и различиями в коде, а затем передавайте замечания агенту. Просматривайте локальные изменения и изолируйте задачи в отдельных рабочих деревьях. Для функций GitHub требуется установить CLI gh и войти в аккаунт на хосте.",
+ "detail": "docs/DETAIL.ru.md"
}
}
diff --git a/packages/experimental/forge-bundle/locale/zh.json b/packages/experimental/forge-bundle/locale/zh.json
index 50259f6fe0..7e4786270f 100644
--- a/packages/experimental/forge-bundle/locale/zh.json
+++ b/packages/experimental/forge-bundle/locale/zh.json
@@ -1,6 +1,7 @@
{
"meta": {
"title": "变更请求与工作树",
- "description": "跟踪每个会话的变更请求及其检查与评审,新会话也可以在 Git 工作树中开始;GitHub 通过 gh 命令行访问。"
+ "description": "在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。",
+ "detail": "docs/DETAIL.zh.md"
}
}
diff --git a/packages/experimental/forge-bundle/package.json b/packages/experimental/forge-bundle/package.json
index b66fbe47b0..13e3ab5025 100644
--- a/packages/experimental/forge-bundle/package.json
+++ b/packages/experimental/forge-bundle/package.json
@@ -27,6 +27,7 @@
"files": [
"icon.svg",
"locale/*.json",
+ "docs",
"lib/index.js",
"cordis.patch.yml",
"lib/types/**/*.d.ts"
@@ -37,6 +38,7 @@
"@deepseek-ai/dsh-experimental-forge": "workspace:*",
"@deepseek-ai/dsh-experimental-forge-github": "workspace:*",
"@deepseek-ai/dsh-experimental-forge-session": "workspace:*",
+ "@deepseek-ai/dsh-experimental-tool-worktree": "workspace:*",
"@deepseek-ai/dsh-experimental-worktree": "workspace:*"
},
"peerDependencies": {
diff --git a/packages/experimental/tool-worktree/README.i18n.yaml b/packages/experimental/tool-worktree/README.i18n.yaml
index 33ca340c2f..10910e375f 100644
--- a/packages/experimental/tool-worktree/README.i18n.yaml
+++ b/packages/experimental/tool-worktree/README.i18n.yaml
@@ -9,14 +9,14 @@
en: db61f6b6ad671f45
zh: 9f3083d7f5605cbb
/deepseek-ai-dsh-experimental-tool-worktree/summary:
- en: addc1cb3414df6be
- zh: 5f2d371d844b0568
+ en: 106bccb04bd14134
+ zh: 579b316a56bebbb8
/deepseek-ai-dsh-experimental-tool-worktree/table-of-contents:
en: d152484eb41ac6b4
zh: 2f8a621b991260a1
/deepseek-ai-dsh-experimental-tool-worktree/use-this-package:
- en: 06074f9f6989911b
- zh: 05c9a85b7cdcfbad
+ en: f357051b201aa5b9
+ zh: ace93e12e8d4de82
/deepseek-ai-dsh-experimental-tool-worktree/understand-the-implementation:
en: c03f875211ab69a8
zh: 8f49b82f90a60223
diff --git a/packages/experimental/tool-worktree/README.md b/packages/experimental/tool-worktree/README.md
index b614aa6a8e..2f1b293808 100644
--- a/packages/experimental/tool-worktree/README.md
+++ b/packages/experimental/tool-worktree/README.md
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
## Summary
-Add Git worktrees from the GUI plugin manager to let a model create and enter a new Git worktree with one call. This optional bundle is installed with Harness and stays off until selected. Native tool calls and PTC programs receive the same typed result, and the existing file policy governs creation.
+Let a model create and enter a new Git worktree with one call. Web and Desktop expose this tool through Change requests & worktrees; other profiles can select this standalone bundle. Native tool calls and PTC programs receive the same typed result, and the existing file policy governs creation.
## Table of Contents
@@ -25,7 +25,7 @@ Add Git worktrees from the GUI plugin manager to let a model create and enter a
## Use this package
-In the GUI, open **Plugins → Official → Git worktrees** and turn on the switch. The bundle loads the [worktree runtime](../worktree/README.md) and this tool together; it is off in every shipped profile. Turning it off removes `create_worktree` without deleting existing checkouts or branches. The built-in `working_directory` tool remains available.
+In the GUI, enable [Change requests & worktrees](../forge-bundle/README.md). The standalone bundle has no Plugins page card. Profiles without the Web application may select it in `dsh.profile.bundles`; it loads the [worktree runtime](../worktree/README.md) and this tool together. Turning it off removes `create_worktree` without deleting existing checkouts or branches. The built-in `working_directory` tool remains available.
For an explicit composition, mount this function plugin after the worktree runtime and tool registry.
diff --git a/packages/experimental/tool-worktree/README.zh.md b/packages/experimental/tool-worktree/README.zh.md
index 46afb3e972..8b37299687 100644
--- a/packages/experimental/tool-worktree/README.zh.md
+++ b/packages/experimental/tool-worktree/README.zh.md
@@ -9,7 +9,7 @@ kind: "package-bundle"
## 概述
-从 GUI 插件管理器添加 Git 工作树,让模型通过一次调用创建并进入新的 Git 工作树。此可选 bundle 随 Harness 安装,在选中之前保持关闭。原生工具调用与 PTC 程序获得相同的带类型结果,创建操作沿用现有文件策略。
+让模型通过一次调用创建并进入新的 Git 工作树。Web 与 Desktop 通过“变更请求与工作树”提供本工具;其他 profile 可以选择本独立组合包。原生工具调用与 PTC 程序获得相同的带类型结果,创建操作沿用现有文件策略。
## 目录
@@ -25,7 +25,7 @@ kind: "package-bundle"
## 使用本包
-在 GUI 中打开**插件 → 官方 → Git 工作树**并启用开关。此 bundle 一起加载[工作树运行时](../worktree/README.zh.md)与本工具;所有随附 profile 默认关闭它。关闭后会移除 `create_worktree`,已有检出目录与分支会保留。内置 `working_directory` 工具仍然可用。
+在 GUI 中启用[变更请求与工作树](../forge-bundle/README.zh.md)。独立组合包在插件页没有卡片。未组合 Web 应用的 profile 可以在 `dsh.profile.bundles` 中选择它;它一起加载[工作树运行时](../worktree/README.zh.md)与本工具。关闭后会移除 `create_worktree`,已有检出目录与分支会保留。内置 `working_directory` 工具仍然可用。
在显式组合中,将此函数插件挂载到工作树运行时和工具注册表之后。
diff --git a/packages/util/official-bundles/src/plugin-manager.ts b/packages/util/official-bundles/src/plugin-manager.ts
index 48f866a748..510c85699f 100644
--- a/packages/util/official-bundles/src/plugin-manager.ts
+++ b/packages/util/official-bundles/src/plugin-manager.ts
@@ -18,7 +18,7 @@ export const PROTECTED_PLUGINS: ReadonlySet = new Set([
])
/**
- * Built-in profile bundles and persistent terminals, which have no plugin manager page.
+ * Built-in profile bundles, persistent terminals, and the standalone worktree tool, which have no plugin manager page.
* Their Host availability and activation stay intact.
*/
export const HIDDEN_BUNDLES: ReadonlySet = new Set([
@@ -29,6 +29,7 @@ export const HIDDEN_BUNDLES: ReadonlySet = new Set([
'@deepseek-ai/dsh-acp-app',
'@deepseek-ai/dsh-sdk-minimal',
'@deepseek-ai/dsh-experimental-terminal-bundle',
+ '@deepseek-ai/dsh-experimental-tool-worktree',
])
/**
@@ -50,7 +51,6 @@ export const MORE_BUNDLES: readonly string[] = [
'@deepseek-ai/dsh-personalized-recommendations',
'@deepseek-ai/dsh-experimental-inspector-profile',
'@deepseek-ai/dsh-cua-bundle',
- '@deepseek-ai/dsh-experimental-tool-worktree',
'@deepseek-ai/dsh-experimental-cot-translation-bundle',
'@deepseek-ai/dsh-experimental-session-search',
'@deepseek-ai/dsh-experimental-session-titles-bundle',
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 451d80179f..78bf276a8d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10028,6 +10028,9 @@ importers:
'@deepseek-ai/dsh-experimental-forge-session':
specifier: workspace:*
version: link:../forge-session
+ '@deepseek-ai/dsh-experimental-tool-worktree':
+ specifier: workspace:*
+ version: link:../tool-worktree
'@deepseek-ai/dsh-experimental-worktree':
specifier: workspace:*
version: link:../worktree
diff --git a/scripts/gen-tool-catalog.ts b/scripts/gen-tool-catalog.ts
index a40c08fca0..5713199b1b 100644
--- a/scripts/gen-tool-catalog.ts
+++ b/scripts/gen-tool-catalog.ts
@@ -676,7 +676,7 @@ const TOOL_PACKAGES: ToolPackage[] = [
})
await ctx.plugin(ToolWorktree)
},
- note: 'Explicit experimental composition only. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout.',
+ note: 'Enabled through the Change requests & worktrees bundle on Web and Desktop; other profiles can select the standalone bundle. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout.',
},
{
pkg: '@deepseek-ai/dsh-tool-workflow',
diff --git a/scripts/optional-bundles.spec.ts b/scripts/optional-bundles.spec.ts
index 7423aa0c9f..e5c30c6c84 100644
--- a/scripts/optional-bundles.spec.ts
+++ b/scripts/optional-bundles.spec.ts
@@ -133,7 +133,7 @@ describe('optional bundles', () => {
}
})
- it('offers Git Worktrees as one disabled bundle with its runtime and tool', () => {
+ it('retains the standalone worktree bundle for explicit profiles', () => {
const name = '@deepseek-ai/dsh-experimental-tool-worktree'
expect(OPTIONAL_BUNDLES).toContain(name)
for (const template of Object.values(PROFILE_TEMPLATES)) expect(template.bundles).not.toContain(name)
@@ -144,7 +144,7 @@ describe('optional bundles', () => {
}
})
- it('offers the forge panel as one disabled bundle with its registry, provider, bindings, panel, and isolated worktree service', () => {
+ it('offers the forge panel and model worktree tool together with their separate worktree services', () => {
const name = '@deepseek-ai/dsh-experimental-forge-bundle'
expect(OPTIONAL_BUNDLES).toContain(name)
for (const template of Object.values(PROFILE_TEMPLATES)) expect(template.bundles).not.toContain(name)
@@ -154,24 +154,28 @@ describe('optional bundles', () => {
'@deepseek-ai/dsh-experimental-forge-github',
'@deepseek-ai/dsh-experimental-forge-session',
'@deepseek-ai/dsh-experimental-client-ui-forge',
- '@deepseek-ai/dsh-experimental-worktree',
+ '@deepseek-ai/dsh-experimental-tool-worktree',
]) {
expect(flattenRows(composeEntries(shipped)).some(row => row.name === moduleName)).toBe(false)
expect(rows.filter(row => row.name === moduleName && row.disabled !== true)).toHaveLength(1)
}
const group = composeEntries([...shipped, bundle(name).patches]).find(row => row.id === 'optional-forge-panel')
expect(group?.isolate).toEqual({ worktrees: true })
+ expect(rows.filter(row => row.name === '@deepseek-ai/dsh-experimental-worktree')).toHaveLength(2)
})
- it('composes the forge panel beside Git Worktrees with one worktree service each', () => {
- const composed = composeEntries([
- ...shipped,
- bundle('@deepseek-ai/dsh-experimental-tool-worktree').patches,
- bundle('@deepseek-ai/dsh-experimental-forge-bundle').patches,
- ], (message) => { throw new Error(message) })
- const topLevelIds = composed.flatMap(entry => typeof entry.id === 'string' ? [entry.id] : [])
- expect(topLevelIds).toHaveLength(new Set(topLevelIds).size)
- expect(flattenRows(composed).filter(row => row.name === '@deepseek-ai/dsh-experimental-worktree')).toHaveLength(2)
+ it('keeps the existing tool and panel row overrides addressable in the unified bundle', () => {
+ const config = { directory: '.agents/custom-worktrees' }
+ const warnings: string[] = []
+ const composed = composeEntries([...shipped, bundle('@deepseek-ai/dsh-experimental-forge-bundle').patches, [
+ { id: 'worktree', config },
+ { id: 'tool-worktree', disabled: true },
+ { id: 'optional-forge-panel', disabled: true },
+ ]], message => warnings.push(message))
+ expect(warnings).toEqual([])
+ expect(composed.find(row => row.id === 'worktree')?.config).toEqual(config)
+ expect(composed.find(row => row.id === 'tool-worktree')?.disabled).toBe(true)
+ expect(composed.find(row => row.id === 'optional-forge-panel')?.disabled).toBe(true)
})
it('ships all five lightweight bundles without selecting them in a default template', () => {
diff --git a/scripts/verify-package-readme-model-experience.ts b/scripts/verify-package-readme-model-experience.ts
index f18901f6be..09dbf45585 100644
--- a/scripts/verify-package-readme-model-experience.ts
+++ b/scripts/verify-package-readme-model-experience.ts
@@ -74,7 +74,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly> = {
'packages/experimental/forge': { kind: 'none', reason: 'Providers and watchers exchange code host status without contributing model context.' },
'packages/experimental/forge-github': { kind: 'none', reason: 'The provider reads pull request status for host-side watchers without contributing model context.' },
'packages/experimental/client-ui-forge': { kind: 'indirect', reason: 'Switching a Session directory from the panel reaches the model through the working-directory notice; inspection and status stay on the host.' },
- 'packages/experimental/forge-bundle': { kind: 'none', reason: 'Composes the forge packages and panel without adding a model tool or prompt.' },
+ 'packages/experimental/forge-bundle': { kind: 'indirect', reason: 'The worktree tool and panel own the model-visible schemas, results, and directory notices selected by the bundle.' },
'packages/experimental/forge-session': { kind: 'none', reason: 'Bindings, discovery records, and polled status stay on the host; binding records never enter model requests.' },
'packages/experimental/worktree': { kind: 'indirect', reason: 'The worktree tool renders creation results; the working-directory service owns model-visible directory context.' },
'packages/experimental/client-ui-stats': { kind: 'none', reason: 'The panel reads Session events and renders them in the browser; it registers no tool, prompt section, or model input.' },
diff --git a/snapshots/web/creation-recommendations/session.v4.jsonl b/snapshots/web/creation-recommendations/session.v4.jsonl
index b92ddb4ef8..f327415d58 100644
--- a/snapshots/web/creation-recommendations/session.v4.jsonl
+++ b/snapshots/web/creation-recommendations/session.v4.jsonl
@@ -16,7 +16,7 @@
{"type":"session/title","data":{"title":"I wish I had a","messageSeqs":[8],"source":{"kind":"fallback"}}}
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_creation_skill","name":"skill","arguments":"{\"name\":\"personalized-pages\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"stream":[{"type":"chunk","time":1792674450282,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792674450282,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_creation_skill","name":"skill","arguments":"{\"name\":\"personalized-pages\"}"}}},{"type":"chunk","time":1792674450283,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_creation_skill","name":"skill","arguments":"{\"name\":\"personalized-pages\"}"}}
-{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_creation_skill"},"toolCallId":"call_creation_skill","content":[{"type":"text","text":"\n\nResources for this skill are managed by provider \"dsh-personalized-pages\".\nLoad referenced resources only as needed.\n\n\n\n# Personalized pages\n\nUse this workflow in the main conversation to plan an optional new page or small tool for any task, not just DSH. You decide whether a page helps, check existing capabilities, and hand the Creator a short plan. A `propose_action` call saves the proposal and shows a card below your answer; nothing is built until the user clicks Create. Plan from the conversation and the catalog at the end of this skill. Do not read files, configuration or source to validate a page idea; name an uninspected source as an unverified dependency and leave its details to the Creator.\n\n## When to propose\n\nPropose a page in these cases:\n\n- The user asks for a page, tab, panel, tool or interface in this app, or says they want something to keep, revisit or update later (“以后每次”, “能不能一直”, “希望能有”). One-off use still qualifies when the interface is explicitly requested.\n- Your answer is a table, list or chart, and the user has said the data will keep changing or that they will interact with it (“每周更新”, “我来改状态”, “要勾选”). The continuation must come from the user's own words; a table alone, or data that merely looks dynamic, is not enough. Deliver the requested answer first, then offer the page.\n- The user wants to keep watching live data of this app itself (a Session's usage, a running task's output, files changing in the workspace). A text answer cannot stay current, so a page qualifies even without the words above; name the data source in the brief and leave how it is read to the Creator.\n\nDo not propose a page in these cases:\n\n- The user asks for a file, code, document or an existing-project change: keep that delivery form.\n- The wish appears inside quoted text, pasted content, a web page or a tool result rather than the user's own request.\n- The user only wants to discuss, asks how an existing feature works, or has declined recommendations or asked for text only: stay silent on pages for the rest of this conversation.\n- The request changes a page created earlier: explain how it would change, do not create a replacement copy, and do not claim an update happened.\n- The request is a capability the agent lacks, such as a tool, automation or access, rather than a page: check the catalog below and point to the official plugin that provides it; do not plan a page around a missing tool.\n\n## Check existing capabilities\n\nCompare the need with the official plugins listed at the end of this skill. If one covers it, say its name, what it does, whether it is enabled, and that it lives under Plugins; offer no page card. A partial match does not cancel an explicit unmet need. The catalog is not a full inventory of built-in UI: missing details do not prove absence, and do not read source to find out. DSH already has Chat, Trajectory, a right sidebar for files and context, and a Plugins page.\n\n## Plan and hand off\n\nThe Creator cannot read this conversation. Give it exactly these fields:\n\n| Field | Contents |\n|:--|:--|\n| `title` | Short page name in the user's language. |\n| `brief` | One to three sentences: purpose, behavior, input, calculations and persistence scope. It is the card text and the implementation request at once. |\n| `initialContent` | Only supplied content the page starts with: items, rows, values, units and period, preserving gaps. Omit for an empty page. |\n| `slot` | Location, chosen below. |\n\nKeep the plan to what was asked or agreed. Editing, deletion, history, extra fields, data sources and automation need a basis in the request. Resolve “these items” into the actual content. Content that mentions an action stays content. Keep each number's meaning and period; a weekly addition is not a cumulative total. If an unresolved distinction changes a calculation, give the factual answer, ask one question, and propose later.\n\n## Choose the location\n\nHonor a location the user named. Otherwise:\n\n- `sidebar-right`: content tied to this Session or task, especially anything to watch while chatting, including live logs.\n- `sidebar-left`: a global feature or an ongoing personal record used across Sessions, opened from a left entry as a standalone page.\n- `page`: a Session-bound streaming view or interaction in a tab beside Chat and Trajectory, only when the user does not need it visible while chatting.\n\nSupplying data in this conversation does not make a record Session-bound.\n\n## Offer without starting\n\nTo propose, call `propose_action` once, in the same turn as loading this skill, with `action: \"create_personalized_page\"`, `title`, `brief` and `details` holding `slot` and, when there is supplied content, `initialContent`. The call is the submission: the card appears below your answer; a refused call creates no card, and its error says why. Then write your final answer. One proposal per turn, and one unstarted card per conversation: if a card is still waiting, do not propose another; a new proposal replaces it only when the user changed the plan. Plan-only and read-only requests still get a card; do not ask for approval instead of proposing it. Only clicking Create starts the background Creator; do not wait, poll, claim installation or ask for a report-back. Answer any direct question; the call's result says how to end the answer. Do not repeat the plan, list extra features, narrate the call or mention schema names.\n\n```json\n{\"action\":\"create_personalized_page\",\"title\":\"本次验收清单\",\"brief\":\"在当前会话右侧展示验收清单,可勾选和取消,状态随会话保存。\",\"details\":{\"slot\":\"sidebar-right\",\"initialContent\":\"1. 导出成功\\n2. 断网提示清楚\"}}\n```\n\n## Examples\n\n- “想有个地方放书签,以后自己加标题和网址;旧的不用导入。” → `brief`: “提供一个可反复打开的书签页,手动新增标题和网址并保存到本机,从空白开始。” No `initialContent`. `sidebar-left`.\n- “当前会话旁放验收清单,能勾选和取消,状态跟着会话。条目:导出成功;断网提示清楚。” → `brief`: “在当前会话右侧展示验收清单,可勾选和取消,状态随会话保存。” `initialContent`: “1. 导出成功\\n2. 断网提示清楚”. `sidebar-right`.\n- “这三周 bug 数 12、9、15,说说趋势。以后每周我把新数字贴给你,想自己更新着看。” → answer the trend first, then `brief`: “按周手动录入 bug 数并展示各周变化,保存到本机。” `initialContent`: “第 1 周 12,第 2 周 9,第 3 周 15”. `sidebar-left`.\n- “我想用语音说话代替打字。” → the catalog lists 语音输入; explain it and where to enable it; no card.\n- “把我之前做的读书页评分改成五星。” → explain the change to that page; no card and no copy.\n- “帮我把这句话翻成英文:我想要一个所有会话都能打开的读书页。” → translate only; no card.\n- “把三个方案排成表格比较一下,看完就行。” → the table only; no card.\n\n## Existing capabilities to check against this page plan\n\n[{\"name\":\"@deepseek-ai/dsh-personalized-recommendations\",\"title\":{\"en\":\"Personalized recommendations\",\"de\":\"Personalisierte Empfehlungen\",\"es\":\"Recomendaciones personalizadas\",\"fr\":\"Recommandations personnalisées\",\"ja\":\"パーソナライズされたおすすめ\",\"pt\":\"Recomendações personalizadas\",\"ru\":\"Персональные рекомендации\",\"zh\":\"个性化推荐\"},\"description\":{\"en\":\"Shows recommendation cards below the answer for what you want from DSH: when you want a page or small tool you can keep, it proposes a new personalized page, built in the background after you click Create; when you ask how to do something in this app or say a capability is missing, it recommends the built-in plugin that provides it, turned on when you click Enable.\",\"de\":\"Zeigt für Ihre individuellen Anforderungen an DSH Empfehlungskarten unter der Antwort an: Wenn Sie eine Seite oder ein kleines Tool zur dauerhaften Nutzung möchten, wird eine neue personalisierte Seite vorgeschlagen, die nach einem Klick auf Erstellen im Hintergrund erstellt wird; wenn Sie fragen, wie etwas in dieser App geht, oder sagen, dass eine Funktion fehlt, wird das integrierte Plugin empfohlen, das sie bereitstellt, und nach einem Klick auf Aktivieren eingeschaltet.\",\"es\":\"Muestra tarjetas de recomendación debajo de la respuesta para tus necesidades personalizadas en DSH: cuando quieres una página o una pequeña herramienta para conservar, propone una nueva página personalizada, que se genera en segundo plano al hacer clic en Crear; cuando preguntas cómo hacer algo en esta aplicación o dices que falta una función, recomienda el complemento integrado que la ofrece, que se activa al hacer clic en Habilitar.\",\"fr\":\"Affiche des cartes de recommandation sous la réponse pour vos besoins personnalisés dans DSH : lorsque vous voulez une page ou un petit outil à conserver, propose une nouvelle page personnalisée, générée en arrière-plan après un clic sur Créer ; lorsque vous demandez comment faire quelque chose dans cette application ou signalez qu’une fonctionnalité manque, recommande le plugin intégré qui la fournit, activé lorsque vous cliquez sur Activer.\",\"ja\":\"DSH に対するあなた個人のニーズに合わせて、回答の下におすすめカードを表示します。長く使えるページや小さなツールが欲しいときは新しいパーソナルページを提案し、「作成」をクリックするとバックグラウンドで生成します。このアプリで何かをする方法を尋ねたときや機能が足りないと言ったときは、それを提供する内蔵プラグインを推薦し、「有効にする」をクリックすると有効になります。\",\"pt\":\"Mostra cartões de recomendação abaixo da resposta para suas necessidades personalizadas no DSH: quando você quer uma página ou uma pequena ferramenta para manter, propõe uma nova página personalizada, gerada em segundo plano depois que você clica em Criar; quando você pergunta como fazer algo neste aplicativo ou diz que falta um recurso, recomenda o plug-in integrado que o oferece, ativado quando você clica em Ativar.\",\"ru\":\"Показывает карточки рекомендаций под ответом с учетом ваших индивидуальных потребностей в DSH: когда вам нужна страница или небольшой инструмент для постоянного использования, предлагает новую персональную страницу, которая создается в фоне после нажатия «Создать»; когда вы спрашиваете, как что-то сделать в этом приложении, или говорите, что не хватает какой-то возможности, рекомендует встроенный плагин, который ее предоставляет, и включает его после нажатия «Включить».\",\"zh\":\"针对你对 DSH 的个性化需求,在回答下方展示推荐卡片:想要能长期使用的页面或小工具时,提议新增个性化页面,点击创建后在后台生成;问到本应用怎么做某件事或缺少某项能力时,推荐对应的内置插件,点击启用后开启。\"},\"enabled\":true},{\"name\":\"@deepseek-ai/dsh-experimental-agent-team-profile\",\"title\":{\"en\":\"Agent teams\",\"de\":\"Agententeams\",\"es\":\"Equipos de agentes\",\"fr\":\"Équipes d'agents\",\"ja\":\"エージェントチーム\",\"pt\":\"Equipes de agentes\",\"ru\":\"Команды агентов\",\"zh\":\"智能体团队\"},\"description\":{\"en\":\"Lets the agent you talk to split a job among named teammates, track it on a shared task board, and report back with their results.\",\"de\":\"Ermöglicht dem Agenten, mit dem Sie sprechen, eine Aufgabe auf benannte Teammitglieder aufzuteilen, sie auf einem gemeinsamen Aufgabenboard zu verfolgen und Ihnen mit deren Ergebnissen zu berichten.\",\"es\":\"Permite que el agente con el que habla reparta un trabajo entre compañeros con nombre, lo siga en un tablero de tareas compartido y le informe con sus resultados.\",\"fr\":\"Permet à l'agent avec lequel vous parlez de répartir un travail entre des coéquipiers nommés, de le suivre sur un tableau de tâches partagé et de vous rendre compte de leurs résultats.\",\"ja\":\"対話しているエージェントが、仕事を名前付きのチームメイトに分担させ、共有タスクボードで進捗を追跡し、チームメイトの結果をまとめて報告します。\",\"pt\":\"Permite que o agente com quem você conversa divida um trabalho entre colegas de equipe nomeados, acompanhe-o em um quadro de tarefas compartilhado e informe você com os resultados deles.\",\"ru\":\"Позволяет агенту, с которым вы общаетесь, распределить работу между именованными участниками команды, отслеживать её на общей доске задач и отчитываться перед вами об их результатах.\",\"zh\":\"让与你对话的智能体把工作分给有名字的队友,在共享任务看板上跟踪进度,并汇总队友的结果向你汇报。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-inspector-profile\",\"title\":{\"en\":\"Developer tools\",\"de\":\"Entwicklertools\",\"es\":\"Herramientas de desarrollador\",\"fr\":\"Outils de développement\",\"ja\":\"開発者ツール\",\"pt\":\"Ferramentas de desenvolvedor\",\"ru\":\"Инструменты разработчика\",\"zh\":\"开发者工具\"},\"description\":{\"en\":\"For troubleshooting: view what DSH recorded for a session in Session log, inspect per-turn and per-step statistics in the Statistics tab, and debug the DSH backend in Chrome DevTools.\",\"de\":\"Zur Fehlersuche: Sehen Sie in „Sitzungsprotokoll“, was DSH für eine Sitzung aufgezeichnet hat, prüfen Sie im Tab „Statistik“ Kontext, Dauer, Cache und Werkzeugkosten pro Runde und Schritt und debuggen Sie das DSH-Backend in Chrome DevTools.\",\"es\":\"Para solucionar problemas: vea en «Registro de sesión» lo que DSH registró de una sesión, consulte el contexto, los tiempos, la caché y el coste de herramientas por turno y paso en la pestaña «Estadísticas», y depure el backend de DSH en Chrome DevTools.\",\"fr\":\"Pour le dépannage : consultez dans « Journal de session » ce que DSH a enregistré pour une session, examinez le contexte, les durées, le cache et le coût des outils par tour et étape dans l’onglet « Statistiques », et déboguez le backend de DSH dans Chrome DevTools.\",\"ja\":\"トラブルシューティング用です。「セッションログ」で DSH がセッションについて記録した内容を確認し、「統計」タブでターン/ステップごとのコンテキスト、時間、キャッシュ、ツールコストを確認し、Chrome DevTools で DSH バックエンドをデバッグできます。\",\"pt\":\"Para solução de problemas: veja em «Registro da sessão» o que o DSH registrou de uma sessão, consulte contexto, tempos, cache e custo de ferramentas por turno e etapa na aba «Estatísticas» e depure o backend do DSH no Chrome DevTools.\",\"ru\":\"Для диагностики: просматривайте в «Журнале сеанса», что DSH записал для сеанса, смотрите контекст, время, кэш и стоимость инструментов по ходам и шагам на вкладке «Статистика» и отлаживайте бэкенд DSH в Chrome DevTools.\",\"zh\":\"用于排查问题:在「会话数据诊断」中查看 DSH 为会话记录的内容,在「统计」页签查看每轮/每步的上下文、耗时、缓存和工具成本,并在 Chrome DevTools 中调试 DSH 后端。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-voice-input-bundle\",\"title\":{\"en\":\"Voice input\",\"de\":\"Spracheingabe\",\"es\":\"Entrada de voz\",\"fr\":\"Saisie vocale\",\"ja\":\"音声入力\",\"pt\":\"Entrada de voz\",\"ru\":\"Голосовой ввод\",\"zh\":\"语音输入\"},\"description\":{\"en\":\"Transcribe recordings locally with SenseVoice; first use requires installing dependencies.\",\"de\":\"Transkribieren Sie Aufnahmen lokal mit SenseVoice; Für die erste Verwendung müssen Abhängigkeiten installiert werden.\",\"es\":\"Transcribe grabaciones localmente con SenseVoice; El primer uso requiere instalar dependencias.\",\"fr\":\"Transcrivez les enregistrements localement avec SenseVoice ; la première utilisation nécessite l'installation de dépendances.\",\"ja\":\"ローカルの SenseVoice で録音を文字に起こします。初回利用時には依存関係のインストールが必要です。\",\"pt\":\"Transcreva gravações localmente com SenseVoice; o primeiro uso requer a instalação de dependências.\",\"ru\":\"Транскрибируйте записи локально с помощью SenseVoice; при первом использовании требуется установка зависимостей.\",\"zh\":\"在本机使用 SenseVoice 转写录音,首次使用需安装依赖。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-auto-review\",\"title\":{\"en\":\"Auto authorization review\",\"de\":\"Automatische Autorisierungsüberprüfung\",\"es\":\"Revisión de autorización automática\",\"fr\":\"Examen des autorisations automatiques\",\"ja\":\"自動認可レビュー\",\"pt\":\"Revisão de autorização automática\",\"ru\":\"Проверка автоматической авторизации\",\"zh\":\"自动授权审查\"},\"description\":{\"en\":\"Adds an Auto review access mode: before each tool call, a model checks it against what you asked for, runs allowed calls at once, and holds denied calls for your approval.\",\"de\":\"Fügt den Zugriffsmodus „Auto review“ hinzu: Vor jedem Tool-Aufruf prüft ein Modell den Aufruf anhand Ihrer Anforderung; zugelassene Aufrufe laufen sofort, abgelehnte Aufrufe warten auf Ihre Genehmigung.\",\"es\":\"Añade el modo de acceso “Auto review”: antes de cada llamada a una herramienta, un modelo comprueba la llamada frente a lo que usted pidió; las llamadas permitidas se ejecutan de inmediato y las denegadas esperan su aprobación.\",\"fr\":\"Ajoute le mode d'accès « Auto review » : avant chaque appel d'outil, un modèle vérifie l'appel par rapport à ce que vous avez demandé ; les appels autorisés s'exécutent immédiatement et les appels refusés attendent votre approbation.\",\"ja\":\"「自動認可レビュー」アクセスモードを追加します。各ツール呼び出しの前に、モデルがその呼び出しをあなたの依頼内容と照らし合わせて確認し、許可された呼び出しは即座に実行され、拒否された呼び出しはあなたの承認を待ちます。\",\"pt\":\"Adiciona o modo de acesso “Auto review”: antes de cada chamada de ferramenta, um modelo verifica a chamada em relação ao que você pediu; as chamadas permitidas são executadas imediatamente e as negadas aguardam sua aprovação.\",\"ru\":\"Добавляет режим доступа «Auto review»: перед каждым вызовом инструмента модель сверяет вызов с вашей просьбой; разрешённые вызовы выполняются сразу, а отклонённые ждут вашего одобрения.\",\"zh\":\"提供“自动审查”访问模式:每次工具调用前,由模型对照你的要求检查,获准的调用立即运行,被拒绝的调用等你审批。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-cot-translation-bundle\",\"title\":{\"en\":\"Machine translation of reasoning\",\"de\":\"Maschinelle Übersetzung der Argumentation\",\"es\":\"Traducción automática de razonamiento\",\"fr\":\"Traduction automatique du raisonnement\",\"ja\":\"思考内容の機械翻訳\",\"pt\":\"Tradução automática de raciocínio\",\"ru\":\"Машинный перевод рассуждений\",\"zh\":\"思考过程机器翻译\"},\"description\":{\"en\":\"Translates expanded Think rows into your chosen language as the agent writes them, and View original switches back.\",\"de\":\"Übersetzt aufgeklappte „Denken Sie nach“-Zeilen, während der Agent sie schreibt, in die von Ihnen gewählte Sprache, und „Original ansehen“ wechselt zurück.\",\"es\":\"Traduce las filas “pensar” expandidas al idioma que elija mientras el agente las escribe, y “Ver original” vuelve al texto original.\",\"fr\":\"Traduit les lignes « Pensez » développées dans la langue de votre choix pendant que l'agent les écrit, et « Voir l'original » permet de revenir au texte d'origine.\",\"ja\":\"エージェントが書き出すのと同時に、展開された「思考」行を選択した言語に翻訳します。「原文を表示」で原文に戻せます。\",\"pt\":\"Traduz as linhas “Pense” expandidas para o idioma que você escolher enquanto o agente as escreve, e “Ver original” volta ao texto original.\",\"ru\":\"Переводит развёрнутые строки «Подумайте» на выбранный вами язык по мере того, как агент их пишет, а «Посмотреть оригинал» возвращает исходный текст.\",\"zh\":\"智能体输出时,把展开的“思考”行翻译成你选择的语言,点击“查看原文”可切换回原文。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-badge-skill-bundle\",\"title\":{\"en\":\"DSH badge skill\",\"de\":\"DSH-Abzeichen-Fertigkeit\",\"es\":\"Habilidad de insignia DSH\",\"fr\":\"Compétence du badge DSH\",\"ja\":\"DSH バッジスキル\",\"pt\":\"DSH habilidade de distintivo\",\"ru\":\"DSH значок навыка\",\"zh\":\"DSH 徽章技能\"},\"description\":{\"en\":\"Let agents add a “powered by dsh” badge to documents, pull requests, and other outputs.\",\"de\":\"Lassen Sie Agenten Dokumente, Pull-Requests und andere Ausgaben mit einem „powered by dsh“-Badge versehen.\",\"es\":\"Permita que los agentes agreguen una insignia \\\"con tecnología de dsh\\\" a documentos, solicitudes de extracción y otros resultados.\",\"fr\":\"Laissez les agents ajouter un badge « propulsé par dsh » aux documents, demandes d'extraction et autres sorties.\",\"ja\":\"エージェントが文書や PR などの成果物に「powered by dsh」バッジを追加できます。\",\"pt\":\"Permita que os agentes adicionem um selo “powered by dsh” a documentos, pull requests e outros resultados.\",\"ru\":\"Позвольте агентам добавлять значок «Powered by dsh» к документам, запросам на включение и другим результатам.\",\"zh\":\"让 Agent 为文档、PR 等产出添加「powered by dsh」徽章。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-ralph-bundle\",\"title\":{\"en\":\"Ralph loops\",\"de\":\"Ralph-Loops\",\"es\":\"Bucles de Ralph\",\"fr\":\"Boucles Ralph\",\"ja\":\"Ralph ループ\",\"pt\":\"Loops de Ralph\",\"ru\":\"Ральф петли\",\"zh\":\"Ralph 循环\"},\"description\":{\"en\":\"Ask for a Ralph loop with a goal, and the agent starts a fresh agent on it round after round until the goal is met, a blocker is reported, or the round limit is reached.\",\"de\":\"Bitten Sie um eine Ralph-Schleife mit einem Ziel, und der Agent startet Runde um Runde einen neuen Agenten darauf, bis das Ziel erreicht ist, ein Hindernis gemeldet wird oder das Rundenlimit erreicht ist.\",\"es\":\"Pida un bucle Ralph con un objetivo, y el agente inicia un agente nuevo sobre él ronda tras ronda hasta que se cumpla el objetivo, se informe de un bloqueo o se alcance el límite de rondas.\",\"fr\":\"Demandez une boucle Ralph avec un objectif, et l'agent lance un nouvel agent dessus, tour après tour, jusqu'à ce que l'objectif soit atteint, qu'un blocage soit signalé ou que la limite de tours soit atteinte.\",\"ja\":\"目標を指定して Ralph ループを依頼すると、エージェントは、目標が達成されるか、阻害要因が報告されるか、ラウンド数の上限に達するまで、ラウンドごとに新しいエージェントを起動してその目標に取り組ませます。\",\"pt\":\"Peça um loop Ralph com um objetivo, e o agente inicia um novo agente nele rodada após rodada até que o objetivo seja atingido, um bloqueio seja informado ou o limite de rodadas seja alcançado.\",\"ru\":\"Попросите запустить цикл Ralph с целью, и агент будет раунд за раундом запускать для неё нового агента, пока цель не будет достигнута, не будет сообщено о препятствии или не будет достигнут лимит раундов.\",\"zh\":\"要求用 Ralph 循环完成一个目标后,智能体会一轮接一轮地启动新的智能体处理它,直到目标达成、报告受阻或达到轮次上限。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-session-titles-bundle\",\"title\":{\"en\":\"Conversation-following titles\",\"de\":\"Konversationsfolgende Titel\",\"es\":\"Títulos que siguen la conversación\",\"fr\":\"Titres de suivi de conversation\",\"ja\":\"会話に追従するタイトル\",\"pt\":\"Títulos que acompanham conversas\",\"ru\":\"Заголовки, следующие за разговором\",\"zh\":\"随对话更新的标题\"},\"description\":{\"en\":\"Writes a session's title from all of your messages and updates it when the main task changes, instead of only from the first message.\",\"de\":\"Erstellt den Titel einer Sitzung aus all Ihren Nachrichten und aktualisiert ihn, wenn sich die Hauptaufgabe ändert, statt ihn nur aus der ersten Nachricht zu bilden.\",\"es\":\"Escribe el título de una sesión a partir de todos sus mensajes y lo actualiza cuando cambia la tarea principal, en lugar de basarse solo en el primer mensaje.\",\"fr\":\"Rédige le titre d'une session à partir de tous vos messages et le met à jour lorsque la tâche principale change, au lieu de se baser uniquement sur le premier message.\",\"ja\":\"最初のメッセージだけでなく、あなたのすべてのメッセージからセッションのタイトルを作成し、主なタスクが変わったときに更新します。\",\"pt\":\"Escreve o título de uma sessão a partir de todas as suas mensagens e o atualiza quando a tarefa principal muda, em vez de usar apenas a primeira mensagem.\",\"ru\":\"Составляет заголовок сеанса по всем вашим сообщениям и обновляет его при смене основной задачи, а не только по первому сообщению.\",\"zh\":\"根据你的所有消息生成会话标题,并在主要任务变化时更新,而不是只根据第一条消息生成。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-terminal-bundle\",\"title\":{\"en\":\"Persistent terminals\",\"de\":\"Persistente Terminals\",\"es\":\"Terminales persistentes\",\"fr\":\"Terminaux persistants\",\"ja\":\"永続ターミナル\",\"pt\":\"Terminais persistentes\",\"ru\":\"Постоянные терминалы\",\"zh\":\"持久终端\"},\"description\":{\"en\":\"Gives the agent terminals whose processes keep running in the background between tool calls, so it can start a dev server or REPL and come back later to read output or type input.\",\"de\":\"Stellt dem Agenten Terminals bereit, deren Prozesse zwischen Tool-Aufrufen im Hintergrund weiterlaufen, sodass er einen Entwicklungsserver oder eine REPL starten und später zurückkehren kann, um Ausgaben zu lesen oder Eingaben zu tippen.\",\"es\":\"Proporciona al agente terminales cuyos procesos siguen ejecutándose en segundo plano entre llamadas a herramientas, de modo que puede iniciar un servidor de desarrollo o un REPL y volver más tarde para leer la salida o escribir entradas.\",\"fr\":\"Fournit à l'agent des terminaux dont les processus continuent de s'exécuter en arrière-plan d'un appel d'outil à l'autre, afin qu'il puisse lancer un serveur de développement ou un REPL et revenir plus tard lire la sortie ou saisir des entrées.\",\"ja\":\"エージェントにターミナルを提供します。プロセスはツール呼び出し間もバックグラウンドで実行され続けるため、エージェントは開発サーバーや REPL を起動し、後から出力を読んだり入力したりできます。\",\"pt\":\"Fornece ao agente terminais cujos processos continuam em execução em segundo plano entre chamadas de ferramentas, para que ele possa iniciar um servidor de desenvolvimento ou um REPL e voltar depois para ler a saída ou digitar entradas.\",\"ru\":\"Предоставляет агенту терминалы, процессы которых продолжают работать в фоне между вызовами инструментов, поэтому агент может запустить сервер разработки или REPL и позже вернуться, чтобы прочитать вывод или ввести данные.\",\"zh\":\"为智能体提供终端,进程在多次工具调用之间持续在后台运行,因此它可以启动开发服务器或 REPL,稍后再读取输出或继续输入。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-liveshare\",\"title\":{\"en\":\"LiveShare Session Sharing\",\"de\":\"LiveShare-Sitzungsfreigabe\",\"es\":\"Compartir sesión de LiveShare\",\"fr\":\"Partage de session LiveShare\",\"ja\":\"LiveShare セッション共有\",\"pt\":\"Compartilhamento de sessão do LiveShare\",\"ru\":\"Совместный доступ к сеансу LiveShare\",\"zh\":\"LiveShare 会话分享\"},\"description\":{\"en\":\"Share the current Session with a colleague, who can drive it in a browser, edit files inside the granted workspace when the share allows writes, or branch their own Session from the completed history.\",\"de\":\"Teilt die aktuelle Sitzung mit einer Kollegin oder einem Kollegen, die oder der sie im Browser bedienen, bei erlaubten Schreibzugriffen Dateien im freigegebenen Arbeitsbereich bearbeiten oder aus der abgeschlossenen Historie eine eigene Sitzung abzweigen kann.\",\"es\":\"Comparte la sesión actual con un compañero, que puede dirigirla en un navegador, editar archivos dentro del espacio de trabajo concedido cuando el recurso compartido permite escritura, o crear su propia sesión a partir del historial completado.\",\"fr\":\"Partagez la session en cours avec un collègue, qui peut la piloter dans un navigateur, modifier des fichiers dans l'espace de travail accordé lorsque le partage autorise l'écriture, ou créer sa propre session à partir de l'historique terminé.\",\"ja\":\"現在のセッションを同僚と共有し、ブラウザから操作してもらう、共有が書き込みを許可する場合は付与されたワークスペース内のファイルを編集してもらう、または完了した履歴から自分のセッションを分岐してもらえます。\",\"pt\":\"Compartilhe a sessão atual com um colega, que pode conduzi-la no navegador, editar arquivos dentro do espaço de trabalho concedido quando o compartilhamento permite escrita, ou ramificar a própria sessão a partir do histórico concluído.\",\"ru\":\"Поделитесь текущим сеансом с коллегой: он сможет управлять им в браузере, редактировать файлы в предоставленном рабочем пространстве, если общий доступ разрешает запись, или ответвить собственный сеанс из завершённой истории.\",\"zh\":\"把当前会话分享给同事,对方可在浏览器中驱动该会话、在分享允许写入时修改授权工作区内的文件,或从已完成历史分支出自己的会话。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-session-search\",\"title\":{\"en\":\"Session search\",\"de\":\"Sitzungssuche\",\"es\":\"búsqueda de sesión\",\"fr\":\"Recherche de sessions\",\"ja\":\"セッション検索\",\"pt\":\"Pesquisa de sessão\",\"ru\":\"Поиск сеанса\",\"zh\":\"会话搜索\"},\"description\":{\"en\":\"Ask about earlier work, such as “How did we fix the pool leak last week?”, and the agent searches your earlier sessions in the same workspace to answer.\",\"de\":\"Fragen Sie nach früherer Arbeit, etwa „Wie haben wir letzte Woche das Pool-Leck behoben?“, und der Agent durchsucht Ihre früheren Sitzungen aus demselben Arbeitsverzeichnis, um zu antworten.\",\"es\":\"Pregunte por trabajo anterior, como “¿Cómo arreglamos la fuga del pool la semana pasada?”, y el agente busca en sus sesiones anteriores del mismo directorio de trabajo para responder.\",\"fr\":\"Posez une question sur un travail antérieur, par exemple « Comment avons-nous corrigé la fuite du pool la semaine dernière ? », et l'agent recherche dans vos sessions antérieures du même répertoire de travail pour répondre.\",\"ja\":\"「先週プールのリークをどう直した?」のように以前の作業について尋ねると、エージェントは同じ作業ディレクトリの過去のセッションを検索して回答します。\",\"pt\":\"Pergunte sobre trabalhos anteriores, como “Como corrigimos o vazamento do pool na semana passada?”, e o agente pesquisa suas sessões anteriores do mesmo diretório de trabalho para responder.\",\"ru\":\"Спросите о прошлой работе, например «Как мы исправили утечку в пуле на прошлой неделе?», и агент выполнит поиск по вашим прошлым сеансам из того же рабочего каталога, чтобы ответить.\",\"zh\":\"询问以往的工作,例如“上周我们是怎么修好连接池泄漏的?”,智能体会搜索同一工作区的历史会话来回答。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-tool-worktree\",\"title\":{\"en\":\"Git worktrees\",\"de\":\"Git-Arbeitsbäume\",\"es\":\"árboles de trabajo de git\",\"fr\":\"Arbres de travail Git\",\"ja\":\"Git ワークツリー\",\"pt\":\"Árvores de trabalho Git\",\"ru\":\"Рабочие деревья Git\",\"zh\":\"Git 工作树\"},\"description\":{\"en\":\"Ask for work on a new branch, and the agent creates a separate Git worktree and continues there, leaving your current checkout as it is.\",\"de\":\"Bitten Sie um Arbeit auf einem neuen Branch, und der Agent erstellt einen separaten Git-Worktree und arbeitet dort weiter, während Ihr aktueller Checkout unverändert bleibt.\",\"es\":\"Pida trabajar en una rama nueva, y el agente crea un worktree de Git independiente y continúa allí, dejando su checkout actual tal como está.\",\"fr\":\"Demandez à travailler sur une nouvelle branche, et l'agent crée un worktree Git distinct et y poursuit le travail, en laissant votre copie de travail actuelle telle quelle.\",\"ja\":\"新しいブランチでの作業を依頼すると、エージェントは別の Git ワークツリーを作成してそこで作業を続け、現在のチェックアウトはそのまま残します。\",\"pt\":\"Peça para trabalhar em um novo branch, e o agente cria um worktree do Git separado e continua lá, deixando seu checkout atual como está.\",\"ru\":\"Попросите поработать в новой ветке, и агент создаст отдельное рабочее дерево Git и продолжит работу там, оставив вашу текущую рабочую копию как есть.\",\"zh\":\"要求在新分支上工作时,智能体会创建单独的 Git 工作树并在其中继续,你当前的工作树保持原样。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-plugin-market-bundle\",\"title\":{\"en\":\"Custom plugin indexes\",\"de\":\"Benutzerdefinierte Plugin-Indizes\",\"es\":\"Índices de complementos personalizados\",\"fr\":\"Index de plugins personnalisés\",\"ja\":\"カスタムプラグインインデックス\",\"pt\":\"Índices de plug-ins personalizados\",\"ru\":\"Пользовательские индексы плагинов\",\"zh\":\"自定义插件索引\"},\"description\":{\"en\":\"Adds a Discover tab to Plugins, where you browse and install plugins from plugin indexes you add.\",\"de\":\"Fügt unter „Plugins“ den Tab „Entdecken“ hinzu, in dem Sie Plugins aus von Ihnen hinzugefügten Plugin-Indizes durchsuchen und installieren.\",\"es\":\"Añade la pestaña “Descubrir” a “Complementos”, donde puede explorar e instalar complementos de los índices de complementos que agregue.\",\"fr\":\"Ajoute à « Plugins » un onglet « Découvrez » où vous parcourez et installez des plugins provenant des index de plugins que vous ajoutez.\",\"ja\":\"「プラグイン」に「見つける」タブを追加し、追加したプラグインインデックスからプラグインを閲覧・インストールできるようにします。\",\"pt\":\"Adiciona a guia “Descubra” a “Plug-ins”, onde você navega e instala plug-ins dos índices de plug-ins que adiciona.\",\"ru\":\"Добавляет в «Плагины» вкладку «Откройте для себя», где можно просматривать и устанавливать плагины из добавленных вами индексов плагинов.\",\"zh\":\"在插件页添加“发现”标签页,从你添加的插件索引中浏览和安装插件。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-forge-bundle\",\"title\":{\"en\":\"Change requests & worktrees\",\"de\":\"Änderungsanfragen und Arbeitsbäume\",\"es\":\"Solicitudes de cambio y árboles de trabajo\",\"fr\":\"Demandes de modification et arbres de travail\",\"ja\":\"変更リクエストとワークツリー\",\"pt\":\"Solicitações de alteração e árvores de trabalho\",\"ru\":\"Запросы на изменение и рабочие деревья\",\"zh\":\"变更请求与工作树\"},\"description\":{\"en\":\"Track each Session's change requests with their checks and reviews, and start new Sessions in a Git worktree; uses the gh CLI for GitHub.\",\"de\":\"Verfolgen Sie die Änderungsanfragen jeder Sitzung mit ihren Prüfungen und Reviews und starten Sie neue Sitzungen in einem Git-Arbeitsbaum; nutzt die gh CLI für GitHub.\",\"es\":\"Siga las solicitudes de cambio de cada sesión con sus comprobaciones y revisiones, e inicie nuevas sesiones en un árbol de trabajo de Git; usa la CLI gh para GitHub.\",\"fr\":\"Suivez les demandes de modification de chaque session avec leurs vérifications et revues, et démarrez de nouvelles sessions dans un arbre de travail Git ; utilise la CLI gh pour GitHub.\",\"ja\":\"各セッションの変更リクエストとそのチェックやレビューを追跡し、新しいセッションを Git ワークツリーで開始できます。GitHub には gh CLI を使用します。\",\"pt\":\"Acompanhe as solicitações de alteração de cada sessão com suas verificações e revisões e inicie novas sessões em uma árvore de trabalho Git; usa a CLI gh para o GitHub.\",\"ru\":\"Отслеживайте запросы на изменение каждого сеанса вместе с их проверками и ревью и начинайте новые сеансы в рабочем дереве Git; для GitHub используется gh CLI.\",\"zh\":\"跟踪每个会话的变更请求及其检查与评审,新会话也可以在 Git 工作树中开始;GitHub 通过 gh 命令行访问。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-subagent-claude-code\",\"title\":{\"de\":\"Claude Code-Subagent\",\"en\":\"Claude Code subagent\",\"es\":\"Subagente Claude Code\",\"fr\":\"Sous-agent Claude Code\",\"ja\":\"Claude Code サブエージェント\",\"pt\":\"Claude Code subagente\",\"ru\":\"Субагент Claude Code\",\"zh\":\"Claude Code 子智能体\"},\"description\":{\"de\":\"Delegieren Sie eine Aufgabe an Claude Code, indem Sie dessen native Authentifizierung und Einstellungen verwenden.\",\"en\":\"Delegate one task to Claude Code using its native authentication and settings.\",\"es\":\"Delegue una tarea a Claude Code utilizando su autenticación y configuración nativas.\",\"fr\":\"Déléguez une tâche à Claude Code à l’aide de son authentification et de ses paramètres natifs.\",\"ja\":\"Claude Code のネイティブの認証と設定を使用して、単独のタスクを委派します。\",\"pt\":\"Delegue uma tarefa a Claude Code usando sua autenticação e configurações nativas.\",\"ru\":\"Делегируйте одну задачу Claude Code, используя его встроенную аутентификацию и настройки.\",\"zh\":\"使用 Claude Code 原生认证和设置委派单个任务。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-subagent-codex\",\"title\":{\"de\":\"Codex-Subagent\",\"en\":\"Codex subagent\",\"es\":\"Subagente Codex\",\"fr\":\"Sous-agent Codex\",\"ja\":\"Codex サブエージェント\",\"pt\":\"Codex subagente\",\"ru\":\"Субагент Codex\",\"zh\":\"Codex 子智能体\"},\"description\":{\"de\":\"Delegieren Sie eine Aufgabe an Codex, indem Sie dessen native Authentifizierung und Einstellungen verwenden.\",\"en\":\"Delegate one task to Codex using its native authentication and settings.\",\"es\":\"Delegue una tarea a Codex utilizando su autenticación y configuración nativas.\",\"fr\":\"Déléguez une tâche à Codex à l’aide de son authentification et de ses paramètres natifs.\",\"ja\":\"Codex のネイティブの認証と設定を使用して、単独のタスクを委派します。\",\"pt\":\"Delegue uma tarefa a Codex usando sua autenticação e configurações nativas.\",\"ru\":\"Делегируйте одну задачу Codex, используя его встроенную аутентификацию и настройки.\",\"zh\":\"使用 Codex 原生认证和设置委派单个任务。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-cua-bundle\",\"title\":{\"de\":\"Computernutzung\",\"en\":\"Computer use\",\"es\":\"Uso de la computadora\",\"fr\":\"Utilisation de l'ordinateur\",\"ja\":\"Computer Use\",\"pt\":\"Uso do computador\",\"ru\":\"Использование компьютера\",\"zh\":\"Computer Use\"},\"description\":{\"de\":\"Unterstützt derzeit macOS; Die Windows-Unterstützung befindet sich in der Entwicklung. Lädt die Computernutzung für bestehende und neue PTC-Sitzungen. Wechseln Sie in den PTC-Modus und erteilen Sie die Berechtigungen für Barrierefreiheit und Bildschirmaufzeichnung, um ihn zu verwenden.\",\"en\":\"Currently supports macOS; Windows support is in development. Loads computer use for existing and new PTC sessions. Switch to PTC mode and grant Accessibility and Screen Recording permissions to use it.\",\"es\":\"Actualmente es compatible con macOS; El soporte para Windows está en desarrollo. Carga el uso de la computadora para sesiones PTC nuevas y existentes. Cambie al modo PTC y otorgue permisos de Accesibilidad y Grabación de pantalla para usarlo.\",\"fr\":\"Prend actuellement en charge macOS ; La prise en charge de Windows est en cours de développement. Charge l'utilisation de l'ordinateur pour les sessions PTC existantes et nouvelles. Passez en mode PTC et accordez les autorisations d’accessibilité et d’enregistrement d’écran pour l’utiliser.\",\"ja\":\"現在は macOS のみ対応し、Windows 対応は開発中です。既存および新規の PTC セッションに Computer Use を読み込みます。PTC モードに切り替え、アクセシビリティと画面収録の権限を許可して使用してください。\",\"pt\":\"Atualmente suporta macOS; O suporte Windows está em desenvolvimento. Carrega o uso do computador para sessões PTC novas e existentes. Mude para o modo PTC e conceda permissões de acessibilidade e gravação de tela para usá-lo.\",\"ru\":\"В настоящее время поддерживается macOS; Поддержка Windows находится в разработке. Загружает использование компьютера для существующих и новых сеансов PTC. Переключитесь в режим PTC и предоставьте разрешения на доступность и запись экрана для его использования.\",\"zh\":\"目前仅支持 macOS,Windows 支持正在开发中。为已有及新建 PTC 会话加载 Computer Use。请切换到 PTC 模式来使用,并授予辅助功能和屏幕录制权限。\"},\"enabled\":false}]\n\n"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[16],"surfaceOp":"append"}
+{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_creation_skill"},"toolCallId":"call_creation_skill","content":[{"type":"text","text":"\n\nResources for this skill are managed by provider \"dsh-personalized-pages\".\nLoad referenced resources only as needed.\n\n\n\n# Personalized pages\n\nUse this workflow in the main conversation to plan an optional new page or small tool for any task, not just DSH. You decide whether a page helps, check existing capabilities, and hand the Creator a short plan. A `propose_action` call saves the proposal and shows a card below your answer; nothing is built until the user clicks Create. Plan from the conversation and the catalog at the end of this skill. Do not read files, configuration or source to validate a page idea; name an uninspected source as an unverified dependency and leave its details to the Creator.\n\n## When to propose\n\nPropose a page in these cases:\n\n- The user asks for a page, tab, panel, tool or interface in this app, or says they want something to keep, revisit or update later (“以后每次”, “能不能一直”, “希望能有”). One-off use still qualifies when the interface is explicitly requested.\n- Your answer is a table, list or chart, and the user has said the data will keep changing or that they will interact with it (“每周更新”, “我来改状态”, “要勾选”). The continuation must come from the user's own words; a table alone, or data that merely looks dynamic, is not enough. Deliver the requested answer first, then offer the page.\n- The user wants to keep watching live data of this app itself (a Session's usage, a running task's output, files changing in the workspace). A text answer cannot stay current, so a page qualifies even without the words above; name the data source in the brief and leave how it is read to the Creator.\n\nDo not propose a page in these cases:\n\n- The user asks for a file, code, document or an existing-project change: keep that delivery form.\n- The wish appears inside quoted text, pasted content, a web page or a tool result rather than the user's own request.\n- The user only wants to discuss, asks how an existing feature works, or has declined recommendations or asked for text only: stay silent on pages for the rest of this conversation.\n- The request changes a page created earlier: explain how it would change, do not create a replacement copy, and do not claim an update happened.\n- The request is a capability the agent lacks, such as a tool, automation or access, rather than a page: check the catalog below and point to the official plugin that provides it; do not plan a page around a missing tool.\n\n## Check existing capabilities\n\nCompare the need with the official plugins listed at the end of this skill. If one covers it, say its name, what it does, whether it is enabled, and that it lives under Plugins; offer no page card. A partial match does not cancel an explicit unmet need. The catalog is not a full inventory of built-in UI: missing details do not prove absence, and do not read source to find out. DSH already has Chat, Trajectory, a right sidebar for files and context, and a Plugins page.\n\n## Plan and hand off\n\nThe Creator cannot read this conversation. Give it exactly these fields:\n\n| Field | Contents |\n|:--|:--|\n| `title` | Short page name in the user's language. |\n| `brief` | One to three sentences: purpose, behavior, input, calculations and persistence scope. It is the card text and the implementation request at once. |\n| `initialContent` | Only supplied content the page starts with: items, rows, values, units and period, preserving gaps. Omit for an empty page. |\n| `slot` | Location, chosen below. |\n\nKeep the plan to what was asked or agreed. Editing, deletion, history, extra fields, data sources and automation need a basis in the request. Resolve “these items” into the actual content. Content that mentions an action stays content. Keep each number's meaning and period; a weekly addition is not a cumulative total. If an unresolved distinction changes a calculation, give the factual answer, ask one question, and propose later.\n\n## Choose the location\n\nHonor a location the user named. Otherwise:\n\n- `sidebar-right`: content tied to this Session or task, especially anything to watch while chatting, including live logs.\n- `sidebar-left`: a global feature or an ongoing personal record used across Sessions, opened from a left entry as a standalone page.\n- `page`: a Session-bound streaming view or interaction in a tab beside Chat and Trajectory, only when the user does not need it visible while chatting.\n\nSupplying data in this conversation does not make a record Session-bound.\n\n## Offer without starting\n\nTo propose, call `propose_action` once, in the same turn as loading this skill, with `action: \"create_personalized_page\"`, `title`, `brief` and `details` holding `slot` and, when there is supplied content, `initialContent`. The call is the submission: the card appears below your answer; a refused call creates no card, and its error says why. Then write your final answer. One proposal per turn, and one unstarted card per conversation: if a card is still waiting, do not propose another; a new proposal replaces it only when the user changed the plan. Plan-only and read-only requests still get a card; do not ask for approval instead of proposing it. Only clicking Create starts the background Creator; do not wait, poll, claim installation or ask for a report-back. Answer any direct question; the call's result says how to end the answer. Do not repeat the plan, list extra features, narrate the call or mention schema names.\n\n```json\n{\"action\":\"create_personalized_page\",\"title\":\"本次验收清单\",\"brief\":\"在当前会话右侧展示验收清单,可勾选和取消,状态随会话保存。\",\"details\":{\"slot\":\"sidebar-right\",\"initialContent\":\"1. 导出成功\\n2. 断网提示清楚\"}}\n```\n\n## Examples\n\n- “想有个地方放书签,以后自己加标题和网址;旧的不用导入。” → `brief`: “提供一个可反复打开的书签页,手动新增标题和网址并保存到本机,从空白开始。” No `initialContent`. `sidebar-left`.\n- “当前会话旁放验收清单,能勾选和取消,状态跟着会话。条目:导出成功;断网提示清楚。” → `brief`: “在当前会话右侧展示验收清单,可勾选和取消,状态随会话保存。” `initialContent`: “1. 导出成功\\n2. 断网提示清楚”. `sidebar-right`.\n- “这三周 bug 数 12、9、15,说说趋势。以后每周我把新数字贴给你,想自己更新着看。” → answer the trend first, then `brief`: “按周手动录入 bug 数并展示各周变化,保存到本机。” `initialContent`: “第 1 周 12,第 2 周 9,第 3 周 15”. `sidebar-left`.\n- “我想用语音说话代替打字。” → the catalog lists 语音输入; explain it and where to enable it; no card.\n- “把我之前做的读书页评分改成五星。” → explain the change to that page; no card and no copy.\n- “帮我把这句话翻成英文:我想要一个所有会话都能打开的读书页。” → translate only; no card.\n- “把三个方案排成表格比较一下,看完就行。” → the table only; no card.\n\n## Existing capabilities to check against this page plan\n\n[{\"name\":\"@deepseek-ai/dsh-personalized-recommendations\",\"title\":{\"en\":\"Personalized recommendations\",\"de\":\"Personalisierte Empfehlungen\",\"es\":\"Recomendaciones personalizadas\",\"fr\":\"Recommandations personnalisées\",\"ja\":\"パーソナライズされたおすすめ\",\"pt\":\"Recomendações personalizadas\",\"ru\":\"Персональные рекомендации\",\"zh\":\"个性化推荐\"},\"description\":{\"en\":\"Shows recommendation cards below the answer for what you want from DSH: when you want a page or small tool you can keep, it proposes a new personalized page, built in the background after you click Create; when you ask how to do something in this app or say a capability is missing, it recommends the built-in plugin that provides it, turned on when you click Enable.\",\"de\":\"Zeigt für Ihre individuellen Anforderungen an DSH Empfehlungskarten unter der Antwort an: Wenn Sie eine Seite oder ein kleines Tool zur dauerhaften Nutzung möchten, wird eine neue personalisierte Seite vorgeschlagen, die nach einem Klick auf Erstellen im Hintergrund erstellt wird; wenn Sie fragen, wie etwas in dieser App geht, oder sagen, dass eine Funktion fehlt, wird das integrierte Plugin empfohlen, das sie bereitstellt, und nach einem Klick auf Aktivieren eingeschaltet.\",\"es\":\"Muestra tarjetas de recomendación debajo de la respuesta para tus necesidades personalizadas en DSH: cuando quieres una página o una pequeña herramienta para conservar, propone una nueva página personalizada, que se genera en segundo plano al hacer clic en Crear; cuando preguntas cómo hacer algo en esta aplicación o dices que falta una función, recomienda el complemento integrado que la ofrece, que se activa al hacer clic en Habilitar.\",\"fr\":\"Affiche des cartes de recommandation sous la réponse pour vos besoins personnalisés dans DSH : lorsque vous voulez une page ou un petit outil à conserver, propose une nouvelle page personnalisée, générée en arrière-plan après un clic sur Créer ; lorsque vous demandez comment faire quelque chose dans cette application ou signalez qu’une fonctionnalité manque, recommande le plugin intégré qui la fournit, activé lorsque vous cliquez sur Activer.\",\"ja\":\"DSH に対するあなた個人のニーズに合わせて、回答の下におすすめカードを表示します。長く使えるページや小さなツールが欲しいときは新しいパーソナルページを提案し、「作成」をクリックするとバックグラウンドで生成します。このアプリで何かをする方法を尋ねたときや機能が足りないと言ったときは、それを提供する内蔵プラグインを推薦し、「有効にする」をクリックすると有効になります。\",\"pt\":\"Mostra cartões de recomendação abaixo da resposta para suas necessidades personalizadas no DSH: quando você quer uma página ou uma pequena ferramenta para manter, propõe uma nova página personalizada, gerada em segundo plano depois que você clica em Criar; quando você pergunta como fazer algo neste aplicativo ou diz que falta um recurso, recomenda o plug-in integrado que o oferece, ativado quando você clica em Ativar.\",\"ru\":\"Показывает карточки рекомендаций под ответом с учетом ваших индивидуальных потребностей в DSH: когда вам нужна страница или небольшой инструмент для постоянного использования, предлагает новую персональную страницу, которая создается в фоне после нажатия «Создать»; когда вы спрашиваете, как что-то сделать в этом приложении, или говорите, что не хватает какой-то возможности, рекомендует встроенный плагин, который ее предоставляет, и включает его после нажатия «Включить».\",\"zh\":\"针对你对 DSH 的个性化需求,在回答下方展示推荐卡片:想要能长期使用的页面或小工具时,提议新增个性化页面,点击创建后在后台生成;问到本应用怎么做某件事或缺少某项能力时,推荐对应的内置插件,点击启用后开启。\"},\"enabled\":true},{\"name\":\"@deepseek-ai/dsh-experimental-agent-team-profile\",\"title\":{\"en\":\"Agent teams\",\"de\":\"Agententeams\",\"es\":\"Equipos de agentes\",\"fr\":\"Équipes d'agents\",\"ja\":\"エージェントチーム\",\"pt\":\"Equipes de agentes\",\"ru\":\"Команды агентов\",\"zh\":\"智能体团队\"},\"description\":{\"en\":\"Lets the agent you talk to split a job among named teammates, track it on a shared task board, and report back with their results.\",\"de\":\"Ermöglicht dem Agenten, mit dem Sie sprechen, eine Aufgabe auf benannte Teammitglieder aufzuteilen, sie auf einem gemeinsamen Aufgabenboard zu verfolgen und Ihnen mit deren Ergebnissen zu berichten.\",\"es\":\"Permite que el agente con el que habla reparta un trabajo entre compañeros con nombre, lo siga en un tablero de tareas compartido y le informe con sus resultados.\",\"fr\":\"Permet à l'agent avec lequel vous parlez de répartir un travail entre des coéquipiers nommés, de le suivre sur un tableau de tâches partagé et de vous rendre compte de leurs résultats.\",\"ja\":\"対話しているエージェントが、仕事を名前付きのチームメイトに分担させ、共有タスクボードで進捗を追跡し、チームメイトの結果をまとめて報告します。\",\"pt\":\"Permite que o agente com quem você conversa divida um trabalho entre colegas de equipe nomeados, acompanhe-o em um quadro de tarefas compartilhado e informe você com os resultados deles.\",\"ru\":\"Позволяет агенту, с которым вы общаетесь, распределить работу между именованными участниками команды, отслеживать её на общей доске задач и отчитываться перед вами об их результатах.\",\"zh\":\"让与你对话的智能体把工作分给有名字的队友,在共享任务看板上跟踪进度,并汇总队友的结果向你汇报。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-inspector-profile\",\"title\":{\"en\":\"Developer tools\",\"de\":\"Entwicklertools\",\"es\":\"Herramientas de desarrollador\",\"fr\":\"Outils de développement\",\"ja\":\"開発者ツール\",\"pt\":\"Ferramentas de desenvolvedor\",\"ru\":\"Инструменты разработчика\",\"zh\":\"开发者工具\"},\"description\":{\"en\":\"For troubleshooting: view what DSH recorded for a session in Session log, inspect per-turn and per-step statistics in the Statistics tab, and debug the DSH backend in Chrome DevTools.\",\"de\":\"Zur Fehlersuche: Sehen Sie in „Sitzungsprotokoll“, was DSH für eine Sitzung aufgezeichnet hat, prüfen Sie im Tab „Statistik“ Kontext, Dauer, Cache und Werkzeugkosten pro Runde und Schritt und debuggen Sie das DSH-Backend in Chrome DevTools.\",\"es\":\"Para solucionar problemas: vea en «Registro de sesión» lo que DSH registró de una sesión, consulte el contexto, los tiempos, la caché y el coste de herramientas por turno y paso en la pestaña «Estadísticas», y depure el backend de DSH en Chrome DevTools.\",\"fr\":\"Pour le dépannage : consultez dans « Journal de session » ce que DSH a enregistré pour une session, examinez le contexte, les durées, le cache et le coût des outils par tour et étape dans l’onglet « Statistiques », et déboguez le backend de DSH dans Chrome DevTools.\",\"ja\":\"トラブルシューティング用です。「セッションログ」で DSH がセッションについて記録した内容を確認し、「統計」タブでターン/ステップごとのコンテキスト、時間、キャッシュ、ツールコストを確認し、Chrome DevTools で DSH バックエンドをデバッグできます。\",\"pt\":\"Para solução de problemas: veja em «Registro da sessão» o que o DSH registrou de uma sessão, consulte contexto, tempos, cache e custo de ferramentas por turno e etapa na aba «Estatísticas» e depure o backend do DSH no Chrome DevTools.\",\"ru\":\"Для диагностики: просматривайте в «Журнале сеанса», что DSH записал для сеанса, смотрите контекст, время, кэш и стоимость инструментов по ходам и шагам на вкладке «Статистика» и отлаживайте бэкенд DSH в Chrome DevTools.\",\"zh\":\"用于排查问题:在「会话数据诊断」中查看 DSH 为会话记录的内容,在「统计」页签查看每轮/每步的上下文、耗时、缓存和工具成本,并在 Chrome DevTools 中调试 DSH 后端。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-voice-input-bundle\",\"title\":{\"en\":\"Voice input\",\"de\":\"Spracheingabe\",\"es\":\"Entrada de voz\",\"fr\":\"Saisie vocale\",\"ja\":\"音声入力\",\"pt\":\"Entrada de voz\",\"ru\":\"Голосовой ввод\",\"zh\":\"语音输入\"},\"description\":{\"en\":\"Transcribe recordings locally with SenseVoice; first use requires installing dependencies.\",\"de\":\"Transkribieren Sie Aufnahmen lokal mit SenseVoice; Für die erste Verwendung müssen Abhängigkeiten installiert werden.\",\"es\":\"Transcribe grabaciones localmente con SenseVoice; El primer uso requiere instalar dependencias.\",\"fr\":\"Transcrivez les enregistrements localement avec SenseVoice ; la première utilisation nécessite l'installation de dépendances.\",\"ja\":\"ローカルの SenseVoice で録音を文字に起こします。初回利用時には依存関係のインストールが必要です。\",\"pt\":\"Transcreva gravações localmente com SenseVoice; o primeiro uso requer a instalação de dependências.\",\"ru\":\"Транскрибируйте записи локально с помощью SenseVoice; при первом использовании требуется установка зависимостей.\",\"zh\":\"在本机使用 SenseVoice 转写录音,首次使用需安装依赖。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-auto-review\",\"title\":{\"en\":\"Auto authorization review\",\"de\":\"Automatische Autorisierungsüberprüfung\",\"es\":\"Revisión de autorización automática\",\"fr\":\"Examen des autorisations automatiques\",\"ja\":\"自動認可レビュー\",\"pt\":\"Revisão de autorização automática\",\"ru\":\"Проверка автоматической авторизации\",\"zh\":\"自动授权审查\"},\"description\":{\"en\":\"Adds an Auto review access mode: before each tool call, a model checks it against what you asked for, runs allowed calls at once, and holds denied calls for your approval.\",\"de\":\"Fügt den Zugriffsmodus „Auto review“ hinzu: Vor jedem Tool-Aufruf prüft ein Modell den Aufruf anhand Ihrer Anforderung; zugelassene Aufrufe laufen sofort, abgelehnte Aufrufe warten auf Ihre Genehmigung.\",\"es\":\"Añade el modo de acceso “Auto review”: antes de cada llamada a una herramienta, un modelo comprueba la llamada frente a lo que usted pidió; las llamadas permitidas se ejecutan de inmediato y las denegadas esperan su aprobación.\",\"fr\":\"Ajoute le mode d'accès « Auto review » : avant chaque appel d'outil, un modèle vérifie l'appel par rapport à ce que vous avez demandé ; les appels autorisés s'exécutent immédiatement et les appels refusés attendent votre approbation.\",\"ja\":\"「自動認可レビュー」アクセスモードを追加します。各ツール呼び出しの前に、モデルがその呼び出しをあなたの依頼内容と照らし合わせて確認し、許可された呼び出しは即座に実行され、拒否された呼び出しはあなたの承認を待ちます。\",\"pt\":\"Adiciona o modo de acesso “Auto review”: antes de cada chamada de ferramenta, um modelo verifica a chamada em relação ao que você pediu; as chamadas permitidas são executadas imediatamente e as negadas aguardam sua aprovação.\",\"ru\":\"Добавляет режим доступа «Auto review»: перед каждым вызовом инструмента модель сверяет вызов с вашей просьбой; разрешённые вызовы выполняются сразу, а отклонённые ждут вашего одобрения.\",\"zh\":\"提供“自动审查”访问模式:每次工具调用前,由模型对照你的要求检查,获准的调用立即运行,被拒绝的调用等你审批。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-cot-translation-bundle\",\"title\":{\"en\":\"Machine translation of reasoning\",\"de\":\"Maschinelle Übersetzung der Argumentation\",\"es\":\"Traducción automática de razonamiento\",\"fr\":\"Traduction automatique du raisonnement\",\"ja\":\"思考内容の機械翻訳\",\"pt\":\"Tradução automática de raciocínio\",\"ru\":\"Машинный перевод рассуждений\",\"zh\":\"思考过程机器翻译\"},\"description\":{\"en\":\"Translates expanded Think rows into your chosen language as the agent writes them, and View original switches back.\",\"de\":\"Übersetzt aufgeklappte „Denken Sie nach“-Zeilen, während der Agent sie schreibt, in die von Ihnen gewählte Sprache, und „Original ansehen“ wechselt zurück.\",\"es\":\"Traduce las filas “pensar” expandidas al idioma que elija mientras el agente las escribe, y “Ver original” vuelve al texto original.\",\"fr\":\"Traduit les lignes « Pensez » développées dans la langue de votre choix pendant que l'agent les écrit, et « Voir l'original » permet de revenir au texte d'origine.\",\"ja\":\"エージェントが書き出すのと同時に、展開された「思考」行を選択した言語に翻訳します。「原文を表示」で原文に戻せます。\",\"pt\":\"Traduz as linhas “Pense” expandidas para o idioma que você escolher enquanto o agente as escreve, e “Ver original” volta ao texto original.\",\"ru\":\"Переводит развёрнутые строки «Подумайте» на выбранный вами язык по мере того, как агент их пишет, а «Посмотреть оригинал» возвращает исходный текст.\",\"zh\":\"智能体输出时,把展开的“思考”行翻译成你选择的语言,点击“查看原文”可切换回原文。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-badge-skill-bundle\",\"title\":{\"en\":\"DSH badge skill\",\"de\":\"DSH-Abzeichen-Fertigkeit\",\"es\":\"Habilidad de insignia DSH\",\"fr\":\"Compétence du badge DSH\",\"ja\":\"DSH バッジスキル\",\"pt\":\"DSH habilidade de distintivo\",\"ru\":\"DSH значок навыка\",\"zh\":\"DSH 徽章技能\"},\"description\":{\"en\":\"Let agents add a “powered by dsh” badge to documents, pull requests, and other outputs.\",\"de\":\"Lassen Sie Agenten Dokumente, Pull-Requests und andere Ausgaben mit einem „powered by dsh“-Badge versehen.\",\"es\":\"Permita que los agentes agreguen una insignia \\\"con tecnología de dsh\\\" a documentos, solicitudes de extracción y otros resultados.\",\"fr\":\"Laissez les agents ajouter un badge « propulsé par dsh » aux documents, demandes d'extraction et autres sorties.\",\"ja\":\"エージェントが文書や PR などの成果物に「powered by dsh」バッジを追加できます。\",\"pt\":\"Permita que os agentes adicionem um selo “powered by dsh” a documentos, pull requests e outros resultados.\",\"ru\":\"Позвольте агентам добавлять значок «Powered by dsh» к документам, запросам на включение и другим результатам.\",\"zh\":\"让 Agent 为文档、PR 等产出添加「powered by dsh」徽章。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-ralph-bundle\",\"title\":{\"en\":\"Ralph loops\",\"de\":\"Ralph-Loops\",\"es\":\"Bucles de Ralph\",\"fr\":\"Boucles Ralph\",\"ja\":\"Ralph ループ\",\"pt\":\"Loops de Ralph\",\"ru\":\"Ральф петли\",\"zh\":\"Ralph 循环\"},\"description\":{\"en\":\"Ask for a Ralph loop with a goal, and the agent starts a fresh agent on it round after round until the goal is met, a blocker is reported, or the round limit is reached.\",\"de\":\"Bitten Sie um eine Ralph-Schleife mit einem Ziel, und der Agent startet Runde um Runde einen neuen Agenten darauf, bis das Ziel erreicht ist, ein Hindernis gemeldet wird oder das Rundenlimit erreicht ist.\",\"es\":\"Pida un bucle Ralph con un objetivo, y el agente inicia un agente nuevo sobre él ronda tras ronda hasta que se cumpla el objetivo, se informe de un bloqueo o se alcance el límite de rondas.\",\"fr\":\"Demandez une boucle Ralph avec un objectif, et l'agent lance un nouvel agent dessus, tour après tour, jusqu'à ce que l'objectif soit atteint, qu'un blocage soit signalé ou que la limite de tours soit atteinte.\",\"ja\":\"目標を指定して Ralph ループを依頼すると、エージェントは、目標が達成されるか、阻害要因が報告されるか、ラウンド数の上限に達するまで、ラウンドごとに新しいエージェントを起動してその目標に取り組ませます。\",\"pt\":\"Peça um loop Ralph com um objetivo, e o agente inicia um novo agente nele rodada após rodada até que o objetivo seja atingido, um bloqueio seja informado ou o limite de rodadas seja alcançado.\",\"ru\":\"Попросите запустить цикл Ralph с целью, и агент будет раунд за раундом запускать для неё нового агента, пока цель не будет достигнута, не будет сообщено о препятствии или не будет достигнут лимит раундов.\",\"zh\":\"要求用 Ralph 循环完成一个目标后,智能体会一轮接一轮地启动新的智能体处理它,直到目标达成、报告受阻或达到轮次上限。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-session-titles-bundle\",\"title\":{\"en\":\"Conversation-following titles\",\"de\":\"Konversationsfolgende Titel\",\"es\":\"Títulos que siguen la conversación\",\"fr\":\"Titres de suivi de conversation\",\"ja\":\"会話に追従するタイトル\",\"pt\":\"Títulos que acompanham conversas\",\"ru\":\"Заголовки, следующие за разговором\",\"zh\":\"随对话更新的标题\"},\"description\":{\"en\":\"Writes a session's title from all of your messages and updates it when the main task changes, instead of only from the first message.\",\"de\":\"Erstellt den Titel einer Sitzung aus all Ihren Nachrichten und aktualisiert ihn, wenn sich die Hauptaufgabe ändert, statt ihn nur aus der ersten Nachricht zu bilden.\",\"es\":\"Escribe el título de una sesión a partir de todos sus mensajes y lo actualiza cuando cambia la tarea principal, en lugar de basarse solo en el primer mensaje.\",\"fr\":\"Rédige le titre d'une session à partir de tous vos messages et le met à jour lorsque la tâche principale change, au lieu de se baser uniquement sur le premier message.\",\"ja\":\"最初のメッセージだけでなく、あなたのすべてのメッセージからセッションのタイトルを作成し、主なタスクが変わったときに更新します。\",\"pt\":\"Escreve o título de uma sessão a partir de todas as suas mensagens e o atualiza quando a tarefa principal muda, em vez de usar apenas a primeira mensagem.\",\"ru\":\"Составляет заголовок сеанса по всем вашим сообщениям и обновляет его при смене основной задачи, а не только по первому сообщению.\",\"zh\":\"根据你的所有消息生成会话标题,并在主要任务变化时更新,而不是只根据第一条消息生成。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-terminal-bundle\",\"title\":{\"en\":\"Persistent terminals\",\"de\":\"Persistente Terminals\",\"es\":\"Terminales persistentes\",\"fr\":\"Terminaux persistants\",\"ja\":\"永続ターミナル\",\"pt\":\"Terminais persistentes\",\"ru\":\"Постоянные терминалы\",\"zh\":\"持久终端\"},\"description\":{\"en\":\"Gives the agent terminals whose processes keep running in the background between tool calls, so it can start a dev server or REPL and come back later to read output or type input.\",\"de\":\"Stellt dem Agenten Terminals bereit, deren Prozesse zwischen Tool-Aufrufen im Hintergrund weiterlaufen, sodass er einen Entwicklungsserver oder eine REPL starten und später zurückkehren kann, um Ausgaben zu lesen oder Eingaben zu tippen.\",\"es\":\"Proporciona al agente terminales cuyos procesos siguen ejecutándose en segundo plano entre llamadas a herramientas, de modo que puede iniciar un servidor de desarrollo o un REPL y volver más tarde para leer la salida o escribir entradas.\",\"fr\":\"Fournit à l'agent des terminaux dont les processus continuent de s'exécuter en arrière-plan d'un appel d'outil à l'autre, afin qu'il puisse lancer un serveur de développement ou un REPL et revenir plus tard lire la sortie ou saisir des entrées.\",\"ja\":\"エージェントにターミナルを提供します。プロセスはツール呼び出し間もバックグラウンドで実行され続けるため、エージェントは開発サーバーや REPL を起動し、後から出力を読んだり入力したりできます。\",\"pt\":\"Fornece ao agente terminais cujos processos continuam em execução em segundo plano entre chamadas de ferramentas, para que ele possa iniciar um servidor de desenvolvimento ou um REPL e voltar depois para ler a saída ou digitar entradas.\",\"ru\":\"Предоставляет агенту терминалы, процессы которых продолжают работать в фоне между вызовами инструментов, поэтому агент может запустить сервер разработки или REPL и позже вернуться, чтобы прочитать вывод или ввести данные.\",\"zh\":\"为智能体提供终端,进程在多次工具调用之间持续在后台运行,因此它可以启动开发服务器或 REPL,稍后再读取输出或继续输入。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-liveshare\",\"title\":{\"en\":\"LiveShare Session Sharing\",\"de\":\"LiveShare-Sitzungsfreigabe\",\"es\":\"Compartir sesión de LiveShare\",\"fr\":\"Partage de session LiveShare\",\"ja\":\"LiveShare セッション共有\",\"pt\":\"Compartilhamento de sessão do LiveShare\",\"ru\":\"Совместный доступ к сеансу LiveShare\",\"zh\":\"LiveShare 会话分享\"},\"description\":{\"en\":\"Share the current Session with a colleague, who can drive it in a browser, edit files inside the granted workspace when the share allows writes, or branch their own Session from the completed history.\",\"de\":\"Teilt die aktuelle Sitzung mit einer Kollegin oder einem Kollegen, die oder der sie im Browser bedienen, bei erlaubten Schreibzugriffen Dateien im freigegebenen Arbeitsbereich bearbeiten oder aus der abgeschlossenen Historie eine eigene Sitzung abzweigen kann.\",\"es\":\"Comparte la sesión actual con un compañero, que puede dirigirla en un navegador, editar archivos dentro del espacio de trabajo concedido cuando el recurso compartido permite escritura, o crear su propia sesión a partir del historial completado.\",\"fr\":\"Partagez la session en cours avec un collègue, qui peut la piloter dans un navigateur, modifier des fichiers dans l'espace de travail accordé lorsque le partage autorise l'écriture, ou créer sa propre session à partir de l'historique terminé.\",\"ja\":\"現在のセッションを同僚と共有し、ブラウザから操作してもらう、共有が書き込みを許可する場合は付与されたワークスペース内のファイルを編集してもらう、または完了した履歴から自分のセッションを分岐してもらえます。\",\"pt\":\"Compartilhe a sessão atual com um colega, que pode conduzi-la no navegador, editar arquivos dentro do espaço de trabalho concedido quando o compartilhamento permite escrita, ou ramificar a própria sessão a partir do histórico concluído.\",\"ru\":\"Поделитесь текущим сеансом с коллегой: он сможет управлять им в браузере, редактировать файлы в предоставленном рабочем пространстве, если общий доступ разрешает запись, или ответвить собственный сеанс из завершённой истории.\",\"zh\":\"把当前会话分享给同事,对方可在浏览器中驱动该会话、在分享允许写入时修改授权工作区内的文件,或从已完成历史分支出自己的会话。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-session-search\",\"title\":{\"en\":\"Session search\",\"de\":\"Sitzungssuche\",\"es\":\"búsqueda de sesión\",\"fr\":\"Recherche de sessions\",\"ja\":\"セッション検索\",\"pt\":\"Pesquisa de sessão\",\"ru\":\"Поиск сеанса\",\"zh\":\"会话搜索\"},\"description\":{\"en\":\"Ask about earlier work, such as “How did we fix the pool leak last week?”, and the agent searches your earlier sessions in the same workspace to answer.\",\"de\":\"Fragen Sie nach früherer Arbeit, etwa „Wie haben wir letzte Woche das Pool-Leck behoben?“, und der Agent durchsucht Ihre früheren Sitzungen aus demselben Arbeitsverzeichnis, um zu antworten.\",\"es\":\"Pregunte por trabajo anterior, como “¿Cómo arreglamos la fuga del pool la semana pasada?”, y el agente busca en sus sesiones anteriores del mismo directorio de trabajo para responder.\",\"fr\":\"Posez une question sur un travail antérieur, par exemple « Comment avons-nous corrigé la fuite du pool la semaine dernière ? », et l'agent recherche dans vos sessions antérieures du même répertoire de travail pour répondre.\",\"ja\":\"「先週プールのリークをどう直した?」のように以前の作業について尋ねると、エージェントは同じ作業ディレクトリの過去のセッションを検索して回答します。\",\"pt\":\"Pergunte sobre trabalhos anteriores, como “Como corrigimos o vazamento do pool na semana passada?”, e o agente pesquisa suas sessões anteriores do mesmo diretório de trabalho para responder.\",\"ru\":\"Спросите о прошлой работе, например «Как мы исправили утечку в пуле на прошлой неделе?», и агент выполнит поиск по вашим прошлым сеансам из того же рабочего каталога, чтобы ответить.\",\"zh\":\"询问以往的工作,例如“上周我们是怎么修好连接池泄漏的?”,智能体会搜索同一工作区的历史会话来回答。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-tool-worktree\",\"title\":{\"en\":\"Git worktrees\",\"de\":\"Git-Arbeitsbäume\",\"es\":\"árboles de trabajo de git\",\"fr\":\"Arbres de travail Git\",\"ja\":\"Git ワークツリー\",\"pt\":\"Árvores de trabalho Git\",\"ru\":\"Рабочие деревья Git\",\"zh\":\"Git 工作树\"},\"description\":{\"en\":\"Ask for work on a new branch, and the agent creates a separate Git worktree and continues there, leaving your current checkout as it is.\",\"de\":\"Bitten Sie um Arbeit auf einem neuen Branch, und der Agent erstellt einen separaten Git-Worktree und arbeitet dort weiter, während Ihr aktueller Checkout unverändert bleibt.\",\"es\":\"Pida trabajar en una rama nueva, y el agente crea un worktree de Git independiente y continúa allí, dejando su checkout actual tal como está.\",\"fr\":\"Demandez à travailler sur une nouvelle branche, et l'agent crée un worktree Git distinct et y poursuit le travail, en laissant votre copie de travail actuelle telle quelle.\",\"ja\":\"新しいブランチでの作業を依頼すると、エージェントは別の Git ワークツリーを作成してそこで作業を続け、現在のチェックアウトはそのまま残します。\",\"pt\":\"Peça para trabalhar em um novo branch, e o agente cria um worktree do Git separado e continua lá, deixando seu checkout atual como está.\",\"ru\":\"Попросите поработать в новой ветке, и агент создаст отдельное рабочее дерево Git и продолжит работу там, оставив вашу текущую рабочую копию как есть.\",\"zh\":\"要求在新分支上工作时,智能体会创建单独的 Git 工作树并在其中继续,你当前的工作树保持原样。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-plugin-market-bundle\",\"title\":{\"en\":\"Custom plugin indexes\",\"de\":\"Benutzerdefinierte Plugin-Indizes\",\"es\":\"Índices de complementos personalizados\",\"fr\":\"Index de plugins personnalisés\",\"ja\":\"カスタムプラグインインデックス\",\"pt\":\"Índices de plug-ins personalizados\",\"ru\":\"Пользовательские индексы плагинов\",\"zh\":\"自定义插件索引\"},\"description\":{\"en\":\"Adds a Discover tab to Plugins, where you browse and install plugins from plugin indexes you add.\",\"de\":\"Fügt unter „Plugins“ den Tab „Entdecken“ hinzu, in dem Sie Plugins aus von Ihnen hinzugefügten Plugin-Indizes durchsuchen und installieren.\",\"es\":\"Añade la pestaña “Descubrir” a “Complementos”, donde puede explorar e instalar complementos de los índices de complementos que agregue.\",\"fr\":\"Ajoute à « Plugins » un onglet « Découvrez » où vous parcourez et installez des plugins provenant des index de plugins que vous ajoutez.\",\"ja\":\"「プラグイン」に「見つける」タブを追加し、追加したプラグインインデックスからプラグインを閲覧・インストールできるようにします。\",\"pt\":\"Adiciona a guia “Descubra” a “Plug-ins”, onde você navega e instala plug-ins dos índices de plug-ins que adiciona.\",\"ru\":\"Добавляет в «Плагины» вкладку «Откройте для себя», где можно просматривать и устанавливать плагины из добавленных вами индексов плагинов.\",\"zh\":\"在插件页添加“发现”标签页,从你添加的插件索引中浏览和安装插件。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-experimental-forge-bundle\",\"title\":{\"en\":\"Change requests & worktrees\",\"de\":\"Änderungsanfragen und Arbeitsbäume\",\"es\":\"Solicitudes de cambio y árboles de trabajo\",\"fr\":\"Demandes de modification et arbres de travail\",\"ja\":\"変更リクエストとワークツリー\",\"pt\":\"Solicitações de alteração e árvores de trabalho\",\"ru\":\"Запросы на изменение и рабочие деревья\",\"zh\":\"变更请求与工作树\"},\"description\":{\"en\":\"Keep linked GitHub pull requests beside your conversation: follow checks and reviews, inspect diffs, and send feedback to the agent. Review local changes and use a separate worktree to isolate each task. GitHub features require the gh CLI installed and signed in on the host.\",\"de\":\"Verknüpfte GitHub-Pull-Requests neben der Unterhaltung verfolgen: Prüfungen und Reviews ansehen, Code vergleichen und Feedback an den Agenten senden. Lokale Änderungen prüfen und Aufgaben mit separaten Arbeitsbäumen isolieren. GitHub-Funktionen erfordern eine installierte gh-CLI und eine Anmeldung auf dem Host.\",\"es\":\"Sigue los pull requests de GitHub vinculados a la conversación: consulta comprobaciones y revisiones, compara código y envía comentarios al agente. Revisa cambios locales y aísla cada tarea en un árbol de trabajo separado. Las funciones de GitHub requieren instalar la CLI gh e iniciar sesión en el equipo anfitrión.\",\"fr\":\"Suivez les pull requests GitHub liées à votre conversation : consultez les vérifications et les revues, comparez le code et transmettez vos remarques à l’agent. Examinez les modifications locales et isolez chaque tâche dans un arbre de travail séparé. Les fonctions GitHub nécessitent la CLI gh installée et une connexion sur l’hôte.\",\"ja\":\"会話のサイドバーで関連付けられた GitHub PR をまとめて確認できます。チェックやレビューの状況、コードの差分を確認し、修正案をエージェントに渡せます。ローカルの変更確認や、独立したワークツリーによるタスクの分離にも対応します。GitHub 機能にはホストでの gh CLI のインストールとログインが必要です。\",\"pt\":\"Acompanhe os pull requests do GitHub vinculados à conversa: consulte verificações e revisões, compare código e envie comentários ao agente. Revise alterações locais e isole cada tarefa em uma árvore de trabalho separada. Os recursos do GitHub exigem a CLI gh instalada e uma sessão iniciada no host.\",\"ru\":\"Следите за связанными с беседой pull request GitHub: проверками, рецензиями и различиями в коде, а затем передавайте замечания агенту. Просматривайте локальные изменения и изолируйте задачи в отдельных рабочих деревьях. Для функций GitHub требуется установить CLI gh и войти в аккаунт на хосте.\",\"zh\":\"在会话侧栏集中跟踪关联的 GitHub PR:查看检查状态、评审意见与代码差异,并把修改建议交给智能体继续处理。也可查看本地改动,用独立工作树隔离任务。GitHub 功能需要本机安装 gh 并登录。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-subagent-claude-code\",\"title\":{\"de\":\"Claude Code-Subagent\",\"en\":\"Claude Code subagent\",\"es\":\"Subagente Claude Code\",\"fr\":\"Sous-agent Claude Code\",\"ja\":\"Claude Code サブエージェント\",\"pt\":\"Claude Code subagente\",\"ru\":\"Субагент Claude Code\",\"zh\":\"Claude Code 子智能体\"},\"description\":{\"de\":\"Delegieren Sie eine Aufgabe an Claude Code, indem Sie dessen native Authentifizierung und Einstellungen verwenden.\",\"en\":\"Delegate one task to Claude Code using its native authentication and settings.\",\"es\":\"Delegue una tarea a Claude Code utilizando su autenticación y configuración nativas.\",\"fr\":\"Déléguez une tâche à Claude Code à l’aide de son authentification et de ses paramètres natifs.\",\"ja\":\"Claude Code のネイティブの認証と設定を使用して、単独のタスクを委派します。\",\"pt\":\"Delegue uma tarefa a Claude Code usando sua autenticação e configurações nativas.\",\"ru\":\"Делегируйте одну задачу Claude Code, используя его встроенную аутентификацию и настройки.\",\"zh\":\"使用 Claude Code 原生认证和设置委派单个任务。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-subagent-codex\",\"title\":{\"de\":\"Codex-Subagent\",\"en\":\"Codex subagent\",\"es\":\"Subagente Codex\",\"fr\":\"Sous-agent Codex\",\"ja\":\"Codex サブエージェント\",\"pt\":\"Codex subagente\",\"ru\":\"Субагент Codex\",\"zh\":\"Codex 子智能体\"},\"description\":{\"de\":\"Delegieren Sie eine Aufgabe an Codex, indem Sie dessen native Authentifizierung und Einstellungen verwenden.\",\"en\":\"Delegate one task to Codex using its native authentication and settings.\",\"es\":\"Delegue una tarea a Codex utilizando su autenticación y configuración nativas.\",\"fr\":\"Déléguez une tâche à Codex à l’aide de son authentification et de ses paramètres natifs.\",\"ja\":\"Codex のネイティブの認証と設定を使用して、単独のタスクを委派します。\",\"pt\":\"Delegue uma tarefa a Codex usando sua autenticação e configurações nativas.\",\"ru\":\"Делегируйте одну задачу Codex, используя его встроенную аутентификацию и настройки.\",\"zh\":\"使用 Codex 原生认证和设置委派单个任务。\"},\"enabled\":false},{\"name\":\"@deepseek-ai/dsh-cua-bundle\",\"title\":{\"de\":\"Computernutzung\",\"en\":\"Computer use\",\"es\":\"Uso de la computadora\",\"fr\":\"Utilisation de l'ordinateur\",\"ja\":\"Computer Use\",\"pt\":\"Uso do computador\",\"ru\":\"Использование компьютера\",\"zh\":\"Computer Use\"},\"description\":{\"de\":\"Unterstützt derzeit macOS; Die Windows-Unterstützung befindet sich in der Entwicklung. Lädt die Computernutzung für bestehende und neue PTC-Sitzungen. Wechseln Sie in den PTC-Modus und erteilen Sie die Berechtigungen für Barrierefreiheit und Bildschirmaufzeichnung, um ihn zu verwenden.\",\"en\":\"Currently supports macOS; Windows support is in development. Loads computer use for existing and new PTC sessions. Switch to PTC mode and grant Accessibility and Screen Recording permissions to use it.\",\"es\":\"Actualmente es compatible con macOS; El soporte para Windows está en desarrollo. Carga el uso de la computadora para sesiones PTC nuevas y existentes. Cambie al modo PTC y otorgue permisos de Accesibilidad y Grabación de pantalla para usarlo.\",\"fr\":\"Prend actuellement en charge macOS ; La prise en charge de Windows est en cours de développement. Charge l'utilisation de l'ordinateur pour les sessions PTC existantes et nouvelles. Passez en mode PTC et accordez les autorisations d’accessibilité et d’enregistrement d’écran pour l’utiliser.\",\"ja\":\"現在は macOS のみ対応し、Windows 対応は開発中です。既存および新規の PTC セッションに Computer Use を読み込みます。PTC モードに切り替え、アクセシビリティと画面収録の権限を許可して使用してください。\",\"pt\":\"Atualmente suporta macOS; O suporte Windows está em desenvolvimento. Carrega o uso do computador para sessões PTC novas e existentes. Mude para o modo PTC e conceda permissões de acessibilidade e gravação de tela para usá-lo.\",\"ru\":\"В настоящее время поддерживается macOS; Поддержка Windows находится в разработке. Загружает использование компьютера для существующих и новых сеансов PTC. Переключитесь в режим PTC и предоставьте разрешения на доступность и запись экрана для его использования.\",\"zh\":\"目前仅支持 macOS,Windows 支持正在开发中。为已有及新建 PTC 会话加载 Computer Use。请切换到 PTC 模式来使用,并授予辅助功能和屏幕录制权限。\"},\"enabled\":false}]\n\n"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[16],"surfaceOp":"append"}
{"type":"step/end","data":{"turn":1,"step":1}}
{"type":"step/start","data":{"turn":1,"step":2}}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":["apply_patch","ask_user_question","bash","create_goal","edit","get_goal","glob","grep","interrupt_agent","job_kill","job_list","job_output","list_agents","list_subagent_models","plugin_manager","present","propose_action","read","read_image","schedule_create","schedule_edit","schedule_list","schedule_view","send_message","skill","subagent","subagent_fork","todo_write","update_goal","web_fetch","web_search","workflow","working_directory","write"]},"reason":"change"}}