refactor(acp): trim unreachable bridge surface (branding knobs, kind-sniffing fallback)

Two pieces of dsh-acp surface were unreachable from any shipped config:

- AcpConfig.agentName/agentVersion: the app package hands the bridge only
  { model, systemPrompt }, so no leaf cordis.yml could set them; they were
  settable only by direct-mounting the bridge (a unit test). Hardcode
  agentInfo at the initialize site and delete the fields, their schema
  defaults, the ?? fallbacks, and the TODO(double-default) whose subject
  vanishes. The handshake wire value is unchanged (all snapshot initialize
  lines byte-identical).

- The toolKindFor name heuristic special-cased bash*/read*/write/edit*
  names in the generic-fallback path, violating the bridge's own design
  rule ("the bridge never special-cases tool names"). Every first-party
  tool ships its kind via presentCall; the fallback now renders the
  neutral kind 'other'. The fallback is reachable when a presentCall
  throws OR when model args fail the tool schema (defineTool's presentCall
  wrapper returns undefined on violations) — the latter shows up in one
  committed golden (hook-codex-posttool-block: three bash calls missing
  the required description), whose kind cells flip execute->other. That
  3-line golden refresh is the whole transcript delta.

The empty-arguments branch of parseToolArguments lost its only exercise
with the deleted heuristic test; it is live behavior (JSON.parse('')
throws, so the guard is what renders a zero-arg call as rawInput {}), so
it gets a dedicated pin instead of deletion.

RFC moved to docs/rfc/implemented/simplification/ and amended to shipped
reality: fallback reachability includes schema-invalid args, and the
golden churn is exactly the three kind cells (the original zero-churn
claim held only for the branding half).
This commit is contained in:
Tianyi Cui
2026-07-04 15:46:11 +08:00
parent 226a8b5e4c
commit 4036300353
10 changed files with 62 additions and 80 deletions
+4 -5
View File
@@ -33,7 +33,7 @@ describe('acp bridge', () => {
expect(res.protocolVersion).toBe(PROTOCOL_VERSION)
expect(res.agentCapabilities?.loadSession).toBe(true)
expect(res.agentCapabilities?.promptCapabilities).toMatchObject({ image: false, audio: false })
expect(res.agentInfo?.name).toBe('deepseek-harness-acp')
expect(res.agentInfo).toEqual({ name: 'deepseek-harness-acp', version: '0.0.1' })
})
it('session/new creates a session and a full prompt turn streams text then settles end_turn', async () => {
@@ -148,14 +148,13 @@ describe('acp bridge', () => {
await expect(harness.client.authenticate({ methodId: 'whatever' })).resolves.toBeDefined()
})
it('honors agentName/agentVersion/systemPrompt config', async () => {
it('honors systemPrompt config', async () => {
harness = await makeBridgeHarness({
storageDir,
script: [textResponse('ok')],
config: { agentName: 'custom-agent', agentVersion: '9.9.9', systemPrompt: 'be terse' },
config: { systemPrompt: 'be terse' },
})
const res = await harness.client.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: {} })
expect(res.agentInfo).toMatchObject({ name: 'custom-agent', version: '9.9.9' })
await harness.client.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: {} })
// Create + prompt so the systemPrompt config flows through agentOptions and
// reaches the model request.
const { sessionId } = await harness.client.newSession({ cwd: process.cwd(), mcpServers: [] })