Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine
# Conflicts: # .agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.md # .agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.zh.md # .agents/notes/implemented/feature/2026-06-30-hook-bridges.i18n.yaml # .agents/notes/implemented/feature/2026-06-30-interception-seams.i18n.yaml # .agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml # .agents/notes/implemented/feature/2026-07-06-sandbox.md # .agents/notes/implemented/feature/2026-07-06-sandbox.zh.md # .agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.i18n.yaml # .agents/notes/implemented/feature/2026-07-25-workspace-ui-product-flow.i18n.yaml # .agents/notes/implemented/simplification/2026-07-02-remove-stream-chunk-mirror.i18n.yaml # docs/architecture.i18n.yaml # docs/cookbook/adding-a-tool.i18n.yaml # docs/cookbook/extension-cookbook.i18n.yaml # docs/core-data-structures/llm-streaming.i18n.yaml # docs/core-data-structures/session.i18n.yaml # docs/core-data-structures/tools.i18n.yaml # docs/event-producer-consumer.md # docs/persistence-catalog.md # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl # examples/acp-agent/tests/snapshots/escalation-approved/session.jsonl # examples/acp-agent/tests/snapshots/escalation-rejected/session.jsonl # examples/acp-agent/tests/snapshots/fs-escalation-approved/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/permission-switching/session.jsonl # examples/acp-agent/tests/snapshots/plan-mode-reject/session.jsonl # examples/acp-agent/tests/snapshots/plan-mode/session.jsonl # examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl # packages/context/session-reference/README.md # packages/core/agent-loop/tests/agent.spec.ts # packages/hooks/hooks-claude/tests/coverage-cases.ts # packages/host/runtime/tests/host-runtime.spec.ts # packages/llm/llm-retry/tests/retry.spec.ts # packages/session-persistence/session-persistence/src/coordinator.ts # packages/support/acp-snapshot/README.md # packages/support/acp-snapshot/src/normalize.ts # packages/ui/acp/acp-feature-support.md # packages/ui/acp/src/codec.ts # packages/ui/acp/src/index.ts # packages/ui/acp/tests/bridge.spec.ts # packages/ui/acp/tests/codec.spec.ts # packages/ui/acp/tests/config-options.spec.ts # packages/ui/acp/tests/dispose.spec.ts # packages/ui/acp/tests/edges.spec.ts # packages/ui/acp/tests/stream-update.spec.ts # packages/ui/acp/tests/turns.spec.ts
This commit is contained in:
@@ -45,6 +45,24 @@ describe('normalizeStdout', () => {
|
||||
expect(out).not.toContain(ctx.sessionIds[0] as string)
|
||||
})
|
||||
|
||||
it('scrubs every filesystem spelling of the cwd longest-first', () => {
|
||||
const longCwd = String.raw`C:\Users\runneradmin\AppData\Local\Temp\acp-snapshot`
|
||||
const aliasedCtx: NormalizeContext = {
|
||||
sessionIds: [],
|
||||
cwd: String.raw`C:\Users\RUNNER~1\AppData\Local\Temp\acp-snapshot`,
|
||||
cwdAliases: [
|
||||
longCwd,
|
||||
String.raw`C:\Users\runneradmin\AppData\Local\Temp\acp`,
|
||||
],
|
||||
}
|
||||
const raw = JSON.stringify({
|
||||
cwd: longCwd,
|
||||
path: `${longCwd}\\nested\\proof.txt`,
|
||||
})
|
||||
const frame = JSON.parse(normalizeStdout(raw, aliasedCtx)) as { cwd: string; path: string }
|
||||
expect(frame).toEqual({ cwd: '{{cwd}}', path: '{{cwd}}/nested/proof.txt' })
|
||||
})
|
||||
|
||||
it('canonicalizes only cwd-rooted path separators', () => {
|
||||
const windowsCtx: NormalizeContext = {
|
||||
sessionIds: [],
|
||||
@@ -106,22 +124,54 @@ Additional instructions from: nested\AGENTS.md`,
|
||||
expect(out).not.toContain('"id"')
|
||||
})
|
||||
|
||||
it('stabilizes the timestamp carried by session title updates', () => {
|
||||
it('stabilizes only the top-level event timestamp and spill byte count in event-read text', () => {
|
||||
const raw = JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'session/update',
|
||||
params: {
|
||||
sessionId: ctx.sessionIds[0],
|
||||
update: {
|
||||
sessionUpdate: 'session_info_update',
|
||||
title: 'Stable title',
|
||||
updatedAt: '2026-07-20T17:03:13.689Z',
|
||||
sessionUpdate: 'tool_call_update',
|
||||
content: [{
|
||||
type: 'content',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: 'Session prior — title\nTarget event seq 4:\n```json\n{\n "seq": 4,\n "time": 1784876275593,\n "data": {\n "time": 31337,\n "note": "model-visible"\n }\n}\n```\n\nAfter:\n "time": 424242,\n neighbor semantic text\n\n(Omitted 39387 bytes. Full formatted result stored at: /tmp/result.txt.)',
|
||||
},
|
||||
}],
|
||||
},
|
||||
},
|
||||
})
|
||||
const out = normalizeStdout(raw, ctx)
|
||||
expect(out).toContain('"updatedAt":"{{updatedAt}}"')
|
||||
expect(out).not.toContain('2026-07-20T17:03:13.689Z')
|
||||
expect(out).toContain('\\"time\\": {{eventTime}}')
|
||||
expect(out).toContain('\\"time\\": 31337')
|
||||
expect(out).toContain('\\"time\\": 424242')
|
||||
expect(out).toContain('Omitted {{eventOmittedBytes}} bytes')
|
||||
expect(out).not.toContain('1784876275593')
|
||||
expect(out).not.toContain('39387')
|
||||
})
|
||||
|
||||
it('preserves event-like timestamps in unrelated output text', () => {
|
||||
const raw = JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'session/update',
|
||||
params: {
|
||||
update: {
|
||||
sessionUpdate: 'tool_call_update',
|
||||
content: [{
|
||||
type: 'content',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: 'bash output:\n```json\n{\n "time": 1784876275593,\n "data": {}\n}\n```\n\n(Omitted 39387 bytes. Full formatted result stored at: /tmp/result.txt.)',
|
||||
},
|
||||
}],
|
||||
},
|
||||
},
|
||||
})
|
||||
const out = normalizeStdout(raw, ctx)
|
||||
expect(out).toContain('1784876275593')
|
||||
expect(out).toContain('39387')
|
||||
expect(out).not.toContain('{{eventTime}}')
|
||||
expect(out).not.toContain('{{eventOmittedBytes}}')
|
||||
})
|
||||
|
||||
it('throws on a non-JSON stdout line (the purity check)', () => {
|
||||
|
||||
Reference in New Issue
Block a user