diff --git a/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.i18n.yaml b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.i18n.yaml
new file mode 100644
index 0000000000..c81c4aa5ba
--- /dev/null
+++ b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.i18n.yaml
@@ -0,0 +1,6 @@
+# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
+# side as of the last confirmed-consistent state. Both languages carry equal authority;
+# after editing either side, bring the other along and re-record with:
+# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.md
+2026-08-29-inline-visualizer-cordis-extension.md: 527aac505e0cf625282daa4575c8bcd35ed8e342
+2026-08-29-inline-visualizer-cordis-extension.zh.md: c7e6521d5d01e531498abd5587811ee6aec7aa54
diff --git a/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.md b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.md
new file mode 100644
index 0000000000..527aac505e
--- /dev/null
+++ b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.md
@@ -0,0 +1,35 @@
+# Agent Note: Inline Visualizer Cordis extension
+
+Status: implemented
+
+English | [中文](2026-08-29-inline-visualizer-cordis-extension.zh.md)
+
+## Problem
+
+DSH had no first-party Host contract for a model to request a temporary inline visual, progressively load construction guidance, or let a compatible Client submit an explicitly labelled follow-up from a successful HTML widget. Adding that surface globally would change every Agent preset even when no renderer or authority was present.
+
+## Decision
+
+`@deepseek-ai/dsh-tool-visualizer` is an independently loadable, dormant Host/model capability with two Cordis entrypoints. The root service owns Host source and complete-follow-up limits, exact-live-Agent and exact successful-`show_widget`-result authorization, the authoritative per-Agent follow-up rate limit, and insertion of authorized widget-authored follow-ups. Result authorization uses direct Session event lookup rather than a call-ID cache. Its generated Remote exposes `sendPrompt` to a separately supplied compatible Client; Client rendering limits remain independent security ceilings rather than transported Host configuration.
+
+The package's `./model` function-plugin requires `systemPrompt` and `tools`, then recoverably injects `visualizer`; while authority exists it installs the `tool:visualizer` prompt plus `widget_guidelines` and `show_widget` only in an Agent preset standing scope. `standard` and `cordis` always mount this wrapper, so late authority appearance, withdrawal, and reappearance activate, remove, and reactivate the model surface for existing and new Agents. `minimal` and `ptc` omit it. PTC's nested code-dispatch log does not provide the ordinary `show_widget` call/result identity required by the follow-up bridge. No default application composition mounts the root authority, so the shipped default prompt and tool surfaces remain unchanged.
+
+Each `widget_guidelines` result includes Delivery when `show_widget` is visible, then combines one shared Foundation with only the requested type modules. The Foundation owns host-native composition, responsive flow, theme use, and cross-type accessibility; the type modules own diagram structure, interaction lifecycle, chart semantics, and illustration exceptions.
+
+Mounting the root authority exposes both raw SVG and HTML fragments; source-prefix detection selects the recorded kind without turning rendering policy into model-facing deployment vocabulary. This change supplies no presentation Client and does not activate the capability in Web, headless, or TUI. The Host exposes no mutable-state report, recovery, or model-read surface. No Visualizer session event, Agent-loop rule, or core schema is added.
+
+## Verification
+
+Focused tests pin the shared routing prompt, unified schemas and guidance, source and complete-follow-up UTF-8 limits, exact Agent and successful-result authorization through direct event lookup, per-Agent prompt limits, and root/model disposal. REAL Loader composition tests prove that default Web and headless profiles omit the authority, `standard` and `cordis` always mount a dormant model wrapper, `minimal` and `ptc` have no row, and late authority appearance, withdrawal, and reappearance update the inherited model surface for existing and new Agents without adding global tools or prompt sections.
+
+## Alternatives considered
+
+**Register the tools from the root service.** Rejected because that would make model policy deployment-global and bypass preset inheritance and child tool filtering. The always-mounted `./model` wrapper keeps authority at the Host root and model visibility in the owning preset scope.
+
+**Enable the capability in default application compositions.** Rejected because this change does not include a presentation Client. Dormancy makes the Host/model contract reviewable and independently loadable without claiming an end-to-end user experience.
+
+**Trust a Client-supplied call id without checking the session log.** Rejected because a presentation Client must not mint authority. The Host binds each follow-up to the exact live Agent and a successful recorded HTML `show_widget` result before it enters the inbox.
+
+## Consequences
+
+The capability is isolated to one package, two preset wrapper rows, generated catalogs, and TypeScript aggregates. Default applications retain their existing model surface. The root service controls whether the always-mounted wrapper exposes the model surface; a compatible Client is additionally required for the end-to-end user experience. The authority may be mounted, withdrawn, and restored without rebuilding the preset. The Client must provide rendering security and resource controls for accepted HTML. Mutable widget state is Client-local and resets when its document is recreated.
diff --git a/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.zh.md b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.zh.md
new file mode 100644
index 0000000000..c7e6521d5d
--- /dev/null
+++ b/.agents/notes/implemented/feature/2026-08-29-inline-visualizer-cordis-extension.zh.md
@@ -0,0 +1,35 @@
+# Agent Note: 内联 Visualizer Cordis 扩展
+
+Status: implemented
+
+[English](2026-08-29-inline-visualizer-cordis-extension.md) | 中文
+
+## 问题
+
+DSH 缺少一方 Host 契约,让模型请求临时内联视觉内容、渐进加载构建指南,或让兼容 Client 从成功的 HTML widget 提交带明确标记的 follow-up。如果全局加入这组接口,即使 renderer 或权威服务不存在,也会改变每个 Agent preset。
+
+## 决策
+
+`@deepseek-ai/dsh-tool-visualizer` 是一个可独立装载、默认休眠的 Host/模型能力,包含两个 Cordis entrypoint。根 service 拥有 Host 源码与完整 follow-up 限额、准确 live Agent 与准确成功 `show_widget` result 的授权、权威的每 Agent follow-up 频控,以及已授权 widget-authored follow-up 的写入。result 授权使用直接 Session event 查询,而不是 call-ID 缓存。它生成的 Remote 向单独提供的兼容 Client 暴露 `sendPrompt`;Client 渲染限额是独立的安全上限,而非通过传输获得的 Host 配置。
+
+同一包的 `./model` function-plugin 要求 `systemPrompt` 与 `tools`,然后可恢复地注入 `visualizer`;权威存在时,它只在 Agent preset standing scope 安装 `tool:visualizer` 提示词,以及 `widget_guidelines` 与 `show_widget`。`standard` 与 `cordis` 始终挂载该 wrapper,因此权威稍后出现、撤销与再次出现会针对现有及新 Agent 激活、移除与重新激活模型面。`minimal` 与 `ptc` 不包含该 row,因为 PTC 的嵌套 code-dispatch 日志不提供 follow-up bridge 所需的普通 `show_widget` call/result 身份。默认 application composition 均不挂载根权威,因此正式默认提示词与工具面保持不变。
+
+每个 `widget_guidelines` result 都会在 `show_widget` 可见时包含 Delivery,再把一个共享 Foundation 与所请求的类型模块组合起来。Foundation 拥有宿主原生构图、响应式流、主题使用与跨类型可访问性;类型模块分别拥有 diagram 结构、交互生命周期、chart 语义与 illustration 例外。
+
+挂载根权威后会同时公开 raw SVG 与 HTML fragment;源码前缀检测只选择已记录的 kind,不把 renderer 部署策略泄漏成模型词汇。本次变更不提供展示 Client,也不在 Web、headless 或 TUI 中激活该能力。Host 不提供可变状态上报、恢复或模型读取面。实现不新增 Visualizer session event、Agent loop 规则或 core schema。
+
+## 验证
+
+定向测试固定了共享路由提示词、统一 schema 与 guideline、源码和完整 follow-up UTF-8 限额、通过直接 event 查询完成的准确 Agent 与成功 result 授权、每 Agent prompt 限额,以及 root/model dispose。REAL Loader composition 测试证明默认 Web 与 headless profile 都不含权威,`standard` 与 `cordis` 始终挂载休眠的 model wrapper,`minimal` 与 `ptc` 没有该 row;权威稍后出现、撤销与再次出现时,现有和新 Agent 的继承模型面都会随之更新,而且不会增加全局工具或提示词 section。
+
+## 考虑过的替代方案
+
+**从根 service 注册工具。** 不采用,因为这会让模型策略变成部署全局状态,并绕过 preset 继承与 child 工具过滤。始终挂载的 `./model` wrapper 把权威留在 Host 根层,把模型可见性留在所属 preset scope。
+
+**在默认 application composition 中启用能力。** 不采用,因为本次变更不包含展示 Client。默认休眠让 Host/模型契约可以独立评审和装载,而不会声称已有端到端用户体验。
+
+**不检查 session 日志,直接信任 Client 提交的 call id。** 不采用,因为展示 Client 不能自行生成授权。每个 follow-up 进入 inbox 前,Host 都会把它绑定到准确 live Agent 与一个成功记录的 HTML `show_widget` result。
+
+## 后果
+
+该能力的改动收在一个包、2 条 preset wrapper row、生成式 catalog 与 TypeScript aggregate 中。默认 application 保持原有模型面。根 service 决定始终挂载的 wrapper 是否暴露模型面;端到端用户体验还需要兼容 Client。无需重建 preset 即可挂载、撤销或恢复该权威。Client 必须为所接纳的 HTML 自行提供渲染安全与资源控制。可变 widget 状态只存在于 Client,并会在其 document 重建时重置。
diff --git a/apps/web/tests/visualizer.e2e.ts b/apps/web/tests/visualizer.e2e.ts
new file mode 100644
index 0000000000..6601d9b1c4
--- /dev/null
+++ b/apps/web/tests/visualizer.e2e.ts
@@ -0,0 +1,97 @@
+/** Keyless assembled-Web proof for the opt-in Visualizer Host authority. */
+
+import { join } from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'
+import type { AgentHandle } from '@deepseek-ai/dsh-agent'
+import type { ReplayProviderConfig } from '@deepseek-ai/dsh-llm-replay'
+import { createUserMessage } from '@deepseek-ai/dsh-llm'
+import { SessionId } from '@deepseek-ai/dsh-session'
+import type {} from '@deepseek-ai/dsh-agent-presets'
+import {
+ assertFixtureInventory,
+ launchWebScaffold,
+ recordFixture,
+ webSnapshotMode,
+ type WebScaffold,
+} from './scaffold.ts'
+
+const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/visualizer-host', import.meta.url))
+const FIXTURE = join(SNAPSHOT_DIR, 'session.v2.jsonl')
+const PROMPT = 'Call widget_guidelines with the interactive and chart modules, then reply exactly "Guidance loaded." Do not call show_widget.'
+const VISUALIZER_TOOLS = ['show_widget', 'widget_guidelines']
+const RECORDED_PROVIDER_CATALOG = [{
+ id: 'deepseek-official',
+ name: 'DeepSeek',
+ models: [{
+ id: 'deepseek-v4-flash',
+ name: 'DeepSeek-V4-Flash',
+ contextWindow: 1_000_000,
+ defaultMaxTokens: 256_000,
+ reasoningEfforts: ['off', 'low', 'high', 'max'],
+ defaultReasoningEffort: 'high',
+ }],
+}] satisfies readonly ReplayProviderConfig[]
+const MODE = webSnapshotMode()
+
+describe('Visualizer Host explicit composition', () => {
+ let scaffold: WebScaffold
+ let agentHandle: AgentHandle
+ let authorityId: string
+
+ beforeAll(async () => {
+ scaffold = await launchWebScaffold(MODE === 'record'
+ ? {}
+ : { replayFixture: FIXTURE, replayProviders: [...RECORDED_PROVIDER_CATALOG] })
+ const presetKey = await scaffold.ctx.agentPresets.standingKeyFor('standard')
+ authorityId = await scaffold.ctx.loader.create({ name: '@deepseek-ai/dsh-tool-visualizer' })
+ await scaffold.ctx.loader.await()
+ await vi.waitFor(() => {
+ expect(scaffold.ctx.tools.schemas(presetKey).map(schema => schema.name)
+ .filter(name => VISUALIZER_TOOLS.includes(name)).sort()).toEqual(VISUALIZER_TOOLS)
+ })
+ agentHandle = await scaffold.ctx.agents.create({
+ sessionId: SessionId('visualizer-host-snapshot'),
+ meta: { cwd: scaffold.workspaceCwd, agentPreset: 'standard' },
+ agentOptions: { provider: 'deepseek-official', model: 'deepseek-v4-flash' },
+ setup: agentCtx => scaffold.ctx.agentPresets.mount(agentCtx, 'standard').then(() => undefined),
+ })
+ expect(scaffold.ctx.tools.schemas(agentHandle.agent).map(schema => schema.name)
+ .filter(name => VISUALIZER_TOOLS.includes(name)).sort()).toEqual(VISUALIZER_TOOLS)
+ agentHandle.agent.followup(createUserMessage({
+ content: [{ type: 'text', text: PROMPT }],
+ source: { kind: 'user' },
+ }))
+ await agentHandle.agent.whenIdle()
+ if (MODE === 'record') await recordFixture(scaffold, agentHandle.agent.session.id, FIXTURE)
+ })
+
+ afterAll(async () => {
+ const failures: unknown[] = []
+ await agentHandle?.dispose().catch((error: unknown) => failures.push(error))
+ if (authorityId !== undefined) {
+ await scaffold.ctx.loader.remove(authorityId).catch((error: unknown) => failures.push(error))
+ }
+ await scaffold?.close().catch((error: unknown) => failures.push(error))
+ if (failures.length === 1) throw failures[0]
+ if (failures.length > 1) throw new AggregateError(failures, 'Visualizer Host snapshot teardown failed')
+ })
+
+ it('records the prompt plus two schemas from an explicit Host composition', async () => {
+ expect(scaffold.ctx.get('visualizer')).toBeDefined()
+
+ const requestHeader = agentHandle.agent.session.requestHeader()
+ if (requestHeader === undefined) throw new Error('the Visualizer Host scenario issued no model request')
+ expect(requestHeader.system).toContain('Use show_widget for a temporary inline visual')
+ expect(requestHeader.tools?.map(schema => schema.name).filter(name => VISUALIZER_TOOLS.includes(name)).sort())
+ .toEqual(VISUALIZER_TOOLS)
+ expect(requestHeader.tools?.toSorted((left, right) => left.name.localeCompare(right.name)))
+ .toEqual(scaffold.ctx.tools.schemas(agentHandle.agent).toSorted((left, right) => left.name.localeCompare(right.name)))
+
+ await assertFixtureInventory(SNAPSHOT_DIR, [
+ 'session.jsonl',
+ 'system-prompt.expected.md',
+ 'tool-schemas.expected.json',
+ ])
+ })
+})
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index 8299e0b6da..ae5e961afd 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -64,6 +64,7 @@
"tests/cordis-tool-round.e2e.ts",
"tests/web-search-round.e2e.ts",
"tests/file-upload-round.e2e.ts",
+ "tests/visualizer.e2e.ts",
"tests/message-actions.e2e.ts",
"tests/open-in-app-ssh.e2e.ts",
"tests/message-feedback.e2e.ts",
diff --git a/docs/capability-seams.i18n.yaml b/docs/capability-seams.i18n.yaml
index c370fbef7f..ff7def2a7a 100644
--- a/docs/capability-seams.i18n.yaml
+++ b/docs/capability-seams.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/capability-seams.md
-capability-seams.md: a47ec285e248c4d969e49bc941d5c93faef7b65e
-capability-seams.zh.md: 42e7105611f21f74ee0d8088e06e5c7007af9376
+capability-seams.md: 008a1d3cdb75876697212c47b7570f3d971df6c3
+capability-seams.zh.md: 4ee46b66eb775252df2b67da09e6157f8d042a3f
diff --git a/docs/capability-seams.md b/docs/capability-seams.md
index a47ec285e2..008a1d3cdb 100644
--- a/docs/capability-seams.md
+++ b/docs/capability-seams.md
@@ -98,7 +98,9 @@ flowchart LR
svc_systemPrompt["ctx.systemPrompt
System prompt assembly registry"]
pkg_tools["tools"]
pkg_tool_terminal["tool-terminal"]
+ pkg_tool_visualizer["tool-visualizer"]
pkg_tool_web["tool-web"]
+ svc_visualizer["ctx.visualizer
Inline Visualizer authority"]
svc_tools["ctx.tools
Tool registry and guarded execution pipeline"]
pkg_tool_ask_user["tool-ask-user"]
pkg_tool_cordis["tool-cordis"]
@@ -327,6 +329,7 @@ flowchart LR
pkg_terminal_bash --> svc_terminals
pkg_token_meter --> svc_tokenMeter
pkg_tool_subagent --> svc_subagentModelSelection
+ pkg_tool_visualizer --> svc_visualizer
pkg_tools --> svc_tools
pkg_typert_registry --> svc_typert
pkg_user_approval --> svc_approval
@@ -439,6 +442,7 @@ flowchart LR
svc_systemPrompt --> pkg_agent_loop
svc_systemPrompt --> pkg_tool_fs
svc_systemPrompt --> pkg_tool_terminal
+ svc_systemPrompt --> pkg_tool_visualizer
svc_systemPrompt --> pkg_tool_web
svc_systemPrompt --> pkg_tools
svc_terminals --> pkg_tool_terminal
@@ -453,6 +457,7 @@ flowchart LR
svc_tools --> pkg_tool_subagent
svc_tools --> pkg_tool_terminal
svc_tools --> pkg_tool_todo
+ svc_tools --> pkg_tool_visualizer
svc_tools --> pkg_tool_web
svc_typert --> pkg_api_gateway
svc_typert --> pkg_typert_loader
@@ -503,8 +508,9 @@ flowchart LR
| `ctx.fileReferences` | `seam` | [`file-reference`](../packages/context/file-reference) | [`file-reference-local`](../packages/context/file-reference-local) | [`api-session-controller`](../packages/api/session-controller) | - | The interface returns path-only completion candidates within an Agent cwd; providers own namespace access and ranking without reading file contents. |
| `ctx.sessionReferenceResolver` | `core` | [`session-reference`](../packages/context/session-reference) | - | - | - | Projects bounded current-surface conversation snapshots into durable untrusted message context; host adapters own mention syntax. |
| `ctx.sessionTitle` | `seam` | [`session-title`](../packages/session/session-title) | [`session-title-first-prompt-llm`](../packages/session/session-title-first-prompt-llm), [`session-title-all-prompts-llm`](../packages/session/session-title-all-prompts-llm) | - | - | Owns the deterministic fallback, latest-title fold, and sole optional asynchronous provider registration. |
-| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop), [`tools`](../packages/core/tools), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-web`](../packages/web/tool-web) | - | Collects prompt sections and model-facing tool schemas for each step. |
-| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/interaction/tool-ask-user), [`tool-bash`](../packages/shell/tool-bash), [`tool-cordis`](../packages/extensions/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-web`](../packages/web/tool-web) | - | Registers capabilities, owns PTC mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation. |
+| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop), [`tools`](../packages/core/tools), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-visualizer`](../packages/visualizer/tool-visualizer), [`tool-web`](../packages/web/tool-web) | - | Collects prompt sections and model-facing tool schemas for each step. |
+| `ctx.visualizer` | `core` | [`tool-visualizer`](../packages/visualizer/tool-visualizer) | - | - | - | Owns limits, exact live-Agent/call authorization, follow-up admission, and generated Remote operations; its preset-scoped ./model contribution consumes the authority and owns model-tool and prompt registration lifecycles. |
+| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/interaction/tool-ask-user), [`tool-bash`](../packages/shell/tool-bash), [`tool-cordis`](../packages/extensions/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-visualizer`](../packages/visualizer/tool-visualizer), [`tool-web`](../packages/web/tool-web) | - | Registers capabilities, owns PTC mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation. |
| `ctx.userQuestions` | `seam` | [`user-questions`](../packages/interaction/user-questions) | - | [`tool-ask-user`](../packages/interaction/tool-ask-user) | - | UI front ends provide the active human-answer provider; tool-ask-user pauses a tool call on the provider-neutral ask() promise. |
| `ctx.planMode` | `core` | [`plan-mode`](../packages/plan/plan-mode) | - | - | - | Folds logged plan/mode state, flushes user selections at turn boundaries, renders deployment-owned guidance, registers /plan, and keeps the plan-exit schema stable across transitions. |
| `ctx.agentPresets` | `core` | [`agent-presets`](../packages/preset/agent-presets) | - | - | - | Discovers preset directories over trusted and user-authored roots and mounts one preset cordis.yml under an agent scope during creation, rejecting a row that never activates or that publishes into the root service realm. |
diff --git a/docs/capability-seams.zh.md b/docs/capability-seams.zh.md
index 42e7105611..4ee46b66eb 100644
--- a/docs/capability-seams.zh.md
+++ b/docs/capability-seams.zh.md
@@ -100,7 +100,9 @@ flowchart LR
svc_systemPrompt["ctx.systemPrompt
System prompt assembly registry"]
pkg_tools["tools"]
pkg_tool_terminal["tool-terminal"]
+ pkg_tool_visualizer["tool-visualizer"]
pkg_tool_web["tool-web"]
+ svc_visualizer["ctx.visualizer
Inline Visualizer authority"]
svc_tools["ctx.tools
Tool registry and guarded execution pipeline"]
pkg_tool_ask_user["tool-ask-user"]
pkg_tool_cordis["tool-cordis"]
@@ -329,6 +331,7 @@ flowchart LR
pkg_terminal_bash --> svc_terminals
pkg_token_meter --> svc_tokenMeter
pkg_tool_subagent --> svc_subagentModelSelection
+ pkg_tool_visualizer --> svc_visualizer
pkg_tools --> svc_tools
pkg_typert_registry --> svc_typert
pkg_user_approval --> svc_approval
@@ -441,6 +444,7 @@ flowchart LR
svc_systemPrompt --> pkg_agent_loop
svc_systemPrompt --> pkg_tool_fs
svc_systemPrompt --> pkg_tool_terminal
+ svc_systemPrompt --> pkg_tool_visualizer
svc_systemPrompt --> pkg_tool_web
svc_systemPrompt --> pkg_tools
svc_terminals --> pkg_tool_terminal
@@ -455,6 +459,7 @@ flowchart LR
svc_tools --> pkg_tool_subagent
svc_tools --> pkg_tool_terminal
svc_tools --> pkg_tool_todo
+ svc_tools --> pkg_tool_visualizer
svc_tools --> pkg_tool_web
svc_typert --> pkg_api_gateway
svc_typert --> pkg_typert_loader
@@ -505,8 +510,9 @@ flowchart LR
| `ctx.fileReferences` | `seam` | [`file-reference`](../packages/context/file-reference) | [`file-reference-local`](../packages/context/file-reference-local) | [`api-session-controller`](../packages/api/session-controller) | - | 该接口返回 Agent cwd 内仅含路径的补全候选;提供方负责命名空间访问与排序,但不读取文件内容。 |
| `ctx.sessionReferenceResolver` | `core` | [`session-reference`](../packages/context/session-reference) | - | - | - | 将当前表层中有界的对话快照投影为持久但不可信的消息上下文;Host 适配器负责提及语法。 |
| `ctx.sessionTitle` | `seam` | [`session-title`](../packages/session/session-title) | [`session-title-first-prompt-llm`](../packages/session/session-title-first-prompt-llm), [`session-title-all-prompts-llm`](../packages/session/session-title-all-prompts-llm) | - | - | 负责确定性回退、最新标题折叠区,以及唯一的可选异步提供方注册。 |
-| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop), [`tools`](../packages/core/tools), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-web`](../packages/web/tool-web) | - | 为每个步骤收集提示词各部分和面向模型的工具 schema。 |
-| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/interaction/tool-ask-user), [`tool-bash`](../packages/shell/tool-bash), [`tool-cordis`](../packages/extensions/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-web`](../packages/web/tool-web) | - | 注册能力,负责 PTC mode 传输,并让调用依次经过策略前处理、单调守卫、环绕分派、策略后处理和最终结果观测。 |
+| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop), [`tools`](../packages/core/tools), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-visualizer`](../packages/visualizer/tool-visualizer), [`tool-web`](../packages/web/tool-web) | - | 为每个步骤收集提示词各部分和面向模型的工具 schema。 |
+| `ctx.visualizer` | `core` | [`tool-visualizer`](../packages/visualizer/tool-visualizer) | - | - | - | 拥有限额、精确 live Agent/call 授权、follow-up 准入,以及生成式 Remote 操作;其 preset 作用域的 `./model` contribution 使用该权威,并负责模型工具与提示词注册的生命周期。 |
+| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/interaction/tool-ask-user), [`tool-bash`](../packages/shell/tool-bash), [`tool-cordis`](../packages/extensions/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-terminal`](../packages/terminal/tool-terminal), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-visualizer`](../packages/visualizer/tool-visualizer), [`tool-web`](../packages/web/tool-web) | - | 注册能力,负责 PTC mode 传输,并让调用依次经过策略前处理、单调守卫、环绕分派、策略后处理和最终结果观测。 |
| `ctx.userQuestions` | `seam` | [`user-questions`](../packages/interaction/user-questions) | - | [`tool-ask-user`](../packages/interaction/tool-ask-user) | - | UI 前端提供当前生效的人工回答提供方;tool-ask-user 在提供方无关的 ask() promise 上暂停工具调用。 |
| `ctx.planMode` | `core` | [`plan-mode`](../packages/plan/plan-mode) | - | - | - | 折叠已记录的计划/模式状态,在轮次边界刷新用户选择,渲染由部署方拥有的指导信息,注册 /plan,并在状态转换期间保持计划退出 schema 稳定。 |
| `ctx.agentPresets` | `core` | [`agent-presets`](../packages/preset/agent-presets) | - | - | - | 在受信任根目录与用户创作根目录上发现 preset 目录,并在创建期把一份 preset cordis.yml 挂载到 agent 作用域之下,拒绝始终未激活或向根服务 realm 发布服务的行。 |
diff --git a/docs/config-catalog.i18n.yaml b/docs/config-catalog.i18n.yaml
index 8c4e980c28..fbd91f8229 100644
--- a/docs/config-catalog.i18n.yaml
+++ b/docs/config-catalog.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/config-catalog.md
-config-catalog.md: 90390cab85be57485ad5446e1897f4f11be49ef5
-config-catalog.zh.md: 053ca6d1e357c07524b4b993447a59ed69761a88
+config-catalog.md: 2baaa5c3f2b62e0e0fbb40fc72c5397ce243ad2c
+config-catalog.zh.md: e09699ed6bd7ab322e1058cdd7edb2f59145b4db
diff --git a/docs/config-catalog.md b/docs/config-catalog.md
index 90390cab85..2baaa5c3f2 100644
--- a/docs/config-catalog.md
+++ b/docs/config-catalog.md
@@ -2597,7 +2597,7 @@ export interface Config {
}
```
-Source: [`packages/core/system-prompt/src/index.ts:242`](../packages/core/system-prompt/src/index.ts)
+Source: [`packages/core/system-prompt/src/index.ts:243`](../packages/core/system-prompt/src/index.ts)
@@ -3083,6 +3083,26 @@ export interface Config {
Source: [`packages/todo/tool-todo/src/index.ts:29`](../packages/todo/tool-todo/src/index.ts)
+
+
+## `@deepseek-ai/dsh-tool-visualizer`
+
+Requires: `agents`
+
+```ts config-catalog
+/** Deployment-varying limits for the Visualizer extension. */
+export interface Config {
+ /** Maximum UTF-8 bytes accepted for one widget source argument. At most 131072. */
+ maxWidgetBytes?: number
+ /** Maximum UTF-8 bytes accepted for one complete labelled widget follow-up. At most 4096. */
+ maxPromptBytes?: number
+ /** Per-Agent widget follow-ups admitted during one rolling minute. Defaults to 4. */
+ maxPromptsPerMinutePerAgent?: number
+}
+```
+
+Source: [`packages/visualizer/tool-visualizer/src/types.ts:2`](../packages/visualizer/tool-visualizer/src/types.ts)
+
## `@deepseek-ai/dsh-tool-web`
diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md
index 053ca6d1e3..e09699ed6b 100644
--- a/docs/config-catalog.zh.md
+++ b/docs/config-catalog.zh.md
@@ -2599,7 +2599,7 @@ export interface Config {
}
```
-来源:[`packages/core/system-prompt/src/index.ts:242`](../packages/core/system-prompt/src/index.ts)
+来源:[`packages/core/system-prompt/src/index.ts:243`](../packages/core/system-prompt/src/index.ts)
@@ -3085,6 +3085,26 @@ export interface Config {
来源:[`packages/todo/tool-todo/src/index.ts:29`](../packages/todo/tool-todo/src/index.ts)
+
+
+## `@deepseek-ai/dsh-tool-visualizer`
+
+需要:`agents`
+
+```ts config-catalog
+/** Deployment-varying limits for the Visualizer extension. */
+export interface Config {
+ /** Maximum UTF-8 bytes accepted for one widget source argument. At most 131072. */
+ maxWidgetBytes?: number
+ /** Maximum UTF-8 bytes accepted for one complete labelled widget follow-up. At most 4096. */
+ maxPromptBytes?: number
+ /** Per-Agent widget follow-ups admitted during one rolling minute. Defaults to 4. */
+ maxPromptsPerMinutePerAgent?: number
+}
+```
+
+来源:[`packages/visualizer/tool-visualizer/src/types.ts:2`](../packages/visualizer/tool-visualizer/src/types.ts)
+
## `@deepseek-ai/dsh-tool-web`
diff --git a/docs/module-graph.i18n.yaml b/docs/module-graph.i18n.yaml
index 7789f3c308..84a56bf0a6 100644
--- a/docs/module-graph.i18n.yaml
+++ b/docs/module-graph.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/module-graph.md
-module-graph.md: ecb72f02bc7a27a75318e8abf56c20f9915831ea
-module-graph.zh.md: 5c94c866d10e81948dd69089210cd4b08ded7531
+module-graph.md: 7dba6bfc14dbc7f518b70dfe3dc63a59005896e2
+module-graph.zh.md: 067b54925e01dbd897900bab21982706a68ca543
diff --git a/docs/module-graph.md b/docs/module-graph.md
index ecb72f02bc..7dba6bfc14 100644
--- a/docs/module-graph.md
+++ b/docs/module-graph.md
@@ -358,6 +358,9 @@ flowchart TD
pkg_typert_protocol["typert-protocol"]
pkg_typert_registry["typert-registry"]
end
+ subgraph group_visualizer["packages/visualizer"]
+ pkg_tool_visualizer["tool-visualizer"]
+ end
subgraph group_webhook["packages/webhook"]
pkg_webhook["webhook"]
pkg_webhook_github["webhook-github"]
@@ -879,6 +882,13 @@ flowchart TD
pkg_llm_replay --> pkg_deepseek_llm_api_extensions
pkg_llm_replay --> pkg_llm
pkg_llm_replay --> pkg_session
+ pkg_tool_visualizer --> pkg_agent
+ pkg_tool_visualizer --> pkg_llm
+ pkg_tool_visualizer --> pkg_scope
+ pkg_tool_visualizer --> pkg_session
+ pkg_tool_visualizer --> pkg_system_prompt
+ pkg_tool_visualizer --> pkg_tools
+ pkg_tool_visualizer --> pkg_typert_protocol
pkg_tool_workflow --> pkg_agent
pkg_tool_workflow --> pkg_invariants
pkg_tool_workflow --> pkg_llm
@@ -1393,6 +1403,7 @@ flowchart TD
| [`tool-pwsh-persistent`](../packages/shell/tool-pwsh-persistent) | `shell` | [`agent`](../packages/core/agent), [`terminal`](../packages/terminal/terminal), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
| [`tool-terminal`](../packages/terminal/tool-terminal) | `terminal` | [`agent`](../packages/core/agent), [`jobs`](../packages/jobs/jobs), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`system-prompt`](../packages/core/system-prompt), [`terminal`](../packages/terminal/terminal), [`tools`](../packages/core/tools) |
| [`llm-replay`](../packages/test-support/llm-replay) | `test-support` | [`compaction`](../packages/compaction/compaction), [`deepseek-llm-api-extensions`](../packages/llm/deepseek-llm-api-extensions), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
+| [`tool-visualizer`](../packages/visualizer/tool-visualizer) | `visualizer` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
| [`tool-workflow`](../packages/workflow/tool-workflow) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
| [`plugin-package-inventory-deepseek`](../packages/llm/plugin-package-inventory-deepseek) | `llm` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`deepseek-llm-api-extensions`](../packages/llm/deepseek-llm-api-extensions), [`session`](../packages/core/session) |
| [`session-query`](../packages/session-query/session-query) | `session-query` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-title`](../packages/session/session-title), [`tool-todo`](../packages/todo/tool-todo) |
diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md
index 5c94c866d1..067b54925e 100644
--- a/docs/module-graph.zh.md
+++ b/docs/module-graph.zh.md
@@ -360,6 +360,9 @@ flowchart TD
pkg_typert_protocol["typert-protocol"]
pkg_typert_registry["typert-registry"]
end
+ subgraph group_visualizer["packages/visualizer"]
+ pkg_tool_visualizer["tool-visualizer"]
+ end
subgraph group_webhook["packages/webhook"]
pkg_webhook["webhook"]
pkg_webhook_github["webhook-github"]
@@ -881,6 +884,13 @@ flowchart TD
pkg_llm_replay --> pkg_deepseek_llm_api_extensions
pkg_llm_replay --> pkg_llm
pkg_llm_replay --> pkg_session
+ pkg_tool_visualizer --> pkg_agent
+ pkg_tool_visualizer --> pkg_llm
+ pkg_tool_visualizer --> pkg_scope
+ pkg_tool_visualizer --> pkg_session
+ pkg_tool_visualizer --> pkg_system_prompt
+ pkg_tool_visualizer --> pkg_tools
+ pkg_tool_visualizer --> pkg_typert_protocol
pkg_tool_workflow --> pkg_agent
pkg_tool_workflow --> pkg_invariants
pkg_tool_workflow --> pkg_llm
@@ -1395,6 +1405,7 @@ flowchart TD
| [`tool-pwsh-persistent`](../packages/shell/tool-pwsh-persistent) | `shell` | [`agent`](../packages/core/agent), [`terminal`](../packages/terminal/terminal), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
| [`tool-terminal`](../packages/terminal/tool-terminal) | `terminal` | [`agent`](../packages/core/agent), [`jobs`](../packages/jobs/jobs), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`system-prompt`](../packages/core/system-prompt), [`terminal`](../packages/terminal/terminal), [`tools`](../packages/core/tools) |
| [`llm-replay`](../packages/test-support/llm-replay) | `test-support` | [`compaction`](../packages/compaction/compaction), [`deepseek-llm-api-extensions`](../packages/llm/deepseek-llm-api-extensions), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
+| [`tool-visualizer`](../packages/visualizer/tool-visualizer) | `visualizer` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
| [`tool-workflow`](../packages/workflow/tool-workflow) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
| [`plugin-package-inventory-deepseek`](../packages/llm/plugin-package-inventory-deepseek) | `llm` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`deepseek-llm-api-extensions`](../packages/llm/deepseek-llm-api-extensions), [`session`](../packages/core/session) |
| [`session-query`](../packages/session-query/session-query) | `session-query` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-title`](../packages/session/session-title), [`tool-todo`](../packages/todo/tool-todo) |
diff --git a/docs/subsystems/tools.i18n.yaml b/docs/subsystems/tools.i18n.yaml
index d448297059..43e937bd36 100644
--- a/docs/subsystems/tools.i18n.yaml
+++ b/docs/subsystems/tools.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/tools.md
-tools.md: 9939e8ab9fff9fa5bd23fd370e07f6296a608824
-tools.zh.md: 52e812a35d6932a5ed00a86a3d3fe71460b26cd4
+tools.md: baf129faaab40b54c8b761d84fba75aab3ec66b8
+tools.zh.md: 51019ca211f9dea8c001cd375b2fb3ab8b832925
diff --git a/docs/subsystems/tools.md b/docs/subsystems/tools.md
index 9939e8ab9f..baf129faaa 100644
--- a/docs/subsystems/tools.md
+++ b/docs/subsystems/tools.md
@@ -573,6 +573,32 @@ Types: [ScopeKey](scope.md)
Source: [`packages/core/tools/src/index.ts`](../../packages/core/tools/src/index.ts)
+
+
+### `ctx.visualizer` — `VisualizerService`
+
+One Host service owns every authority-bearing part of the Visualizer extension.
+
+```ts cordis-catalog
+/**
+ * Install the model-facing Visualizer contribution in the caller's preset scope.
+ * @param modelCtx - Preset-scoped context that owns the prompt and tool effects.
+ */
+installModelSurface(modelCtx: Context): void
+
+/**
+ * Queue a widget-authored message after Host-side authorization and rate limiting.
+ * @param agent - Exact live Agent resolved from the Remote session scope.
+ * @param request - Follow-up for one successful interactive widget call.
+ * @returns Receipt confirming that the follow-up was queued.
+ */
+@Remote('sendPrompt') remoteSendPrompt(agent: Agent, request: WidgetPromptRequest): WidgetPromptResult
+```
+
+Types: [Agent](core.md)
+
+Source: [`packages/visualizer/tool-visualizer/src/index.ts`](../../packages/visualizer/tool-visualizer/src/index.ts)
+
### `tools/*` events
diff --git a/docs/subsystems/tools.zh.md b/docs/subsystems/tools.zh.md
index 52e812a35d..51019ca211 100644
--- a/docs/subsystems/tools.zh.md
+++ b/docs/subsystems/tools.zh.md
@@ -573,6 +573,32 @@ Types: [ScopeKey](scope.zh.md)
Source: [`packages/core/tools/src/index.ts`](../../packages/core/tools/src/index.ts)
+
+
+### `ctx.visualizer` — `VisualizerService`
+
+One Host service owns every authority-bearing part of the Visualizer extension.
+
+```ts cordis-catalog
+/**
+ * Install the model-facing Visualizer contribution in the caller's preset scope.
+ * @param modelCtx - Preset-scoped context that owns the prompt and tool effects.
+ */
+installModelSurface(modelCtx: Context): void
+
+/**
+ * Queue a widget-authored message after Host-side authorization and rate limiting.
+ * @param agent - Exact live Agent resolved from the Remote session scope.
+ * @param request - Follow-up for one successful interactive widget call.
+ * @returns Receipt confirming that the follow-up was queued.
+ */
+@Remote('sendPrompt') remoteSendPrompt(agent: Agent, request: WidgetPromptRequest): WidgetPromptResult
+```
+
+Types: [Agent](core.zh.md)
+
+Source: [`packages/visualizer/tool-visualizer/src/index.ts`](../../packages/visualizer/tool-visualizer/src/index.ts)
+
### `tools/*` events
diff --git a/docs/tool-catalog.i18n.yaml b/docs/tool-catalog.i18n.yaml
index 4bb43418d9..a56cf325c2 100644
--- a/docs/tool-catalog.i18n.yaml
+++ b/docs/tool-catalog.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/tool-catalog.md
-tool-catalog.md: 1a98079dcf3d30696cf2dae2895372a90377204d
-tool-catalog.zh.md: 41b5f6d4bc8b0e666e74dde5b4bb43bd0064da8e
+tool-catalog.md: ef1cfee182bb8908d92f4e50b534562eaf4519f9
+tool-catalog.zh.md: 0e7b37857578238c286a109af87bf12187ab5dd4
diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md
index 1a98079dcf..ef1cfee182 100644
--- a/docs/tool-catalog.md
+++ b/docs/tool-catalog.md
@@ -38,6 +38,7 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-tool-jobs` | `job_kill`, `job_list`, `job_output` | `ctx.tools`, `ctx.jobs`, `ctx.systemPrompt` | `tool/call`, `tool/result`, `user/message via agent.inject() for background completion notices` | - | The kind-agnostic background-job controller: background bash commands, PTY sends, and subagents are read, listed, and killed through the same three tools. Loading the plugin attaches the controller that arms producers' `ctx.jobs.start()`. |
| `@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/message/queued`, `team/message/delivered`, `team/task`, `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-visualizer` | `show_widget`, `widget_guidelines` | `ctx.visualizer`, `ctx.tools`, `ctx.systemPrompt` | `tool/call`, `tool/result`, `user/message via agent.followup() for authorized widget follow-ups` | - | The standard and cordis presets always mount a recoverable model wrapper, which contributes prompt and tools only while the authority service exists and follows later authority withdrawal or reappearance. Minimal and PTC omit it; PTC nested code-dispatch calls lack the ordinary show_widget call/result identity required by the follow-up bridge. |
| `@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-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. |
@@ -2078,6 +2079,69 @@ Source: [`packages/todo/tool-todo/src/index.ts`](../packages/todo/tool-todo/src/
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-visualizer`
+
+### `show_widget`
+
+Render one temporary inline graphic or interactive widget from conversation content or completed tool results. Source beginning with