refactor(acp): reduce bridge to automation protocol

This commit is contained in:
Tianyi Cui
2026-07-24 01:40:25 +08:00
parent b06bcfd21c
commit e819a586b0
406 changed files with 3880 additions and 21325 deletions

View File

@@ -78,6 +78,7 @@ const GROUP_ORDER = [
'session-query',
'session-title',
'support',
'acp',
'ui',
]
@@ -129,7 +130,7 @@ const SERVICE_ROLES: ServiceRole[] = [
title: 'Durable session persistence seam',
mode: 'seam',
implementations: ['session-persistence-jsonl', 'session-persistence-sqlite'],
consumers: ['agent-loop', 'tool-bash', 'hooks-claude', 'hooks-codex', 'acp', 'session-query', 'session-query-sqlite'],
consumers: ['agent-loop', 'tool-bash', 'hooks-claude', 'hooks-codex', 'session-query', 'session-query-sqlite'],
note: 'Backends persist the same SessionEvent vocabulary; apps choose a backend at composition time.',
},
{
@@ -146,7 +147,7 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'session-reference',
title: 'Cross-session snapshot preparation',
mode: 'core',
consumers: ['tui', 'acp'],
consumers: ['tui'],
note: 'Projects bounded current-surface conversation snapshots into durable untrusted message context; host adapters own mention syntax.',
},
{
@@ -170,7 +171,7 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'tools',
title: 'Tool registry and guarded execution pipeline',
mode: 'core',
consumers: ['agent-loop', 'tool-ask-user', 'tool-bash', 'tool-cordis', 'tool-fs', 'tool-pty', 'tool-skill', 'tool-subagent', 'tool-todo', 'tool-web', 'acp'],
consumers: ['agent-loop', 'tool-ask-user', 'tool-bash', 'tool-cordis', 'tool-fs', 'tool-pty', 'tool-skill', 'tool-subagent', 'tool-todo', 'tool-web'],
note: 'Registers capabilities, owns Code Mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation.',
},
{
@@ -178,8 +179,8 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'user-interaction',
title: 'Human question/answer seam',
mode: 'seam',
implementations: ['tui', 'acp'],
consumers: ['tool-ask-user', 'tui', 'acp'],
implementations: ['tui'],
consumers: ['tool-ask-user', 'tui'],
note: 'UI front doors provide the active human-answer provider; tool-ask-user pauses a tool call on the provider-neutral ask() promise.',
},
{
@@ -187,7 +188,6 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'plan-mode',
title: 'Plan collaboration state',
mode: 'core',
consumers: ['acp'],
note: '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.',
},
{
@@ -195,8 +195,8 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'commands',
title: 'Human command registry',
mode: 'core',
consumers: ['tui', 'acp'],
note: 'Plugins register direct human commands; TUI and ACP consume the same effective per-agent catalog without sending invocations to the model.',
consumers: ['tui'],
note: 'Plugins register direct human commands; TUI consumes the effective per-agent catalog without sending invocations to the model.',
},
{
key: 'tui',
@@ -295,7 +295,6 @@ const SERVICE_ROLES: ServiceRole[] = [
title: 'Permission presets',
mode: 'core',
implementations: [],
consumers: ['acp'],
note: 'User-facing preset table (`workspace-write`/`danger-full-access`) bundling the sandbox-mode and approval-policy knobs; a switch writes one `permission/preset` event through to both knob events.',
},
{
@@ -531,10 +530,10 @@ const APP_EXAMPLES = [
{
id: 'acp',
rel: 'examples/acp-agent/composition.md',
title: 'ACP Agent App Composition',
title: 'ACP Automation App Composition',
label: 'examples/acp-agent',
config: 'examples/acp-agent/cordis.yml',
summary: 'The ACP demo exposes the same agent spine over JSON-RPC stdio, with no stdout logger and no pre-created agent; clients create sessions through the ACP bridge.',
summary: 'The ACP demo exposes fresh text-only agent sessions to programmatic clients over JSON-RPC stdio, with no stdout logger, human UI, or pre-created agent.',
},
]
@@ -550,7 +549,7 @@ function renderAppExpansion(lines: string[], appNode: string, pluginName: string
} else if (pluginName === '@deepseek-ai/dsh-cli-demo') {
lines.push(` ${appNode} --> ${nodeId('frontdoor', 'cli')}["one-shot driver<br/>format-pure stdout<br/>fresh top-level agent"]`)
} else if (pluginName === '@deepseek-ai/dsh-acp-demo') {
lines.push(` ${appNode} --> ${nodeId('frontdoor', 'acp')}["@deepseek-ai/dsh-acp<br/>JSON-RPC stdio bridge<br/>sessions created by client"]`)
lines.push(` ${appNode} --> ${nodeId('frontdoor', 'acp')}["@deepseek-ai/dsh-acp<br/>automation-only JSON-RPC stdio<br/>fresh sessions created by client"]`)
}
lines.push(
` ${agentCore} --> ${nodeId('spine', 'llm')}["ctx.llm"]`,
@@ -1039,35 +1038,6 @@ function renderToolPipeline(): string {
].join('\n')
}
function renderSnapshotReplay(): string {
const maintenance = 'curated Mermaid sequence based on the snapshot test harness'
return [
...generatedHeader('ACP Snapshot Replay'),
'This graph explains what a snapshot scenario proves: recorded real-model session logs are replayed keylessly, ACP stdout is normalized and diffed, and scenario workspaces preserve tool side effects that the UI stream alone cannot prove.',
'',
'```mermaid',
'sequenceDiagram',
' participant Recorder as Real API recording',
' participant Fixture as snapshot fixture',
' participant Workspace',
' participant Replay as llm-replay adapter',
' participant ACP as acp-agent subprocess',
' participant Expected as stdout expected output',
' Recorder->>Fixture: session.jsonl + workspace inputs',
' Fixture->>Workspace: seed files and hook configs',
' Fixture->>Replay: recorded StreamChunk script',
` Replay->>ACP: deterministic ${mermaidCode('llm/stream')} chunks`,
' ACP->>Workspace: bash, fs, and hook side effects',
' ACP->>Expected: normalized sessionUpdate stream',
' Expected-->>ACP: diff must be empty',
'```',
'',
'The fs and hook snapshot matrix is valuable because it proves world state, hook decisions, and failed tool-card rendering, not just that replay returns text.',
'',
...maintenanceFooter(maintenance),
].join('\n')
}
function renderDocs(): GraphDoc[] {
const pkgs = collectPackageGraph(root, GROUP_ORDER, 'gen-doc-graphs')
const docs: GraphDoc[] = [
@@ -1076,7 +1046,6 @@ function renderDocs(): GraphDoc[] {
{ rel: 'docs/event-producer-consumer.md', content: renderEventRelations(pkgs) },
{ rel: 'docs/agent-lifecycle.md', content: renderLifecycle() },
{ rel: 'docs/tool-execution-pipeline.md', content: renderToolPipeline() },
{ rel: 'packages/ui/acp/snapshot-replay.md', content: renderSnapshotReplay() },
]
docs.unshift({ rel: 'docs/graph-atlas.md', content: renderIndex(docs) })
return docs
@@ -1092,7 +1061,6 @@ function renderIndex(docs: GraphDoc[]): string {
'docs/event-producer-consumer.md': 'event producer/consumer matrix',
'docs/agent-lifecycle.md': 'agent turn and step lifecycle',
'docs/tool-execution-pipeline.md': 'tool execution pipeline',
'packages/ui/acp/snapshot-replay.md': 'ACP snapshot replay',
}
const modes: Record<string, string> = {
'docs/capability-seams.md': 'hybrid generated',
@@ -1103,7 +1071,6 @@ function renderIndex(docs: GraphDoc[]): string {
'docs/event-producer-consumer.md': 'hybrid generated',
'docs/agent-lifecycle.md': 'curated',
'docs/tool-execution-pipeline.md': 'curated',
'packages/ui/acp/snapshot-replay.md': 'curated',
}
const rows = [
'| [module dependency graph](module-graph.md) | `generated` |',

View File

@@ -38,6 +38,7 @@ const GROUP_ORDER = [
'session-query',
'session-title',
'support',
'acp',
'ui',
]

View File

@@ -354,7 +354,7 @@ const TOOL_PACKAGES: ToolPackage[] = [
await ctx.plugin(ToolTodo)
},
note:
'todo_write is session-owned state; UIs render the latest todo/write event as a checklist or ACP plan.',
'todo_write is session-owned state; UIs render the latest todo/write event as a checklist.',
},
{
pkg: '@deepseek-ai/dsh-tool-workflow',