Merge remote-tracking branch 'origin/master' into session-query-tool
# Conflicts: # docs/core-data-structures/persistence.i18n.yaml # packages/session-persistence/session-persistence-jsonl/src/index.ts
This commit is contained in:
41
examples/acp-agent/retry.cordis.snapshot.yml
Normal file
41
examples/acp-agent/retry.cordis.snapshot.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
# Keyless replay for the retry overlay: disable the key-requiring DeepSeek
|
||||
# adapter, insert `llm-replay`, and restate the app config with the same
|
||||
# deterministic 1 ms zero-jitter retry policy as the live sibling. A config
|
||||
# patch replaces the whole app config, so the base fields are restated
|
||||
# verbatim (raw JSONL persistence so the harness can harvest the log).
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
path: ./cordis.yml
|
||||
patches:
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
disabled: true
|
||||
- id: acp-agent
|
||||
name: '@deepseek-ai/dsh-acp-demo'
|
||||
config:
|
||||
provider: deepseek
|
||||
model: deepseek-v4-flash
|
||||
persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
|
||||
persistenceCompression: none
|
||||
workspaceContext:
|
||||
maxBytes: 65536
|
||||
llmRetry:
|
||||
maxTransientRetries: 2
|
||||
initialDelayMs: 1
|
||||
maxDelayMs: 1
|
||||
jitterRatio: 0
|
||||
persona: |
|
||||
You are a coding assistant powered by the {{model}} model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
- insert:
|
||||
- id: llm-replay
|
||||
name: '@deepseek-ai/dsh-llm-replay'
|
||||
config:
|
||||
providers:
|
||||
- id: deepseek
|
||||
name: DeepSeek
|
||||
models:
|
||||
- id: deepseek-v4-flash
|
||||
- id: deepseek-v4-pro
|
||||
30
examples/acp-agent/retry.cordis.yml
Normal file
30
examples/acp-agent/retry.cordis.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
# Retry-scenario overlay: pin the bounded transient retry policy to a
|
||||
# deterministic 1 ms zero-jitter delay so the durable `llm/retry` event
|
||||
# (`delayMs`) and replay wall time stay reproducible. The overlay changes no
|
||||
# tool or prompt composition, so its scenarios share the default header class.
|
||||
# A config patch replaces the whole app config, so the base fields are restated
|
||||
# verbatim; the model is re-pinned to `deepseek-v4-flash` like the other
|
||||
# snapshot overlays because the recorded corpus was captured on flash.
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
path: ./cordis.yml
|
||||
patches:
|
||||
- id: acp-agent
|
||||
name: '@deepseek-ai/dsh-acp-demo'
|
||||
config:
|
||||
provider: deepseek
|
||||
model: deepseek-v4-flash
|
||||
persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
|
||||
persistenceCompression: !!js "process.env.DSH_SNAPSHOT === undefined ? 'zstd' : 'none'"
|
||||
workspaceContext:
|
||||
maxBytes: 65536
|
||||
llmRetry:
|
||||
maxTransientRetries: 2
|
||||
initialDelayMs: 1
|
||||
maxDelayMs: 1
|
||||
jitterRatio: 0
|
||||
persona: |
|
||||
You are a coding assistant powered by the {{model}} model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
@@ -114,7 +114,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('acp-agent e2e: real prompt over
|
||||
})
|
||||
expect(['end_turn', 'max_tokens']).toContain(res.stopReason)
|
||||
|
||||
// Verify the WORLD, not the agent's self-report: read the file from disk.
|
||||
// Assert the filesystem effect independently of the model response.
|
||||
const proof = await readFile(join(workdir, 'proof.txt'), 'utf8')
|
||||
expect(proof).toContain('ACP_OK')
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ const PTY_CONFIG = fileURLToPath(new URL('../pty.cordis.yml', import.meta.url))
|
||||
const DEPTH_TWO_CONFIG = fileURLToPath(new URL('../depth-two.cordis.yml', import.meta.url))
|
||||
const PACKED_CHUNKS_CONFIG = fileURLToPath(new URL('../packed-chunks.cordis.yml', import.meta.url))
|
||||
const SESSION_SANDBOX_ROOT_CONFIG = fileURLToPath(new URL('../session-sandbox-root.cordis.yml', import.meta.url))
|
||||
const RETRY_CONFIG = fileURLToPath(new URL('../retry.cordis.yml', import.meta.url))
|
||||
const LSP_CONFIG = fileURLToPath(new URL('./lsp.cordis.yml', import.meta.url))
|
||||
const SNAPSHOTS_DIR = join(dirname(fileURLToPath(import.meta.url)), 'snapshots')
|
||||
const PACKED_CHUNKS_SOURCE = 'hook-cc-pretool-deny'
|
||||
@@ -119,6 +120,14 @@ const SCENARIOS: Scenario[] = [
|
||||
{ name: 'fs-policy-reject', hasModelTurn: true, recorded: true },
|
||||
{ name: 'multi-turn', hasModelTurn: true, recorded: true },
|
||||
{ name: 'error-finish', hasModelTurn: true, recorded: false, overridden: true },
|
||||
// Keyless, authored (like error-finish): a live provider cannot be coaxed
|
||||
// into a degenerate empty completion, so the fixture scripts the adapters'
|
||||
// EMPTY_RESPONSE error finish (step 1) followed by the recovered reply
|
||||
// (step 2), proving the default retry policy end to end: the durable
|
||||
// llm/retry event, no ACP output for the discarded attempt, the recovered
|
||||
// reply, and a clean completed turn. Its overlay only pins a deterministic
|
||||
// 1 ms zero-jitter delay, so it shares the default header class.
|
||||
{ name: 'empty-response-retry', hasModelTurn: true, recorded: false, configPath: RETRY_CONFIG },
|
||||
// Keyless, authored (like error-finish/cancel): deterministically forcing a
|
||||
// LIVE model to repeat one call three times is not a stable recording, so
|
||||
// the fixture scripts five identical todo_write calls and pins BOTH reminder
|
||||
|
||||
@@ -62,7 +62,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('acp-agent e2e: a PreToolUse hook
|
||||
// the model, not a turn failure).
|
||||
expect(['end_turn', 'max_tokens']).toContain(res.stopReason)
|
||||
|
||||
// Verify that the denied hook left no filesystem effect.
|
||||
// Assert the denied operation independently of the model response.
|
||||
await expect(access(join(workdir, 'proof.txt'))).rejects.toThrow()
|
||||
|
||||
// ACP publishes only the committed answer; hook/tool trace stays in the session log.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"steps": [
|
||||
{ "op": "initialize" },
|
||||
{ "op": "newSession" },
|
||||
{ "op": "prompt", "text": "This prompt first receives an empty completion, then a retried reply." }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{"type":"session","version":0,"id":"{{sessionId}}","createdAt":0,"cwd":"{{cwd}}","delegationDepth":0}
|
||||
{"type":"turn/start","seq":0,"time":0,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
|
||||
{"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"This prompt first receives an empty completion, then a retried reply."}],"source":{"kind":"user"}},"surfaceOp":"append"}
|
||||
{"type":"session/title","seq":2,"time":0,"data":{"title":"This prompt first receives an","messageSeqs":[1],"source":{"kind":"fallback"}}}
|
||||
{"type":"step/start","seq":3,"time":0,"data":{"turn":1,"step":1}}
|
||||
{"type":"request/header","seq":4,"time":0,"data":{"header":{"config":{"provider":"deepseek","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
|
||||
{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":0,"outputTokens":0}}}}
|
||||
{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"error","failure":{"message":"model returned a completed response with no content","code":"EMPTY_RESPONSE"}}}}}
|
||||
{"type":"step/end","seq":7,"time":0,"data":{"turn":1,"step":1}}
|
||||
{"type":"llm/retry","seq":8,"time":0,"data":{"turn":1,"step":1,"retry":1,"maxRetries":2,"delayMs":1,"failure":{"message":"model returned a completed response with no content","code":"EMPTY_RESPONSE"}}}
|
||||
{"type":"step/start","seq":9,"time":0,"data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
|
||||
{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"Recovered."}}}
|
||||
{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"Recovered."}}}}
|
||||
{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":12,"outputTokens":3}}}}
|
||||
{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
|
||||
{"type":"assistant/message","seq":15,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"text","text":"Recovered."}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":12,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"}
|
||||
{"type":"step/end","seq":16,"time":0,"data":{"turn":1,"step":2}}
|
||||
{"type":"turn/end","seq":17,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}
|
||||
@@ -0,0 +1,4 @@
|
||||
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}}
|
||||
{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}"}}
|
||||
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Recovered."}}}}
|
||||
{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn"}}
|
||||
Reference in New Issue
Block a user