@monotykamary/dsh-acp-snapshot 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +3 -3
- package/README.md +4 -4
- package/README.zh.md +4 -4
- package/lib/index.js +14 -10
- package/lib/types/index.d.ts +1 -1
- package/package.json +8 -8
- package/LICENSE +0 -21
package/README.i18n.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
|
-
#
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
4
|
+
# bun run verify-translation-pairing --write packages/test-support/acp-snapshot/README.md
|
|
5
|
+
README.md: f56edd8551d6403dffac03b43747bada1ec95934
|
|
6
|
+
README.zh.md: c6399d28e9d1775f0b08c05cea4995d4bb952c8c
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
The ACP snapshot suite kit: the shared machinery behind the keyless snapshot tier (`
|
|
5
|
+
The ACP snapshot suite kit: the shared machinery behind the keyless snapshot tier (`bun run test:snapshot`, [testing policy](../../../docs/testing.md)). An example gets a full snapshot suite from a scenario table plus a fixtures directory; every compare/guard mechanic lives here, under the per-file coverage gate, instead of being copied per example.
|
|
6
6
|
|
|
7
7
|
Four layers, importable separately:
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ Four layers, importable separately:
|
|
|
11
11
|
- **Normalizers** — pure functions turning captured surfaces into stable text or portable fixtures: `normalizeStdout` (JSON-RPC ids → first-seen sequence; UUIDs and every native/JavaScript filesystem spelling of the generated cwd → tokens, longest-first; cwd-rooted separators selected as canonical `/` or host-native; doubles as the stdout-purity check), `normalizeSessionLog` (sequence envelopes retained, times zeroed, the same cwd-path policy), `normalizeSessionSnapshot` (session-log normalization followed by request-header scrubbing and body-envelope projection), `tokenizeSessionFixtureCwd` (the generated workspace and its filesystem aliases → one canonical `{{cwd}}`, including an already-tokenized macOS `/private` alias; authored temp paths unchanged), `scrubSystemPrompts` (prompt text → `{{system}}`), `scrubToolSchemas` (schema bulk → `{{tools}}`), `scrubRequestHeaders` (all header bulk → `{{system}}`/`{{tools}}`/`{{messagePrefix}}` outside each pin, structure kept — [pinned-header Agent Note](../../../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md)), and `stabilizeFixtureMessageIds` (committed UUIDs carried into unchanged, mutually unique messages by structurally rewriting only complete surface and durable-inbox message ID fields across any recorder's fixture-ready parent/child logs).
|
|
12
12
|
- **`defineAcpSnapshotSuite` (factory)** — registers the whole describe/it tree for a scenario table: per-scenario expected-output and re-persisted-log comparisons, record/refresh fixture write-back, rejection of structured `UNKNOWN_TOOL` results, a tokenized pin per header class composed with independently shared `system-prompt.expected.md` and `tool-schemas.expected.json` sidecars, and a live uniformity guard. Its fixture guards reject orphan scenario dirs, missing files, multiple pins for one class, duplicate sidecar content, noncanonical macOS-prefixed cwd tokens, unscrubbed JSONL headers, and malformed pinning headers. Before record or refresh writes fixtures, an unchanged complete message retains its committed UUID only when both its ID and identity-free fingerprint are unique across the scenario's fixture-ready parent/child logs; the session package's authoritative surface-type predicate selects surface carriers, correlated `agent/inbox/spliced` copies join the same mapping, and only validated `id` fields in those carriers are rewritten. New, changed, malformed, and graph-ambiguous messages keep fresh UUIDs. Refresh evaluates fresh leaves with the harvested run's ids, cwd, and every cwd alias, then reuses normalized-equivalent leaves only when the complete logical-record layout aligns and volatile string replacements form a bijection; complete message IDs in surface or inbox carriers are excluded because the later structural pass owns them, ambiguous logs keep fresh strings, and fresh semantic values remain authoritative. It also expands packed timing envelopes before aligning event times, so switching between packed and unpacked layouts cannot shift later records. A newly inserted `session/title` receives its preceding event's time so feature-driven insertions do not churn the remainder of a fixture. Each scenario directory's `session.jsonl` plus contiguous `session.<n>.jsonl` siblings are the ordered primary/child inventory; the scenario table does not duplicate their count. Must be called at vitest collection time.
|
|
13
13
|
|
|
14
|
-
Committed session fixtures retain their complete session header and event payloads but omit ordinary `seq`/`time` and packed-row `seq0`/`time0` envelopes. Replay synthesizes those envelopes in memory; runtime persistence remains unchanged. Fixtures also use canonical packed rows; the [temporary repository migrator](../../../scripts/migrate-packed-session-fixtures.ts) (`
|
|
14
|
+
Committed session fixtures retain their complete session header and event payloads but omit ordinary `seq`/`time` and packed-row `seq0`/`time0` envelopes. Replay synthesizes those envelopes in memory; runtime persistence remains unchanged. Fixtures also use canonical packed rows; the [temporary repository migrator](../../../scripts/migrate-packed-session-fixtures.ts) (`bun run migrate:packed-session-fixtures`) rewrites older fixture layouts, and its [removal proposal](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.md) owns its deletion.
|
|
15
15
|
|
|
16
16
|
A consuming `*.snapshot.ts` is the scenario table plus one factory call:
|
|
17
17
|
|
|
@@ -59,7 +59,7 @@ A child session whose own scope composes a different request declares it per fix
|
|
|
59
59
|
|
|
60
60
|
Every scenario compares `stdout.expected.jsonl` with cwd-rooted separators canonicalized to `/`. On Windows, `pinsNativeWindowsStdout` additionally compares the complete `stdout.expected.windows.jsonl` after the shared expected output and requires that sidecar exactly when enabled. A scenario requiring a non-Windows host declares `posixOnly`, which skips its run test on Windows while the fixture guards keep covering its committed files everywhere; examples include POSIX process semantics (e.g. cancelling a live bash call kills a detached process group) and generated paths Windows cannot represent. A scenario whose composition needs a usable `pwsh` declares `pwshOnly`; the caller-supplied `hasPwsh` probe (the shipped acp-agent suite follows the executor's own resolution, so Program Files installs count) skips the run test when no usable `pwsh` resolves while the fixture guards keep covering its committed files everywhere.
|
|
61
61
|
|
|
62
|
-
The example also ships a `cordis.snapshot.yml` replay overlay next to its `cordis.yml` (the bin swaps them under `DSH_SNAPSHOT=replay` — [single-source replay config Agent Note](../../../.agents/notes/archived/testing/2026-07-04-single-source-acp-replay-config.md)); replay fixtures are served by [`dsh-llm-replay`](../llm-replay/README.md), which this package points at via the `DSH_SNAPSHOT_*` env vars it sets on the child. `
|
|
62
|
+
The example also ships a `cordis.snapshot.yml` replay overlay next to its `cordis.yml` (the bin swaps them under `DSH_SNAPSHOT=replay` — [single-source replay config Agent Note](../../../.agents/notes/archived/testing/2026-07-04-single-source-acp-replay-config.md)); replay fixtures are served by [`dsh-llm-replay`](../llm-replay/README.md), which this package points at via the `DSH_SNAPSHOT_*` env vars it sets on the child. `bun run test:snapshot:record` calls the live LLM and rewrites the recorded scenarios' model fixtures; `bun run test:snapshot:refresh` stays keyless, runs the replay overlay, and rewrites stdout, comparable session-log expected outputs, and owned prompt and tool-schema sidecars from the committed model scripts. Fixture roles, record/replay/refresh semantics, and scenario-table fields are documented on `Scenario` and in the [snapshot Agent Note](../../../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md).
|
|
63
63
|
|
|
64
64
|
Constraints: `suite.ts` and `harness.ts` import vitest (the harness polls its durable-boundary waits through `vi.waitFor`), so the package entry is importable only inside a vitest run (the launcher and normalizers have no such dependency but ship from the same entry). The launcher and suite factory are ACP-specific by design — the launcher speaks the SDK's `ClientSideConnection` — while the normalizers are transport-neutral session-log/text helpers also consumed by the JSON-RPC and Web snapshot recorders. Input scripts cover initialization, fresh-session creation, shorthand text prompts, exact structured ACP prompt blocks, cancellation, expected RPC failures, and durable turn-boundary waits. Permission round-trips are a FIFO queue of option-kind selections (`allow_once`, `reject_once`, …) mapped to the agent-issued `optionId`; an absent or exhausted queue answers `cancelled`, and an unoffered kind rejects the run.
|
|
65
65
|
|
|
@@ -74,5 +74,5 @@ None; this package neither assembles nor sends a provider request.
|
|
|
74
74
|
## Known Limitations and Deferred Work
|
|
75
75
|
|
|
76
76
|
- **Session harvest requires raw JSONL mode** — `runScenario` collects persisted `.jsonl` logs, so snapshot configs set `persistenceCompression: 'none'`; compressed JSONL and SQLite compositions have no snapshot-harvest path.
|
|
77
|
-
- **Built mode requires current artifacts** — run `
|
|
77
|
+
- **Built mode requires current artifacts** — run `bun run build` before selecting `DSH_EXAMPLE_MODE=lib`; source mode remains the zero-build path.
|
|
78
78
|
- **Backend coverage still rides an ACP driver** — see the [automation-only ACP decision](../../../.agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.md#snapshot-boundary) for why retained scenarios use this transport.
|
package/README.zh.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
ACP(Agent Client Protocol)快照套件工具包:无密钥快照层(`
|
|
5
|
+
ACP(Agent Client Protocol)快照套件工具包:无密钥快照层(`bun run test:snapshot`,见[测试策略](../../../docs/testing.zh.md))背后的共享机制。示例只需场景表和 fixture(测试前置数据)目录就能获得完整快照套件;每项比较/保护机制都位于此处,受每文件覆盖率门禁约束,而不是在每个示例中复制。
|
|
6
6
|
|
|
7
7
|
四层可单独导入:
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ ACP(Agent Client Protocol)快照套件工具包:无密钥快照层(`pnpm
|
|
|
11
11
|
- **规范化器**:将已捕获内容转换为稳定文本或可移植 fixture 的纯函数:`normalizeStdout`(JSON-RPC id → 首次出现序列;UUID 以及生成 cwd 的每种原生/JavaScript 文件系统写法 → token,按最长优先;根据 cwd 的分隔符选择规范 `/` 或宿主原生形式;同时作为 stdout 纯度检查)、`normalizeSessionLog`(保留序号 envelope、将时间归零,并使用同一 cwd 路径策略)、`normalizeSessionSnapshot`(依次执行会话日志规范化、request header 清理和正文 envelope 投影)、`tokenizeSessionFixtureCwd`(生成的 workspace 及其文件系统别名,包括已进行 token 化的 macOS `/private` 别名 → 单一规范 `{{cwd}}`;手工编写的临时路径保持不变)、`scrubSystemPrompts`(提示词文本 → `{{system}}`)、`scrubToolSchemas`(schema bulk → `{{tools}}`)、`scrubRequestHeaders`(每个 pin 之外的所有 header bulk → `{{system}}`/`{{tools}}`/`{{messagePrefix}}`,保留结构;见[header 固定 Agent Note](../../../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md))和 `stabilizeFixtureMessageIds`(针对任意录制器已准备写入 fixture 的父级/子级日志,通过结构化方式仅改写 surface 和持久 inbox 中完整消息的 ID 字段,将已提交 UUID 带入未变化且双向唯一匹配的消息)。
|
|
12
12
|
- **`defineAcpSnapshotSuite`(工厂)**:为场景表注册完整 describe/it 树:每场景预期输出与重新持久化日志比较、录制/刷新 fixture 回写、拒绝结构化 `UNKNOWN_TOOL` 结果、每个 header 类别一个 token 化 pin(由可独立共享的 `system-prompt.expected.md` 和 `tool-schemas.expected.json` 伴随文件组合而成),以及实时一致性保护。其 fixture 保护会拒绝遗留场景目录、缺失文件、一个类别包含多个 pin、重复的伴随文件内容、带非规范 macOS 前缀的 cwd token、未擦除的 JSONL header,以及格式错误的 pin header。在录制或刷新模式写入 fixture 前,仅当一条未变化完整消息的 ID 及其去除身份后的指纹在场景可写入 fixture 的父级/子级日志中均唯一时,该消息才会保留已提交的 UUID;会话包的权威 surface 类型谓词负责选择 surface 载体,与其关联的 `agent/inbox/spliced` 副本也纳入同一映射,且仅改写这些载体中通过验证的 `id` 字段。新增、发生变化、格式错误以及图关系存在歧义的消息保留本次生成的 UUID。刷新会使用收集所得本次运行的 id、cwd 及全部 cwd 别名评估本次生成的叶值;只有完整逻辑记录布局对齐且易变字符串替换形成双射时,才会复用归一化后等价的叶值;surface 或 inbox 载体中的完整消息 ID 不参与此路径,因为后续结构化处理负责这些 ID;有歧义的日志保留本次生成的字符串,而本次生成的语义值仍为权威数据。它还会在对齐事件时间前展开打包时序 envelope,因此切换打包/非打包布局无法移动后续记录。新插入的 `session/title` 使用前一个事件的时间,因此功能驱动的插入不会扰动 fixture 余下部分。每个场景目录的 `session.jsonl` 和连续 `session.<n>.jsonl` 同级文件构成有序的主会话/子会话清单;场景表不重复其数量。必须在 vitest 收集时调用。
|
|
13
13
|
|
|
14
|
-
签入仓库的会话 fixture 保留完整会话 header 和事件 payload,但省略普通行的 `seq`/`time` 与打包行的 `seq0`/`time0` envelope。回放只在内存中合成这些 envelope;运行时持久化不变。fixture 同时使用规范打包行;[临时仓库迁移器](../../../scripts/migrate-packed-session-fixtures.ts)(`
|
|
14
|
+
签入仓库的会话 fixture 保留完整会话 header 和事件 payload,但省略普通行的 `seq`/`time` 与打包行的 `seq0`/`time0` envelope。回放只在内存中合成这些 envelope;运行时持久化不变。fixture 同时使用规范打包行;[临时仓库迁移器](../../../scripts/migrate-packed-session-fixtures.ts)(`bun run migrate:packed-session-fixtures`)会改写较旧的 fixture 布局,由其[移除提案](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.zh.md)负责删除该迁移器。
|
|
15
15
|
|
|
16
16
|
消费方 `*.snapshot.ts` 就是场景表加一次工厂调用:
|
|
17
17
|
|
|
@@ -59,7 +59,7 @@ defineAcpSnapshotSuite({
|
|
|
59
59
|
|
|
60
60
|
每个场景都比较 `stdout.expected.jsonl`,其中以 cwd 为根的分隔符规范化为 `/`。在 Windows 上,`pinsNativeWindowsStdout` 还会在共享预期输出之后比较完整 `stdout.expected.windows.jsonl`,并且仅在启用时要求存在该伴随文件。需要非 Windows 主机的场景声明 `posixOnly`,在 Windows 上跳过运行测试,但 fixture 保护仍在所有平台覆盖其已提交文件;示例包括 POSIX 进程语义(例如取消正在运行的 bash 调用会终止一个已脱离的进程组)和 Windows 无法表示的生成路径。组合需要可用 `pwsh` 的场景声明 `pwshOnly`;调用方提供的 `hasPwsh` 探测(随附的 acp-agent 套件遵循执行器自身的解析,因此 Program Files 安装也计入)在解析不到可用 `pwsh` 时跳过运行测试,而 fixture 保护仍处处覆盖其已提交文件。
|
|
61
61
|
|
|
62
|
-
示例还发布 `cordis.snapshot.yml` 回放 overlay,位于 `cordis.yml` 旁边(bin 在 `DSH_SNAPSHOT=replay` 下交换它们,见[单源回放配置 Agent Note](../../../.agents/notes/archived/testing/2026-07-04-single-source-acp-replay-config.md));回放 fixture 由 [`dsh-llm-replay`](../llm-replay/README.zh.md) 提供,本包通过为子进程设置的 `DSH_SNAPSHOT_*` env var 指向它。`
|
|
62
|
+
示例还发布 `cordis.snapshot.yml` 回放 overlay,位于 `cordis.yml` 旁边(bin 在 `DSH_SNAPSHOT=replay` 下交换它们,见[单源回放配置 Agent Note](../../../.agents/notes/archived/testing/2026-07-04-single-source-acp-replay-config.md));回放 fixture 由 [`dsh-llm-replay`](../llm-replay/README.zh.md) 提供,本包通过为子进程设置的 `DSH_SNAPSHOT_*` env var 指向它。`bun run test:snapshot:record` 调用在线 LLM(大语言模型),并重写已记录场景的模型 fixture;`bun run test:snapshot:refresh` 保持无密钥,运行回放 overlay,并从已提交模型脚本重写 stdout、可比较会话日志预期输出,以及各 pin 自有的提示词与工具 schema 伴随文件。Fixture 角色、录制/回放/刷新语义和场景表字段记录在 `Scenario` 以及[快照 Agent Note](../../../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.zh.md) 中。
|
|
63
63
|
|
|
64
64
|
约束:`suite.ts` 与 `harness.ts` 导入 vitest(harness 通过 `vi.waitFor` 轮询其持久边界等待),因此包入口只能在 vitest 运行中导入(启动器和规范化器没有此依赖,但从同一入口发布)。启动器和套件工厂按设计专用于 ACP,启动器使用 SDK 的 `ClientSideConnection`;规范化器是与传输无关的会话日志/文本辅助工具,还由 JSON-RPC 和 Web 快照录制器消费。输入脚本覆盖初始化、新建会话、文本提示简写、精确结构化 ACP 提示词块、取消、预期 RPC 失败和持久轮次边界等待。权限往返是选项类别选择(`allow_once`、`reject_once` 等)的 FIFO 队列,映射到 agent 发出的 `optionId`;缺少或耗尽的队列回答 `cancelled`,未提供类别会拒绝运行。
|
|
65
65
|
|
|
@@ -74,5 +74,5 @@ defineAcpSnapshotSuite({
|
|
|
74
74
|
## 已知限制与暂缓事项
|
|
75
75
|
|
|
76
76
|
- **会话收集需要原始 JSONL mode**:`runScenario` 收集持久化 `.jsonl` 日志,因此快照配置使用 `persistenceCompression: 'none'`;压缩 JSONL 和 SQLite 组合没有快照收集路径。
|
|
77
|
-
- **构建 mode 需要当前产物**:先运行 `
|
|
77
|
+
- **构建 mode 需要当前产物**:先运行 `bun run build`,再选择 `DSH_EXAMPLE_MODE=lib`;源 mode 仍是零构建路径。
|
|
78
78
|
- **后端覆盖仍使用 ACP 驱动器**:保留场景为何使用该传输,见[仅自动化 ACP 决策](../../../.agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.zh.md#snapshot-boundary)。
|
package/lib/index.js
CHANGED
|
@@ -244,7 +244,7 @@ function snapshotSpillRoot(fixtureFile, platform = process.platform) {
|
|
|
244
244
|
*/
|
|
245
245
|
async function runScenario(input, opts) {
|
|
246
246
|
const cwd = await mkdtemp(join(opts.workspaceParent ?? tmpdir(), "acp-snap-cwd-"));
|
|
247
|
-
const cwdAliases = [
|
|
247
|
+
const cwdAliases = [.../* @__PURE__ */ new Set([realpathSync(cwd), realpathSync.native(cwd)])];
|
|
248
248
|
const sessionsRoot = await mkdtemp(join(tmpdir(), "acp-snap-sessions-"));
|
|
249
249
|
const spillRoot = snapshotSpillRoot(opts.fixtureFile);
|
|
250
250
|
let launched;
|
|
@@ -678,7 +678,7 @@ const SYSTEM = "{{system}}";
|
|
|
678
678
|
const TOOLS = "{{tools}}";
|
|
679
679
|
const EVENT_TIME = "{{eventTime}}";
|
|
680
680
|
const EVENT_OMITTED_BYTES = "{{eventOmittedBytes}}";
|
|
681
|
-
const PACKED_CHUNK_ROW_TYPES$1 = new Set([
|
|
681
|
+
const PACKED_CHUNK_ROW_TYPES$1 = /* @__PURE__ */ new Set([
|
|
682
682
|
"text-chunks",
|
|
683
683
|
"reasoning-chunks",
|
|
684
684
|
"tool-call-chunks"
|
|
@@ -726,9 +726,9 @@ function canonicalizeEmbeddedPaths(value) {
|
|
|
726
726
|
}
|
|
727
727
|
/** Return every known spelling of the generated cwd, most specific first. */
|
|
728
728
|
function cwdSpellings(ctx) {
|
|
729
|
-
const spellings = [
|
|
729
|
+
const spellings = [.../* @__PURE__ */ new Set([ctx.cwd, ...ctx.cwdAliases ?? []])].filter((spelling) => spelling.length > 0);
|
|
730
730
|
const macAliases = spellings.filter((spelling) => spelling.startsWith("/") && !spelling.startsWith("/private/")).map((spelling) => `/private${spelling}`);
|
|
731
|
-
return [
|
|
731
|
+
return [.../* @__PURE__ */ new Set([...spellings, ...macAliases])].sort((left, right) => right.length - left.length);
|
|
732
732
|
}
|
|
733
733
|
/** Whether an embedded cwd match starts and ends at a path/text boundary. */
|
|
734
734
|
function isCwdMatch(value, start, length) {
|
|
@@ -1040,7 +1040,7 @@ function childSystemPromptSnapshot(index) {
|
|
|
1040
1040
|
const WINDOWS_STDOUT_SNAPSHOT = "stdout.expected.windows.jsonl";
|
|
1041
1041
|
/** Stable session-log token standing in for the sidecar's initial schemas. */
|
|
1042
1042
|
const TOOLS_TOKEN = "{{tools}}";
|
|
1043
|
-
const PACKED_CHUNK_ROW_TYPES = new Set([
|
|
1043
|
+
const PACKED_CHUNK_ROW_TYPES = /* @__PURE__ */ new Set([
|
|
1044
1044
|
"text-chunks",
|
|
1045
1045
|
"reasoning-chunks",
|
|
1046
1046
|
"tool-call-chunks"
|
|
@@ -1355,10 +1355,10 @@ function uniqueMessageIds(logs) {
|
|
|
1355
1355
|
const messageId = id;
|
|
1356
1356
|
const fingerprint = canonicalJson(withoutId);
|
|
1357
1357
|
const fingerprints = fingerprintsById.get(messageId);
|
|
1358
|
-
if (fingerprints === void 0) fingerprintsById.set(messageId, new Set([fingerprint]));
|
|
1358
|
+
if (fingerprints === void 0) fingerprintsById.set(messageId, /* @__PURE__ */ new Set([fingerprint]));
|
|
1359
1359
|
else fingerprints.add(fingerprint);
|
|
1360
1360
|
const ids = idsByFingerprint.get(fingerprint);
|
|
1361
|
-
if (ids === void 0) idsByFingerprint.set(fingerprint, new Set([messageId]));
|
|
1361
|
+
if (ids === void 0) idsByFingerprint.set(fingerprint, /* @__PURE__ */ new Set([messageId]));
|
|
1362
1362
|
else ids.add(messageId);
|
|
1363
1363
|
}
|
|
1364
1364
|
const unique = /* @__PURE__ */ new Map();
|
|
@@ -1744,14 +1744,16 @@ function defineAcpSnapshotSuite(options) {
|
|
|
1744
1744
|
const prompts = normalizedSystemPrompts(primary.content, ctx);
|
|
1745
1745
|
expect(prompts.length, `${mode} produced no system prompt to snapshot`).toBeGreaterThan(0);
|
|
1746
1746
|
const promptSnapshot = formatSystemPromptSnapshot(prompts[0], prompts.slice(1));
|
|
1747
|
-
const
|
|
1747
|
+
const promptSource = promptSourceByClass.get(classOf(scenario)) ?? scenario;
|
|
1748
|
+
const promptPath = join(snapshotsDir, promptSource.name, SYSTEM_PROMPT_SNAPSHOT);
|
|
1748
1749
|
claimSharedSnapshot(promptClaims, promptPath, scenario.name, promptSnapshot);
|
|
1749
1750
|
await writeFile(promptPath, promptSnapshot);
|
|
1750
1751
|
const schemaSets = normalizedToolSchemas(primary.content, ctx);
|
|
1751
1752
|
expect(schemaSets.length, `${mode} produced no tool schemas to snapshot`).toBeGreaterThan(0);
|
|
1752
1753
|
expect(schemaSets.length, `${mode} produced a tool-schema sequence that differs from its prompt sequence`).toBe(prompts.length);
|
|
1753
1754
|
const toolSchemasSnapshot = formatToolSchemasSnapshot(schemaSets[0], schemaSets.slice(1));
|
|
1754
|
-
const
|
|
1755
|
+
const schemaSource = schemaSourceByClass.get(classOf(scenario)) ?? scenario;
|
|
1756
|
+
const schemaPath = join(snapshotsDir, schemaSource.name, TOOL_SCHEMAS_SNAPSHOT);
|
|
1755
1757
|
claimSharedSnapshot(schemaClaims, schemaPath, scenario.name, toolSchemasSnapshot);
|
|
1756
1758
|
await writeFile(schemaPath, toolSchemasSnapshot);
|
|
1757
1759
|
}
|
|
@@ -1911,7 +1913,9 @@ function defineAcpSnapshotSuite(options) {
|
|
|
1911
1913
|
for (const index of scenario.pinsChildSystemPrompts ?? []) {
|
|
1912
1914
|
expect(files[index], `${scenario.name}: child prompt pin ${index} must name an existing session.<n>.jsonl fixture`).toBeDefined();
|
|
1913
1915
|
const file = childSystemPromptSnapshot(index);
|
|
1914
|
-
|
|
1916
|
+
const sidecar = await readFile(join(dir, file), "utf8");
|
|
1917
|
+
const promptSource = promptSourceByClass.get(classOf(scenario)) ?? scenario;
|
|
1918
|
+
assertChildSystemPromptSnapshot(sidecar, initialSystemPromptSnapshot(await readFile(join(snapshotsDir, promptSource.name, SYSTEM_PROMPT_SNAPSHOT), "utf8")), `${scenario.name}/${file}`);
|
|
1915
1919
|
}
|
|
1916
1920
|
}
|
|
1917
1921
|
});
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ACP snapshot suite kit — the shared machinery behind the keyless snapshot
|
|
3
|
-
* tier (`
|
|
3
|
+
* tier (`bun run test:snapshot`). Four layers, composable per example: the
|
|
4
4
|
* shared subprocess/client launcher ({@link launchAcpTestAgent}), the scripted
|
|
5
5
|
* scenario harness ({@link runScenario}), the pure expected-output normalizers
|
|
6
6
|
* ({@link normalizeStdout} / {@link normalizeSessionLog} /
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monotykamary/dsh-acp-snapshot",
|
|
3
3
|
"description": "ACP test kit: shared subprocess launcher, snapshot scenario harness, expected-output normalizers, and suite factory",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.9",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@agentclientprotocol/sdk": "0.25.1",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
36
|
+
"@monotykamary/dsh-loader-smoke": "0.1.9",
|
|
37
|
+
"vitest": "^4.1.8"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@monotykamary/dsh-invariants": "^0.1.
|
|
41
|
-
"@monotykamary/dsh-session": "^0.1.
|
|
40
|
+
"@monotykamary/dsh-invariants": "^0.1.9",
|
|
41
|
+
"@monotykamary/dsh-session": "^0.1.9",
|
|
42
42
|
"@monotykamary/cordis": "^4.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@monotykamary/dsh-invariants": "^0.1.
|
|
46
|
-
"@monotykamary/dsh-session": "^0.1.
|
|
45
|
+
"@monotykamary/dsh-invariants": "^0.1.9",
|
|
46
|
+
"@monotykamary/dsh-session": "^0.1.9",
|
|
47
47
|
"@monotykamary/cordis": "^4.0.1"
|
|
48
48
|
}
|
|
49
|
-
}
|
|
49
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 DeepSeek
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|