Adds the snapshot-test harness and the keyless replay pipeline end-to-end. - snapshot-harness.ts: boots the real acp-agent subprocess via the cordis Loader (preserving TSX_TSCONFIG_PATH so unbuilt dsh-* imports resolve from a temp cwd), tees raw stdout into an SDK ClientSideConnection, interprets a per-scenario input.json DSL (initialize / newSession capturing the random sessionId / prompt / cancel), closes stdin to trigger graceful shutdown, and harvests the persisted session.jsonl. Failure-safe: a finally block SIGKILLs a live child, awaits its exit, and removes both temp dirs even on a thrown step or harvest. Raw bytes are buffered and decoded once (no multibyte split). - snapshot-normalize.ts (+ spec): two pure normalizers (stdout frames + session JSONL) scrub cwd, session ids / UUIDs, and JSON-RPC ids, and zero time / createdAt — but keep `seq` (deterministic by contract). normalizeStdout throws on a non-JSON line (the stdout-purity check). - start.ts: selects cordis.snapshot.yml (replay, providerless) or cordis.snapshot-record.yml (record, real adapter) from DSH_SNAPSHOT, skips .env in replay, and disposes the ctx on stdin end so persistence flushes before exit (harvest-after-flush, not on the prompt response). - acp.snapshot.ts: asserts the normalized stdout golden (and, for model scenarios, the re-persisted JSONL golden) via toMatchFileSnapshot; record mode writes the harvested log back to the scenario fixture; an orphan-fixture guard fails on an unregistered scenario dir. - handshake scenario: initialize + session/new (no model call; a header-only session.jsonl, since session/new persists no events). - vitest.snapshot.config.ts, test:snapshot / test:snapshot:record scripts, a pre-push snapshot job, and the knip entry. Incorporates Codex review: record-fixture writeback, failure-safe teardown, seq-not-scrubbed, harvest-after-flush. Per docs/rfc/implemented/2026-06-19.
70 lines
2.1 KiB
YAML
70 lines
2.1 KiB
YAML
# Snapshot-test REPLAY config: the acp-agent plugin tree with the model replaced
|
|
# by llm-replay (serves a recorded session JSONL — no API key, no network).
|
|
#
|
|
# This does NOT include ../base.yml: base.yml always loads
|
|
# @deepseek-ai/dsh-llm-deepseek, whose apply() throws without DEEPSEEK_API_KEY,
|
|
# so a keyless replay run would die at boot. We inline the providerless core
|
|
# instead and install llm-replay where the adapter would be.
|
|
#
|
|
# stdout is reserved for the ACP JSON-RPC protocol — no stdout logger (see
|
|
# cordis.yml). The replay fixture path comes from $DSH_SNAPSHOT_FILE (and an
|
|
# optional $DSH_SNAPSHOT_OVERRIDE sidecar), set by the snapshot harness.
|
|
|
|
- id: timer
|
|
name: '@cordisjs/plugin-timer'
|
|
|
|
# Providerless core (everything base.yml has EXCEPT llm-deepseek).
|
|
- id: llm
|
|
name: '@deepseek-ai/dsh-llm'
|
|
|
|
- id: sessions
|
|
name: '@deepseek-ai/dsh-session'
|
|
|
|
- id: system-prompt
|
|
name: '@deepseek-ai/dsh-system-prompt'
|
|
|
|
- id: tools
|
|
name: '@deepseek-ai/dsh-tools'
|
|
|
|
- id: agents
|
|
name: '@deepseek-ai/dsh-agent'
|
|
|
|
- id: invariants
|
|
name: '@deepseek-ai/dsh-invariants'
|
|
|
|
- id: bash
|
|
name: '@deepseek-ai/dsh-bash-local'
|
|
config:
|
|
timeoutMs: 60000
|
|
|
|
- id: tool-bash
|
|
name: '@deepseek-ai/dsh-tool-bash'
|
|
|
|
# The replay adapter: short-circuits llm/stream with the recorded log's chunks.
|
|
- id: llm-replay
|
|
name: './src/llm-replay.ts'
|
|
|
|
- id: agent-loop
|
|
name: '@deepseek-ai/dsh-agent-loop'
|
|
config:
|
|
agents: []
|
|
|
|
- id: session-persistence
|
|
name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
|
config:
|
|
root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT
|
|
|
|
- id: acp
|
|
name: '@deepseek-ai/dsh-acp'
|
|
config:
|
|
model: deepseek-v4-flash
|
|
systemPrompt: |
|
|
You are a coding assistant driven over the Agent Client Protocol.
|
|
|
|
Your only tools are bash (plus bash_output/bash_kill for background
|
|
tasks). Do ALL file operations through bash: read with cat/sed/head,
|
|
search with grep, write with heredocs (cat <<'EOF' > file), edit with
|
|
sed or a rewrite. Each bash call runs in a fresh shell — pass workdir
|
|
instead of cd. Check the [exit code: N] marker; verify your work. Keep
|
|
answers brief and factual.
|