Merge remote-tracking branch 'origin/master' into worktree/acp-automation-protocol

# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.md
#	.agents/notes/implemented/architecture/2026-06-20-package-hierarchy.md
#	.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.md
#	.agents/notes/implemented/feature/2026-06-14-acp-multi-session.md
#	.agents/notes/implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.md
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-trim-acp-bridge-unreachable-surface.md
#	docs/architecture.i18n.yaml
#	docs/cookbook/extension-cookbook.i18n.yaml
#	docs/cookbook/extension-cookbook.md
#	docs/cookbook/extension-cookbook.zh.md
#	docs/core-data-structures/approval.md
#	docs/core-data-structures/user-interaction.md
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	docs/testing.md
#	docs/tool-catalog.md
#	examples/acp-agent/tests/fixtures/live-mode-switching-2026-07-07.session.jsonl
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl
#	examples/acp-agent/tests/snapshots/permission-switching/session.jsonl
#	packages/goal/tool-goal/README.md
#	packages/ui/acp/README.md
#	packages/ui/acp/acp-feature-support.md
#	packages/ui/acp/src/index.ts
#	packages/ui/acp/tests/bridge.spec.ts
#	packages/ui/acp/tests/dispose.spec.ts
#	packages/ui/acp/tests/edges.spec.ts
#	packages/ui/acp/tests/turns.spec.ts
This commit is contained in:
Tianyi Cui
2026-07-24 23:43:10 +08:00
829 changed files with 23607 additions and 1815 deletions

View File

@@ -114,7 +114,7 @@ describe('real Loader composition', () => {
loaded.llm.registerAdapter(['mock'], adapter)
const agent = loaded.agentLoop.create(SessionId('loader-retry'), { provider: 'mock', model: 'mock' })
const idle = waitForIdle(loaded, agent)
agent.send([{ type: 'text', text: 'recover' }])
agent.followup([{ type: 'text', text: 'recover' }])
await idle
expect(adapter.requests).toBe(2)

View File

@@ -129,7 +129,7 @@ describe('bounded transient retry policy', () => {
})
})
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
const event = await scheduled
expect(event.data).toEqual({
@@ -178,7 +178,7 @@ describe('bounded transient retry policy', () => {
const agent = context.agentLoop.create(SessionId('retry-partial'), { provider: 'mock', model: 'mock' })
const scheduled = waitForRetry(context, agent, 1)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await scheduled
const idle = waitForIdle(context, agent)
await vi.advanceTimersByTimeAsync(500)
@@ -213,7 +213,7 @@ describe('bounded transient retry policy', () => {
const agent = context.agentLoop.create(SessionId('retry-exhausted'), { provider: 'mock', model: 'mock' })
const first = waitForRetry(context, agent, 1)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
expect((await first).data.delayMs).toBe(450)
const second = waitForRetry(context, agent, 2)
@@ -246,7 +246,7 @@ describe('bounded transient retry policy', () => {
const agent = context.agentLoop.create(SessionId('retry-zero-delay'), { provider: 'mock', model: 'mock' })
const scheduled = waitForRetry(context, agent, 1)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
expect((await scheduled).data.delayMs).toBe(0)
const idle = waitForIdle(context, agent)
@@ -264,7 +264,7 @@ describe('bounded transient retry policy', () => {
;({ ctx: context } = await harness(accepted, { jitterRatio: 1 }))
const acceptedAgent = context.agentLoop.create(SessionId('retry-after-accepted'), { provider: 'mock', model: 'mock' })
const scheduled = waitForRetry(context, acceptedAgent, 1)
acceptedAgent.send([{ type: 'text', text: 'go' }])
acceptedAgent.followup([{ type: 'text', text: 'go' }])
expect((await scheduled).data.delayMs).toBe(2_000)
const acceptedIdle = waitForIdle(context, acceptedAgent)
await vi.advanceTimersByTimeAsync(2_000)
@@ -278,7 +278,7 @@ describe('bounded transient retry policy', () => {
;({ ctx: context } = await harness(rejected))
const rejectedAgent = context.agentLoop.create(SessionId('retry-after-rejected'), { provider: 'mock', model: 'mock' })
const rejectedIdle = waitForIdle(context, rejectedAgent)
rejectedAgent.send([{ type: 'text', text: 'go' }])
rejectedAgent.followup([{ type: 'text', text: 'go' }])
await rejectedIdle
expect(rejected.requests).toHaveLength(1)
expect(rejectedAgent.session.events.some(event => event.type === 'llm/retry')).toBe(false)
@@ -290,7 +290,7 @@ describe('bounded transient retry policy', () => {
;({ ctx: context } = await harness(adapter))
const agent = context.agentLoop.create(SessionId('retry-auth'), { provider: 'mock', model: 'mock' })
const idle = waitForIdle(context, agent)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await idle
expect(adapter.requests).toHaveLength(1)
expect(agent.session.events.some(event => event.type === 'llm/retry')).toBe(false)
@@ -307,7 +307,7 @@ describe('bounded transient retry policy', () => {
context = mounted.ctx
const agent = context.agentLoop.create(SessionId('retry-hmr'), { provider: 'mock', model: 'mock' })
const scheduled = waitForRetry(context, agent, 1)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await scheduled
const idle = waitForIdle(context, agent)
@@ -335,7 +335,7 @@ describe('bounded transient retry policy', () => {
model: 'mock',
})
const idle = waitForIdle(context, agent)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await entered.promise
const disposing = mounted.retryFiber.dispose()
@@ -376,7 +376,7 @@ describe('bounded transient retry policy', () => {
model: 'mock',
})
const idle = waitForIdle(context, agent)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await captured.promise
await mounted.retryFiber.dispose()
@@ -397,7 +397,7 @@ describe('bounded transient retry policy', () => {
;({ ctx: context } = await harness(adapter))
const agent = context.agentLoop.create(SessionId('retry-cancel'), { provider: 'mock', model: 'mock' })
const scheduled = waitForRetry(context, agent, 1)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await scheduled
const idle = waitForIdle(context, agent)
agent.cancel({ kind: 'user' })
@@ -426,7 +426,7 @@ describe('bounded transient retry policy', () => {
const agent = context.agentLoop.create(SessionId('retry-pre-cancel'), { provider: 'mock', model: 'mock' })
const idle = waitForIdle(context, agent)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await idle
expect(adapter.requests).toHaveLength(1)
@@ -450,7 +450,7 @@ describe('bounded transient retry policy', () => {
})
const idle = waitForIdle(context, agent)
agent.send([{ type: 'text', text: 'go' }])
agent.followup([{ type: 'text', text: 'go' }])
await idle
expect(adapter.requests).toHaveLength(1)