@lucascouts/claude-agent-tui 0.3.1 → 0.5.0
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/dist/acp-agent.d.ts +7 -0
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +103 -3
- package/dist/claude-path.d.ts +48 -5
- package/dist/claude-path.d.ts.map +1 -1
- package/dist/claude-path.js +101 -27
- package/dist/drift-checks.d.ts +57 -0
- package/dist/drift-checks.d.ts.map +1 -0
- package/dist/drift-checks.js +183 -0
- package/dist/permissions/gate-wiring.d.ts +36 -2
- package/dist/permissions/gate-wiring.d.ts.map +1 -1
- package/dist/permissions/gate-wiring.js +105 -19
- package/dist/permissions/request-permission.d.ts +5 -0
- package/dist/permissions/request-permission.d.ts.map +1 -1
- package/dist/permissions/request-permission.js +8 -3
- package/dist/subagent-gate.d.ts +58 -0
- package/dist/subagent-gate.d.ts.map +1 -0
- package/dist/subagent-gate.js +110 -0
- package/package.json +10 -9
package/dist/acp-agent.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { JsonlWatcher, GetMessages, SessionMessage } from "./engine-watcher
|
|
|
12
12
|
import type { LocateOptions } from "./jsonl.js";
|
|
13
13
|
import type { DiffEnrichedReaderOptions } from "./diff-enriched-reader.js";
|
|
14
14
|
import type { ListSubagents, GetSubagentMessages } from "./subagent-source.js";
|
|
15
|
+
import { type SidechainToolUse } from "./subagent-gate.js";
|
|
15
16
|
import type { SubagentWatcher } from "./subagent-watcher.js";
|
|
16
17
|
import type { DetectorSchedule, EndOfTurnDetector } from "./end-of-turn.js";
|
|
17
18
|
import type { SessionGate, SessionGateOptions } from "./permissions/gate-wiring.js";
|
|
@@ -48,6 +49,12 @@ type Session = {
|
|
|
48
49
|
* was surfaced in an earlier pump). Per-session — sub-agent row uuids are session-scoped.
|
|
49
50
|
*/
|
|
50
51
|
emittedNested: Set<string>;
|
|
52
|
+
/** Story 054 — per-session dedup Set of sidechain inner tool_use ids already fed to the gate
|
|
53
|
+
* correlator (R3 exactly-once). Lazy-init on the gated pump path; absent on a no-gate session. */
|
|
54
|
+
registeredSidechain?: Set<string>;
|
|
55
|
+
/** Story 054 — maps a sidechain inner tool_use id → its SidechainToolUse (parentId/toolName/
|
|
56
|
+
* toolInput), for the decide()-time parent-Task dialog relay (Tasks 3/4). */
|
|
57
|
+
sidechainParentMap?: Map<string, SidechainToolUse>;
|
|
51
58
|
/** The managed engine that owns the PTY + watcher; used for idempotent teardown (story 014). */
|
|
52
59
|
engine?: SessionEngine;
|
|
53
60
|
cancelled: boolean;
|
package/dist/acp-agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
|
package/dist/acp-agent.js
CHANGED
|
@@ -17,6 +17,7 @@ import { resolveWatchTarget } from "./jsonl.js";
|
|
|
17
17
|
import { linearizeTurns, readOrderedMessages, defaultGetMessages } from "./linearize.js";
|
|
18
18
|
import { createDiffEnrichedReader } from "./diff-enriched-reader.js";
|
|
19
19
|
import { sourceSubagentRows, defaultListSubagents, defaultGetSubagentMessages, hasSubagentSpawn, spawnIdsOpen, } from "./subagent-source.js";
|
|
20
|
+
import { collectSidechainToolUses, registerSidechainGateToolUses, } from "./subagent-gate.js";
|
|
20
21
|
import { createSubagentWatcher } from "./subagent-watcher.js";
|
|
21
22
|
import { classifyDiffSource, diffToolCallUpdate } from "./diff-source.js";
|
|
22
23
|
import { guardEvent } from "./billing/entrypoint-guard.js";
|
|
@@ -254,9 +255,40 @@ const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
|
|
|
254
255
|
// payload in these XML-like markers that the CLI uses for its own display.
|
|
255
256
|
// The live prompt loop drops them; replay must strip them too or they leak
|
|
256
257
|
// into the UI on session/load.
|
|
257
|
-
const
|
|
258
|
+
const LOCAL_COMMAND_MARKERS = [
|
|
259
|
+
"command-name",
|
|
260
|
+
"command-message",
|
|
261
|
+
"command-args",
|
|
262
|
+
"local-command-stdout",
|
|
263
|
+
"local-command-stderr",
|
|
264
|
+
].map((tag) => ({ open: `<${tag}>`, close: `</${tag}>` }));
|
|
265
|
+
// Single-pass scanner that removes each `<tag>…</tag>` marker (matching the nearest
|
|
266
|
+
// closing tag of the same name, like a lazy regex would) in O(n) — no polynomial
|
|
267
|
+
// backtracking (CodeQL js/polynomial-redos #1).
|
|
258
268
|
function stripMarkerTags(text) {
|
|
259
|
-
|
|
269
|
+
const dead = new Set();
|
|
270
|
+
let result = "";
|
|
271
|
+
let copiedUpTo = 0;
|
|
272
|
+
let i = 0;
|
|
273
|
+
while (i < text.length) {
|
|
274
|
+
if (text[i] === "<") {
|
|
275
|
+
const marker = LOCAL_COMMAND_MARKERS.find((m) => !dead.has(m.open) && text.startsWith(m.open, i));
|
|
276
|
+
if (marker) {
|
|
277
|
+
const end = text.indexOf(marker.close, i + marker.open.length);
|
|
278
|
+
if (end !== -1) {
|
|
279
|
+
result += text.slice(copiedUpTo, i);
|
|
280
|
+
i = copiedUpTo = end + marker.close.length;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
// No closing marker remains anywhere ahead, and `indexOf` only ever
|
|
284
|
+
// searches forward from here on, so stop treating this tag as an
|
|
285
|
+
// opener — that avoids rescanning the tail for it on every match.
|
|
286
|
+
dead.add(marker.open);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
i++;
|
|
290
|
+
}
|
|
291
|
+
return result + text.slice(copiedUpTo);
|
|
260
292
|
}
|
|
261
293
|
/**
|
|
262
294
|
* Return user-message content with local-command marker tags removed, or
|
|
@@ -406,6 +438,47 @@ function registerGateToolUses(raw, gate) {
|
|
|
406
438
|
}
|
|
407
439
|
}
|
|
408
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Story 054 — best-effort label for the subagent that spawned a sidechain inner tool, for the ACP
|
|
443
|
+
* dialog title + the R4 visible-deny line. `parentId` is the spawning `Task`/`Agent` tool_use id; we
|
|
444
|
+
* scan the MAIN chain `messages` for the assistant `tool_use` block with `id === parentId` whose `name`
|
|
445
|
+
* is `Task`/`Agent`, and return its `input.subagent_type ?? input.description` when a string, else
|
|
446
|
+
* undefined. An orphan (`parentId === null`) has no spawn to name → undefined. Tolerant of the reduced
|
|
447
|
+
* shape in the {@link hasSubagentSpawn} style: non-object rows/messages and non-array content are skipped.
|
|
448
|
+
*/
|
|
449
|
+
function deriveSubagentLabel(messages, parentId) {
|
|
450
|
+
if (parentId === null)
|
|
451
|
+
return undefined;
|
|
452
|
+
for (const msg of messages) {
|
|
453
|
+
if (msg === null || typeof msg !== "object")
|
|
454
|
+
continue;
|
|
455
|
+
const inner = msg.message;
|
|
456
|
+
if (inner === null || typeof inner !== "object")
|
|
457
|
+
continue;
|
|
458
|
+
const content = inner.content;
|
|
459
|
+
if (!Array.isArray(content))
|
|
460
|
+
continue;
|
|
461
|
+
for (const block of content) {
|
|
462
|
+
if (block === null || typeof block !== "object")
|
|
463
|
+
continue;
|
|
464
|
+
const b = block;
|
|
465
|
+
if (b.type !== "tool_use" || b.id !== parentId)
|
|
466
|
+
continue;
|
|
467
|
+
if (b.name !== "Task" && b.name !== "Agent")
|
|
468
|
+
continue;
|
|
469
|
+
const input = b.input;
|
|
470
|
+
if (input === null || typeof input !== "object")
|
|
471
|
+
return undefined;
|
|
472
|
+
const i = input;
|
|
473
|
+
if (typeof i.subagent_type === "string")
|
|
474
|
+
return i.subagent_type;
|
|
475
|
+
if (typeof i.description === "string")
|
|
476
|
+
return i.description;
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
409
482
|
export class ClaudeAcpAgent {
|
|
410
483
|
constructor(client, logger, engine = createStubEngine(), deps = {}) {
|
|
411
484
|
this.backgroundTerminals = {};
|
|
@@ -1449,6 +1522,20 @@ export class ClaudeAcpAgent {
|
|
|
1449
1522
|
// un-merged `messages` slice exactly-once (R4.1 structural: sub-agent rows never advance
|
|
1450
1523
|
// `detectorCursor` nor register as gate tool_uses).
|
|
1451
1524
|
await this.emitLinearizedWithNested(sessionId, session, messages);
|
|
1525
|
+
// === SEAM(054) — feed the gate correlator from the sidechain rows (R3). Gated + LIVE-ONLY: runs
|
|
1526
|
+
// only with a present, non-torndown gate, and NEVER inside the shared emitLinearizedWithNested that
|
|
1527
|
+
// session/load replay also calls — so replay stays pure (U3). Additive: touches only the correlator +
|
|
1528
|
+
// the per-session dedup Set/parentMap, never emittedNested nor the detector cursor (U2/U5).
|
|
1529
|
+
if (session.gate && !session.gate.isTorndown) {
|
|
1530
|
+
const subagentRows = await sourceSubagentRows(sessionId, messages, {
|
|
1531
|
+
dir: session.cwd,
|
|
1532
|
+
listSubagents: this.listSubagents,
|
|
1533
|
+
getSubagentMessages: this.getSubagentMessages,
|
|
1534
|
+
});
|
|
1535
|
+
session.registeredSidechain ??= new Set();
|
|
1536
|
+
session.sidechainParentMap ??= new Map();
|
|
1537
|
+
registerSidechainGateToolUses(collectSidechainToolUses(subagentRows), session.gate.correlator, session.registeredSidechain, session.sidechainParentMap);
|
|
1538
|
+
}
|
|
1452
1539
|
// === SEAM(044) — Option-B sub-agent watcher: arm/refresh/teardown rides the MAIN-CHAIN spawn
|
|
1453
1540
|
// signal (`hasSubagentSpawn` + `spawnIdsOpen` over the FULL pumped messages — design key
|
|
1454
1541
|
// decision 4: NOT the detector's `openTaskIds`, the very inference that failed live in the
|
|
@@ -1780,7 +1867,20 @@ export class ClaudeAcpAgent {
|
|
|
1780
1867
|
// (idempotent with teardownSession) so a crashed TUI leaks no port/server/scratch.
|
|
1781
1868
|
if (gate) {
|
|
1782
1869
|
const boundGate = gate;
|
|
1783
|
-
|
|
1870
|
+
// Story 054 — the third arg is a LAZY subagent relay resolver: at decide()-time it reads the
|
|
1871
|
+
// session's sidechainParentMap (populated by the pump) to map an inner tool_use id to its parent
|
|
1872
|
+
// Task id + a derived label, so the gate relays a subagent tool's dialog under the parent Task
|
|
1873
|
+
// (R1/R2) or fails loud (R4). A main-chain id (no map entry) returns undefined → unchanged (U1).
|
|
1874
|
+
boundGate.bindSession(startedSessionId, () => void this.pumpUpdates(startedSessionId), (innerId) => {
|
|
1875
|
+
const s = this.sessions[startedSessionId];
|
|
1876
|
+
const entry = s?.sidechainParentMap?.get(innerId);
|
|
1877
|
+
if (!entry)
|
|
1878
|
+
return undefined;
|
|
1879
|
+
return {
|
|
1880
|
+
parentId: entry.parentId,
|
|
1881
|
+
subagentLabel: deriveSubagentLabel(s?.lastMessages ?? [], entry.parentId) ?? "subagent",
|
|
1882
|
+
};
|
|
1883
|
+
});
|
|
1784
1884
|
boundGate.bindPty(started.pty);
|
|
1785
1885
|
started.pty.onExit(() => void boundGate.teardown());
|
|
1786
1886
|
}
|
package/dist/claude-path.d.ts
CHANGED
|
@@ -1,12 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance pin the live `claude` version is measured against — kept in lockstep
|
|
3
|
+
* with `fork/.fork-provenance.json`'s externalRuntimeDeps `claude` entry. A live
|
|
4
|
+
* binary whose version differs only triggers a soft drift *warning* (R1.2), never
|
|
5
|
+
* a resolution failure.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PROVENANCE_CLAUDE_VERSION = "2.1.159";
|
|
8
|
+
/**
|
|
9
|
+
* Extract the leading `x.y.z` semver from `claude --version` output.
|
|
10
|
+
*
|
|
11
|
+
* e.g. `"2.1.186 (Claude Code)\n"` → `"2.1.186"`. Pure; returns `null` when no
|
|
12
|
+
* `x.y.z` triple is present (`""`, `"not a version"`, `"\n\n"` → `null`).
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseClaudeVersion(output: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Injectable seam for running `claude --version` — args-list, NEVER a shell (C5).
|
|
17
|
+
* Returns the binary's stdout. The default implementation is `defaultVersionExec`.
|
|
18
|
+
*/
|
|
19
|
+
export type VersionExec = (binPath: string, args: readonly string[]) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Best-effort detection of the live `claude` version at `binPath`.
|
|
22
|
+
*
|
|
23
|
+
* Runs `--version` (args-list, no shell) via the injectable `exec` seam and parses
|
|
24
|
+
* the result. Observability only — it NEVER throws: any failure (spawn error,
|
|
25
|
+
* timeout, unparseable output) yields `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectClaudeVersion(binPath: string, exec?: VersionExec): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Emit a one-line drift warning via `log` IFF `detected` is known AND differs from
|
|
30
|
+
* `pinned` (R1.2). Silent when there is no drift or detection failed (`detected`
|
|
31
|
+
* null). Pure aside from the single `log` call.
|
|
32
|
+
*/
|
|
33
|
+
export declare function reportVersionDrift(detected: string | null, pinned: string, log: (...args: unknown[]) => void): void;
|
|
34
|
+
/** Injectable seams for `resolveClaudePath` so callers/tests can stub the version probe. */
|
|
35
|
+
export interface ResolveOptions {
|
|
36
|
+
/** Override the version probe (default: {@link detectClaudeVersion}). */
|
|
37
|
+
detectVersion?: (binPath: string) => string | null;
|
|
38
|
+
/** Override the warning sink (default: `console.error` → stderr). */
|
|
39
|
+
log?: (...args: unknown[]) => void;
|
|
40
|
+
}
|
|
1
41
|
/**
|
|
2
42
|
* Resolve an absolute path to an executable subscription `claude` binary.
|
|
3
43
|
*
|
|
4
|
-
* Resolution
|
|
5
|
-
*
|
|
6
|
-
*
|
|
44
|
+
* Resolution is PATH-only: scan each `process.env.PATH` entry for an executable
|
|
45
|
+
* `claude` (which-style). On a hit, run a BEST-EFFORT version probe + drift
|
|
46
|
+
* warning (R1.1, R1.2) and return the SAME absolute PATH candidate (R5.2 — the
|
|
47
|
+
* probe never alters the returned path). On a miss, throw a fail-loud Error
|
|
48
|
+
* naming the PATH lookup plus the install hint (R1.3, R1.4) — there is NO
|
|
49
|
+
* native-binary / `.vscode` fallback anymore.
|
|
7
50
|
*
|
|
8
51
|
* @returns absolute path to an executable `claude`.
|
|
9
|
-
* @throws Error naming
|
|
52
|
+
* @throws Error naming the PATH lookup attempt if no executable `claude` is found.
|
|
10
53
|
*/
|
|
11
|
-
export declare function resolveClaudePath(): string;
|
|
54
|
+
export declare function resolveClaudePath(opts?: ResolveOptions): string;
|
|
12
55
|
//# sourceMappingURL=claude-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-path.d.ts","sourceRoot":"","sources":["../src/claude-path.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude-path.d.ts","sourceRoot":"","sources":["../src/claude-path.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAenD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;AAc/E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,WAAgC,GACrC,MAAM,GAAG,IAAI,CAMf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAChC,IAAI,CAON;AAED,4FAA4F;AAC5F,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACnD,qEAAqE;IACrE,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,cAAmB,GAAG,MAAM,CA6BnE"}
|
package/dist/claude-path.js
CHANGED
|
@@ -1,22 +1,40 @@
|
|
|
1
|
-
// Resolves the subscription `claude` binary from PATH (story 012
|
|
1
|
+
// Resolves the subscription `claude` binary from PATH (story 012 R1/R1.2;
|
|
2
|
+
// story 049 R1.1–R1.5, R5.2 — version-aware + fail-loud).
|
|
2
3
|
//
|
|
3
4
|
// The fork must drive the user's *subscription* claude (resolved from PATH),
|
|
4
5
|
// NOT the binary embedded in @anthropic-ai/claude-agent-sdk — the SDK-embedded
|
|
5
6
|
// path bills as credit, while the PATH `claude` bills as signature
|
|
6
7
|
// (`entrypoint == 'cli'`, the E1 keystone — experiments/DEGRAU0-RESULTS.md).
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// fallback (
|
|
10
|
-
//
|
|
8
|
+
//
|
|
9
|
+
// Resolution is PATH-only. Story 049 DROPPED the hardcoded `2.1.159`
|
|
10
|
+
// native-binary fallback (a version-specific `.vscode` path that almost
|
|
11
|
+
// certainly no longer exists is a silent dead end): on a miss we now throw a
|
|
12
|
+
// fail-loud Error naming the PATH lookup that was attempted plus the install
|
|
13
|
+
// hint, so a missing CLI surfaces here rather than as an opaque spawn ENOENT
|
|
14
|
+
// deep in the PTY engine (story 013).
|
|
15
|
+
//
|
|
16
|
+
// On a successful resolve the helper additionally performs a BEST-EFFORT
|
|
17
|
+
// `claude --version` probe and logs a one-line provenance-drift warning when
|
|
18
|
+
// the live binary differs from the pinned `PROVENANCE_CLAUDE_VERSION`
|
|
19
|
+
// (fork/.fork-provenance.json). Drift is observability, never a hard stop: the
|
|
20
|
+
// detect/log path never throws out of `resolveClaudePath` and never changes the
|
|
21
|
+
// returned path (R5.2 — byte-identical return). The version probe spawns the
|
|
22
|
+
// binary directly (execFileSync, args-list, NEVER a shell — C5).
|
|
11
23
|
//
|
|
12
24
|
// Dependency-free on purpose: only node: builtins (FORK.md pins node-pty + the
|
|
13
|
-
// SDK as the only runtime deps; this adds none).
|
|
25
|
+
// SDK as the only runtime deps; this adds none). R1.5 / C4.
|
|
26
|
+
import { execFileSync } from "node:child_process";
|
|
14
27
|
import { accessSync, constants } from "node:fs";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
28
|
import { delimiter, join } from "node:path";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Provenance pin the live `claude` version is measured against — kept in lockstep
|
|
31
|
+
* with `fork/.fork-provenance.json`'s externalRuntimeDeps `claude` entry. A live
|
|
32
|
+
* binary whose version differs only triggers a soft drift *warning* (R1.2), never
|
|
33
|
+
* a resolution failure.
|
|
34
|
+
*/
|
|
35
|
+
export const PROVENANCE_CLAUDE_VERSION = "2.1.159";
|
|
36
|
+
/** Shared install hint appended to the fail-loud resolution error (R1.3). */
|
|
37
|
+
const INSTALL_HINT = 'Install the Claude Code subscription CLI or ensure "claude" is on PATH.';
|
|
20
38
|
/** True if `p` exists and is executable by the current process. */
|
|
21
39
|
function isExecutable(p) {
|
|
22
40
|
try {
|
|
@@ -27,35 +45,91 @@ function isExecutable(p) {
|
|
|
27
45
|
return false;
|
|
28
46
|
}
|
|
29
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract the leading `x.y.z` semver from `claude --version` output.
|
|
50
|
+
*
|
|
51
|
+
* e.g. `"2.1.186 (Claude Code)\n"` → `"2.1.186"`. Pure; returns `null` when no
|
|
52
|
+
* `x.y.z` triple is present (`""`, `"not a version"`, `"\n\n"` → `null`).
|
|
53
|
+
*/
|
|
54
|
+
export function parseClaudeVersion(output) {
|
|
55
|
+
const match = /(\d+\.\d+\.\d+)/.exec(output);
|
|
56
|
+
return match ? match[1] : null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Production `VersionExec`: spawn the binary directly via `execFileSync` (args-list,
|
|
60
|
+
* NO shell — C5) and capture stdout. Bounded by a short timeout; stderr discarded.
|
|
61
|
+
*/
|
|
62
|
+
function defaultVersionExec(binPath, args) {
|
|
63
|
+
return execFileSync(binPath, [...args], {
|
|
64
|
+
encoding: "utf8",
|
|
65
|
+
timeout: 5000,
|
|
66
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Best-effort detection of the live `claude` version at `binPath`.
|
|
71
|
+
*
|
|
72
|
+
* Runs `--version` (args-list, no shell) via the injectable `exec` seam and parses
|
|
73
|
+
* the result. Observability only — it NEVER throws: any failure (spawn error,
|
|
74
|
+
* timeout, unparseable output) yields `null`.
|
|
75
|
+
*/
|
|
76
|
+
export function detectClaudeVersion(binPath, exec = defaultVersionExec) {
|
|
77
|
+
try {
|
|
78
|
+
return parseClaudeVersion(exec(binPath, ["--version"]));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Emit a one-line drift warning via `log` IFF `detected` is known AND differs from
|
|
86
|
+
* `pinned` (R1.2). Silent when there is no drift or detection failed (`detected`
|
|
87
|
+
* null). Pure aside from the single `log` call.
|
|
88
|
+
*/
|
|
89
|
+
export function reportVersionDrift(detected, pinned, log) {
|
|
90
|
+
if (detected !== null && detected !== pinned) {
|
|
91
|
+
log(`[claude-path] claude version drift: detected ${detected} but provenance pins ${pinned} ` +
|
|
92
|
+
`(continuing — drift is a warning, not a hard stop)`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
30
95
|
/**
|
|
31
96
|
* Resolve an absolute path to an executable subscription `claude` binary.
|
|
32
97
|
*
|
|
33
|
-
* Resolution
|
|
34
|
-
*
|
|
35
|
-
*
|
|
98
|
+
* Resolution is PATH-only: scan each `process.env.PATH` entry for an executable
|
|
99
|
+
* `claude` (which-style). On a hit, run a BEST-EFFORT version probe + drift
|
|
100
|
+
* warning (R1.1, R1.2) and return the SAME absolute PATH candidate (R5.2 — the
|
|
101
|
+
* probe never alters the returned path). On a miss, throw a fail-loud Error
|
|
102
|
+
* naming the PATH lookup plus the install hint (R1.3, R1.4) — there is NO
|
|
103
|
+
* native-binary / `.vscode` fallback anymore.
|
|
36
104
|
*
|
|
37
105
|
* @returns absolute path to an executable `claude`.
|
|
38
|
-
* @throws Error naming
|
|
106
|
+
* @throws Error naming the PATH lookup attempt if no executable `claude` is found.
|
|
39
107
|
*/
|
|
40
|
-
export function resolveClaudePath() {
|
|
41
|
-
//
|
|
108
|
+
export function resolveClaudePath(opts = {}) {
|
|
109
|
+
// PATH lookup: scan each PATH entry for an executable `claude`.
|
|
42
110
|
const pathEnv = process.env.PATH ?? "";
|
|
43
111
|
const pathEntries = pathEnv.split(delimiter).filter((entry) => entry.length > 0);
|
|
44
112
|
for (const entry of pathEntries) {
|
|
45
113
|
const candidate = join(entry, "claude");
|
|
46
114
|
if (isExecutable(candidate)) {
|
|
115
|
+
// Best-effort, non-fatal version observability — must NOT change the
|
|
116
|
+
// returned path and must NEVER throw out of the success path (R5.2).
|
|
117
|
+
const log = opts.log ?? console.error;
|
|
118
|
+
try {
|
|
119
|
+
const detected = (opts.detectVersion ?? detectClaudeVersion)(candidate);
|
|
120
|
+
if (detected) {
|
|
121
|
+
log(`[claude-path] resolved claude ${candidate} (version ${detected})`);
|
|
122
|
+
}
|
|
123
|
+
reportVersionDrift(detected, PROVENANCE_CLAUDE_VERSION, log);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Observability is best-effort; never let it break resolution.
|
|
127
|
+
}
|
|
47
128
|
return candidate;
|
|
48
129
|
}
|
|
49
130
|
}
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
// 3. Neither exists: throw naming BOTH attempted locations.
|
|
56
|
-
throw new Error(`Could not resolve an executable "claude" binary. Tried: ` +
|
|
57
|
-
`(1) PATH lookup over ${pathEntries.length} entr${pathEntries.length === 1 ? "y" : "ies"} ` +
|
|
58
|
-
`("${pathEnv}"), and ` +
|
|
59
|
-
`(2) the documented native-binary fallback "${fallback}". ` +
|
|
60
|
-
`Install the Claude Code subscription CLI or ensure "claude" is on PATH.`);
|
|
131
|
+
// No executable `claude` on PATH: fail loud naming the lookup (no fallback).
|
|
132
|
+
throw new Error(`Could not resolve an executable "claude" binary. ` +
|
|
133
|
+
`Tried: PATH lookup over ${pathEntries.length} entr${pathEntries.length === 1 ? "y" : "ies"} ` +
|
|
134
|
+
`("${pathEnv}"). ${INSTALL_HINT}`);
|
|
61
135
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** The verdict a single drift check returns. `surface` names which binary-contact surface was checked. */
|
|
2
|
+
export interface CheckResult {
|
|
3
|
+
/** The binary-contact surface this verdict is about (e.g. "stop_reason", "jsonl_shape"). */
|
|
4
|
+
surface: string;
|
|
5
|
+
/** True iff no drift was detected on this surface. */
|
|
6
|
+
ok: boolean;
|
|
7
|
+
/** Human-readable summary; on `ok=false` it NAMES every offending value (the consumers print it). */
|
|
8
|
+
detail: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The stop_reason values mapStopReason handles EXPLICITLY (stop-reason-map.ts:26-33). Everything else
|
|
12
|
+
* hits its default branch. These are the "terminal" taxonomy the bridge answers a turn with.
|
|
13
|
+
*/
|
|
14
|
+
export declare const HANDLED_STOP_REASONS: ReadonlySet<string>;
|
|
15
|
+
/**
|
|
16
|
+
* stop_reason values that are NON-TERMINAL but EXPECTED (so not drift): the model pauses mid-turn. They
|
|
17
|
+
* hit mapStopReason's default branch BY DESIGN. `tool_use` is the real one seen in transcripts.
|
|
18
|
+
*/
|
|
19
|
+
export declare const KNOWN_NONTERMINAL_STOP_REASONS: ReadonlySet<string>;
|
|
20
|
+
/** The core top-level keys EVERY raw JSONL event line must carry (jsonl.ts:513-523 — the required set). */
|
|
21
|
+
export declare const REQUIRED_JSONL_KEYS: ReadonlySet<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Every top-level key a raw JSONL line is ALLOWED to carry = {@link REQUIRED_JSONL_KEYS} ∪ the known
|
|
24
|
+
* optional universal / per-type fields documented in jsonl.ts:528-543 (plus the universal fields seen
|
|
25
|
+
* in real fixtures). A key OUTSIDE this set is a NEW/unexpected field → drift.
|
|
26
|
+
*/
|
|
27
|
+
export declare const KNOWN_JSONL_KEYS: ReadonlySet<string>;
|
|
28
|
+
/** The keystroke the native TUI permission prompt accepts for Yes — mirror of allow-inject.ts:29. */
|
|
29
|
+
export declare const EXPECTED_ALLOW_KEYSTROKE: string;
|
|
30
|
+
/**
|
|
31
|
+
* R2.1 — verify every non-null `message.stop_reason` is either HANDLED or a KNOWN non-terminal value.
|
|
32
|
+
*
|
|
33
|
+
* `null`/`undefined`/absent stop_reason is NOT drift (absence) and is ignored. A non-null value outside
|
|
34
|
+
* {@link HANDLED_STOP_REASONS} ∪ {@link KNOWN_NONTERMINAL_STOP_REASONS} (e.g. a new `pause_turn`) trips
|
|
35
|
+
* the check; `detail` names every offending value. Pure: no I/O, depends only on `lines`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function checkStopReasons(lines: ReadonlyArray<Record<string, unknown>>): CheckResult;
|
|
38
|
+
/**
|
|
39
|
+
* R2.2 — verify every SDK content-block type is covered by a handled `switch` case. A block type in
|
|
40
|
+
* `sdkBlockTypes` but NOT in `handledCases` (e.g. a new `server_tool_use`) is uncovered drift; `detail`
|
|
41
|
+
* names each uncovered type. Pure: depends only on its two iterable arguments.
|
|
42
|
+
*/
|
|
43
|
+
export declare function checkContentBlockCoverage(sdkBlockTypes: Iterable<string>, handledCases: Iterable<string>): CheckResult;
|
|
44
|
+
/**
|
|
45
|
+
* R2.3 — verify each raw JSONL line carries every {@link REQUIRED_JSONL_KEYS} core key and NO key
|
|
46
|
+
* outside {@link KNOWN_JSONL_KEYS}. A missing core key OR a new/unexpected top-level key is drift;
|
|
47
|
+
* `detail` names the offending key(s). Guards the RAW on-disk shape (camelCase), not the reduced
|
|
48
|
+
* getSessionMessages shape. Pure: depends only on `lines`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function checkJsonlShape(lines: ReadonlyArray<Record<string, unknown>>): CheckResult;
|
|
51
|
+
/**
|
|
52
|
+
* R2.4 — verify the gate's allow keystroke is still the canonical {@link EXPECTED_ALLOW_KEYSTROKE}
|
|
53
|
+
* (`"1\r"`). On mismatch `detail` references both the expected and the actual keystroke. Mirror of
|
|
54
|
+
* allow-inject.ts:29 `KEYSTROKE_YES`. Pure: depends only on `keystroke`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function checkAllowKeystroke(keystroke: string): CheckResult;
|
|
57
|
+
//# sourceMappingURL=drift-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-checks.d.ts","sourceRoot":"","sources":["../src/drift-checks.ts"],"names":[],"mappings":"AA4BA,0GAA0G;AAC1G,MAAM,WAAW,WAAW;IAC1B,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,EAAE,EAAE,OAAO,CAAC;IACZ,qGAAqG;IACrG,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAKnD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAAyB,CAAC;AAEzF,2GAA2G;AAC3G,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAMlD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAsB/C,CAAC;AAEH,qGAAqG;AACrG,eAAO,MAAM,wBAAwB,EAAE,MAAc,CAAC;AA2BtD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,CAe3F;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC/B,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC7B,WAAW,CASb;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,CAiB1F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAalE"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// === Story 049 / Task 2.1 (R2.1, R2.2, R2.3, R2.4) — pure binary-drift checks (no I/O) ============
|
|
2
|
+
//
|
|
3
|
+
// Single source of truth for "what binary-drift looks like" across the four surfaces the bridge reads
|
|
4
|
+
// from the claude binary. Each check is PURE and referentially transparent: it takes ALREADY-PARSED
|
|
5
|
+
// input and returns a `{surface, ok, detail}` verdict. There is NO `fs`, NO `child_process`/`spawn`,
|
|
6
|
+
// NO `process` here — the I/O (read fixtures / spawn the live binary) belongs to the OFFLINE detector
|
|
7
|
+
// (Task 3) and `smoke:live` (Task 5), which both reuse these verdicts. Keeping this module I/O-free is
|
|
8
|
+
// the foundation for Task 3's spawn-import guard.
|
|
9
|
+
//
|
|
10
|
+
// MIRROR ANCHORS (the constants below mirror these real source surfaces — keep them honest):
|
|
11
|
+
// - stop_reason taxonomy ........ src/stop-reason-map.ts:26-33 (the 4 explicit, non-default cases of
|
|
12
|
+
// mapStopReason: end_turn / stop_sequence / max_tokens / refusal)
|
|
13
|
+
// - allow keystroke ............. src/permissions/allow-inject.ts:29 (KEYSTROKE_YES = "1\r")
|
|
14
|
+
// - raw JSONL field set ......... src/jsonl.ts:513-544 (the documented universal + per-type fields)
|
|
15
|
+
//
|
|
16
|
+
// TWO NON-OBVIOUS DECISIONS (both deliberate reads of the requirements, not oversights):
|
|
17
|
+
// 1. `tool_use` is KNOWN-NON-TERMINAL, NOT drift. mapStopReason switches on the 4 terminal cases and
|
|
18
|
+
// DEFAULTS everything else to "end_turn" (with a drift log). `tool_use` legitimately appears in
|
|
19
|
+
// real transcripts — the model pauses to call a tool; that is NOT a turn end — and it hits that
|
|
20
|
+
// default branch BY DESIGN. So it is recorded as expected (KNOWN_NONTERMINAL_STOP_REASONS) and
|
|
21
|
+
// must NOT fail the check. A genuinely NEW value (e.g. `pause_turn`) still fails.
|
|
22
|
+
// 2. `checkJsonlShape` guards the RAW on-disk JSONL shape (camelCase `sessionId`, `parentUuid`, ...),
|
|
23
|
+
// NOT the reduced `getSessionMessages` shape (`session_id` snake_case) that R2.3 literally lists.
|
|
24
|
+
// This is a deliberate read of R2.3's intent: the drift we want to detect is in the on-disk JSONL
|
|
25
|
+
// the bridge actually tails, so the check mirrors jsonl.ts's documented raw field set.
|
|
26
|
+
//
|
|
27
|
+
// node:test runner: `node --experimental-strip-types --test test/drift-checks.test.ts`
|
|
28
|
+
// --- mirror constants ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* The stop_reason values mapStopReason handles EXPLICITLY (stop-reason-map.ts:26-33). Everything else
|
|
31
|
+
* hits its default branch. These are the "terminal" taxonomy the bridge answers a turn with.
|
|
32
|
+
*/
|
|
33
|
+
export const HANDLED_STOP_REASONS = new Set([
|
|
34
|
+
"end_turn",
|
|
35
|
+
"stop_sequence",
|
|
36
|
+
"max_tokens",
|
|
37
|
+
"refusal",
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* stop_reason values that are NON-TERMINAL but EXPECTED (so not drift): the model pauses mid-turn. They
|
|
41
|
+
* hit mapStopReason's default branch BY DESIGN. `tool_use` is the real one seen in transcripts.
|
|
42
|
+
*/
|
|
43
|
+
export const KNOWN_NONTERMINAL_STOP_REASONS = new Set(["tool_use"]);
|
|
44
|
+
/** The core top-level keys EVERY raw JSONL event line must carry (jsonl.ts:513-523 — the required set). */
|
|
45
|
+
export const REQUIRED_JSONL_KEYS = new Set([
|
|
46
|
+
"uuid",
|
|
47
|
+
"type",
|
|
48
|
+
"timestamp",
|
|
49
|
+
"sessionId",
|
|
50
|
+
"message",
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* Every top-level key a raw JSONL line is ALLOWED to carry = {@link REQUIRED_JSONL_KEYS} ∪ the known
|
|
54
|
+
* optional universal / per-type fields documented in jsonl.ts:528-543 (plus the universal fields seen
|
|
55
|
+
* in real fixtures). A key OUTSIDE this set is a NEW/unexpected field → drift.
|
|
56
|
+
*/
|
|
57
|
+
export const KNOWN_JSONL_KEYS = new Set([
|
|
58
|
+
...REQUIRED_JSONL_KEYS,
|
|
59
|
+
// universal fields (present in raw JSONL but absent from the reduced getSessionMessages shape)
|
|
60
|
+
"parentUuid",
|
|
61
|
+
"parentToolUseId",
|
|
62
|
+
"userType",
|
|
63
|
+
"version",
|
|
64
|
+
"isSidechain",
|
|
65
|
+
"entrypoint",
|
|
66
|
+
"cwd",
|
|
67
|
+
"gitBranch",
|
|
68
|
+
"logicalParentUuid",
|
|
69
|
+
"isMeta",
|
|
70
|
+
"isCompactSummary",
|
|
71
|
+
"level",
|
|
72
|
+
"isApiErrorMessage",
|
|
73
|
+
// per-type extras
|
|
74
|
+
"requestId",
|
|
75
|
+
"promptId",
|
|
76
|
+
"usage",
|
|
77
|
+
"toolUseResult",
|
|
78
|
+
"permissionMode",
|
|
79
|
+
]);
|
|
80
|
+
/** The keystroke the native TUI permission prompt accepts for Yes — mirror of allow-inject.ts:29. */
|
|
81
|
+
export const EXPECTED_ALLOW_KEYSTROKE = "1\r";
|
|
82
|
+
// --- shared helpers -----------------------------------------------------------------------------
|
|
83
|
+
/**
|
|
84
|
+
* Build a verdict from a collected list of offending items: `ok=true` (with a positive summary) when
|
|
85
|
+
* the list is empty, otherwise `ok=false` with a detail that NAMES every offending item (the consumers
|
|
86
|
+
* and the unit tests assert each offending value appears in `detail`).
|
|
87
|
+
*/
|
|
88
|
+
function verdict(surface, offenders, okSummary) {
|
|
89
|
+
if (offenders.length === 0) {
|
|
90
|
+
return { surface, ok: true, detail: okSummary };
|
|
91
|
+
}
|
|
92
|
+
return { surface, ok: false, detail: `${surface} drift: ${offenders.join(", ")}` };
|
|
93
|
+
}
|
|
94
|
+
/** Read `line.message?.stop_reason` defensively (the message object is `unknown`). */
|
|
95
|
+
function readStopReason(line) {
|
|
96
|
+
const message = line.message;
|
|
97
|
+
if (typeof message !== "object" || message === null) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return message.stop_reason;
|
|
101
|
+
}
|
|
102
|
+
// --- the four checks ----------------------------------------------------------------------------
|
|
103
|
+
/**
|
|
104
|
+
* R2.1 — verify every non-null `message.stop_reason` is either HANDLED or a KNOWN non-terminal value.
|
|
105
|
+
*
|
|
106
|
+
* `null`/`undefined`/absent stop_reason is NOT drift (absence) and is ignored. A non-null value outside
|
|
107
|
+
* {@link HANDLED_STOP_REASONS} ∪ {@link KNOWN_NONTERMINAL_STOP_REASONS} (e.g. a new `pause_turn`) trips
|
|
108
|
+
* the check; `detail` names every offending value. Pure: no I/O, depends only on `lines`.
|
|
109
|
+
*/
|
|
110
|
+
export function checkStopReasons(lines) {
|
|
111
|
+
const offenders = [];
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
const raw = readStopReason(line);
|
|
114
|
+
if (raw === null || raw === undefined) {
|
|
115
|
+
continue; // absence is not drift
|
|
116
|
+
}
|
|
117
|
+
const value = String(raw);
|
|
118
|
+
if (!HANDLED_STOP_REASONS.has(value) && !KNOWN_NONTERMINAL_STOP_REASONS.has(value)) {
|
|
119
|
+
if (!offenders.includes(value)) {
|
|
120
|
+
offenders.push(value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return verdict("stop_reason", offenders, "all stop_reasons are handled or known-non-terminal");
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* R2.2 — verify every SDK content-block type is covered by a handled `switch` case. A block type in
|
|
128
|
+
* `sdkBlockTypes` but NOT in `handledCases` (e.g. a new `server_tool_use`) is uncovered drift; `detail`
|
|
129
|
+
* names each uncovered type. Pure: depends only on its two iterable arguments.
|
|
130
|
+
*/
|
|
131
|
+
export function checkContentBlockCoverage(sdkBlockTypes, handledCases) {
|
|
132
|
+
const handled = new Set(handledCases);
|
|
133
|
+
const offenders = [];
|
|
134
|
+
for (const type of sdkBlockTypes) {
|
|
135
|
+
if (!handled.has(type) && !offenders.includes(type)) {
|
|
136
|
+
offenders.push(type);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return verdict("content_block", offenders, "every SDK content-block type is a handled case");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* R2.3 — verify each raw JSONL line carries every {@link REQUIRED_JSONL_KEYS} core key and NO key
|
|
143
|
+
* outside {@link KNOWN_JSONL_KEYS}. A missing core key OR a new/unexpected top-level key is drift;
|
|
144
|
+
* `detail` names the offending key(s). Guards the RAW on-disk shape (camelCase), not the reduced
|
|
145
|
+
* getSessionMessages shape. Pure: depends only on `lines`.
|
|
146
|
+
*/
|
|
147
|
+
export function checkJsonlShape(lines) {
|
|
148
|
+
const offenders = [];
|
|
149
|
+
for (const line of lines) {
|
|
150
|
+
for (const required of REQUIRED_JSONL_KEYS) {
|
|
151
|
+
const missing = `missing:${required}`;
|
|
152
|
+
if (!Object.prototype.hasOwnProperty.call(line, required) && !offenders.includes(missing)) {
|
|
153
|
+
offenders.push(missing);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
for (const key of Object.keys(line)) {
|
|
157
|
+
const unexpected = `unexpected:${key}`;
|
|
158
|
+
if (!KNOWN_JSONL_KEYS.has(key) && !offenders.includes(unexpected)) {
|
|
159
|
+
offenders.push(unexpected);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return verdict("jsonl_shape", offenders, "every line matches the known raw JSONL shape");
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* R2.4 — verify the gate's allow keystroke is still the canonical {@link EXPECTED_ALLOW_KEYSTROKE}
|
|
167
|
+
* (`"1\r"`). On mismatch `detail` references both the expected and the actual keystroke. Mirror of
|
|
168
|
+
* allow-inject.ts:29 `KEYSTROKE_YES`. Pure: depends only on `keystroke`.
|
|
169
|
+
*/
|
|
170
|
+
export function checkAllowKeystroke(keystroke) {
|
|
171
|
+
if (keystroke === EXPECTED_ALLOW_KEYSTROKE) {
|
|
172
|
+
return {
|
|
173
|
+
surface: "allow_keystroke",
|
|
174
|
+
ok: true,
|
|
175
|
+
detail: "allow keystroke matches the canonical 1\\r",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
surface: "allow_keystroke",
|
|
180
|
+
ok: false,
|
|
181
|
+
detail: `allow_keystroke drift: expected ${JSON.stringify(EXPECTED_ALLOW_KEYSTROKE)} but got ${JSON.stringify(keystroke)}`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -8,7 +8,18 @@ import { type PtyWriter, type Schedule } from "./allow-inject.js";
|
|
|
8
8
|
* prompt's rendering we have. ANY hit ⇒ the native prompt is showing (#52822 reproduced).
|
|
9
9
|
*/
|
|
10
10
|
export declare const NATIVE_PERMISSION_PROMPT_MARKERS: readonly string[];
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Story 054 (R6) — the native SUBAGENT permission prompt header. claude renders a subagent tool's
|
|
13
|
+
* permission box with a "Tool use · from the <name> agent" header, distinct from the main-chain
|
|
14
|
+
* "Do you want to proceed?" markers above. Without this marker {@link textShowsNativePrompt} misses
|
|
15
|
+
* the subagent box, {@link clearNativePrompt} returns `'suppressed'` and types nothing, and the inner
|
|
16
|
+
* subagent tool hangs. The substring is specific enough not to match ordinary subagent narration
|
|
17
|
+
* ("the … agent finished its work"). The exact middot/wording is confirmed in the deferred in-Zed
|
|
18
|
+
* proof (task 8); kept separate from the verbatim Degrau-0 probe markers above.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SUBAGENT_PROMPT_MARKER = "Tool use \u00B7 from the";
|
|
21
|
+
/** True iff any native-prompt marker — main-chain or the story-054 subagent box — appears in `text`
|
|
22
|
+
* (after ANSI stripping). */
|
|
12
23
|
export declare function textShowsNativePrompt(text: string): boolean;
|
|
13
24
|
/** Default bounded wait for the JSONL `tool_use` correlation to land after a hook fires (ms).
|
|
14
25
|
* The hook fires AFTER claude appended the assistant `tool_use` line, but the fs-watch → pump
|
|
@@ -17,6 +28,12 @@ export declare function textShowsNativePrompt(text: string): boolean;
|
|
|
17
28
|
export declare const DEFAULT_CORRELATION_WAIT_MS = 5000;
|
|
18
29
|
/** Default poll interval for the correlation wait (ms). */
|
|
19
30
|
export declare const DEFAULT_CORRELATION_POLL_MS = 50;
|
|
31
|
+
/** Story 054 — re-nudge cadence inside the correlation wait (ms): a sidechain inner tool_use line can
|
|
32
|
+
* materialize MID-WAIT (after the first nudge) — periodically re-kicking the pump sources + registers
|
|
33
|
+
* that lagging row before the wait expires, so the subagent tool reaches a clean match instead of a
|
|
34
|
+
* fail-closed timeout deny. Tracked separately from the poll interval (the poll is 10-50ms; nudging on
|
|
35
|
+
* every poll would hammer the pump) — a nudge fires only once ~250ms has elapsed since the last one. */
|
|
36
|
+
export declare const DEFAULT_CORRELATION_RENUDGE_MS = 250;
|
|
20
37
|
/** Default window for the native prompt to APPEAR after an allow decision (#52822 sweep, ms).
|
|
21
38
|
* If no marker renders within it, allow-suppression held (the 2.1.161 case) — nothing to clear. */
|
|
22
39
|
export declare const DEFAULT_PROMPT_APPEAR_MS = 1500;
|
|
@@ -56,6 +73,8 @@ export interface SessionGateOptions {
|
|
|
56
73
|
correlationWaitMs?: number;
|
|
57
74
|
/** See {@link DEFAULT_CORRELATION_POLL_MS}. */
|
|
58
75
|
correlationPollMs?: number;
|
|
76
|
+
/** See {@link DEFAULT_CORRELATION_RENUDGE_MS}. */
|
|
77
|
+
correlationRenudgeMs?: number;
|
|
59
78
|
/** See {@link DEFAULT_PROMPT_APPEAR_MS}. */
|
|
60
79
|
promptAppearMs?: number;
|
|
61
80
|
/** See {@link DEFAULT_PROMPT_POLL_MS}. */
|
|
@@ -67,6 +86,15 @@ export interface SessionGateOptions {
|
|
|
67
86
|
/** Injectable port allocator (default: the story-032 `findFreePort`). */
|
|
68
87
|
findPort?: () => Promise<number>;
|
|
69
88
|
}
|
|
89
|
+
/** Story 054 — the parent-Task relay info for a subagent inner tool, resolved at decide() time. */
|
|
90
|
+
export interface SubagentRelay {
|
|
91
|
+
/** The spawning Task/Agent tool_use id to attach the ACP dialog to; null = orphan (no safe target). */
|
|
92
|
+
parentId: string | null;
|
|
93
|
+
/** Best-effort subagent name for the dialog title / the R4 deny line. */
|
|
94
|
+
subagentLabel: string;
|
|
95
|
+
}
|
|
96
|
+
/** Resolve a subagent inner tool_use id → its relay info, or undefined for a main-chain tool. */
|
|
97
|
+
export type ResolveSubagentRelay = (innerToolUseId: string) => SubagentRelay | undefined;
|
|
70
98
|
/** The per-session gate runtime handle `createSession` owns and `teardownSession` disposes. */
|
|
71
99
|
export interface SessionGate {
|
|
72
100
|
/** The verified-free loopback port the hook server bound (== the port in the scratch hook URL). */
|
|
@@ -81,8 +109,14 @@ export interface SessionGate {
|
|
|
81
109
|
* and an optional `nudge` invoked on every hook arrival to force an immediate pump re-read
|
|
82
110
|
* (shrinking the JSONL-correlation race). MUST be called before the first tool call can be
|
|
83
111
|
* approved — an unbound gate fails closed (deny).
|
|
112
|
+
*
|
|
113
|
+
* Story 054 — the third optional arg is a lazy resolver that maps an inner `tool_use.id` to its
|
|
114
|
+
* subagent {@link SubagentRelay} (parent Task id + label) by reading the session's
|
|
115
|
+
* `sidechainParentMap` (populated by the pump). `decide` uses it AFTER the correlation wait to
|
|
116
|
+
* relay a KNOWN subagent tool's dialog under its parent Task id (R1/R2), or to fail LOUD (R4) on
|
|
117
|
+
* an orphan / uncorrelatable subagent. A main-chain tool (no resolver entry) is unchanged (U1).
|
|
84
118
|
*/
|
|
85
|
-
bindSession(sessionId: string, nudge?: () => void): void;
|
|
119
|
+
bindSession(sessionId: string, nudge?: () => void, resolveSubagentRelay?: ResolveSubagentRelay): void;
|
|
86
120
|
/** Bind the live PTY: stores the raw writer for the allow keystroke and (when the PTY exposes
|
|
87
121
|
* `onData`) attaches the recent-output tap feeding the native-prompt probe. */
|
|
88
122
|
bindPty(pty: GatePty): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-wiring.d.ts","sourceRoot":"","sources":["../../src/permissions/gate-wiring.ts"],"names":[],"mappings":"AAqCA,OAAO,EAEL,iBAAiB,EACjB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAqB,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAErF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,EAAE,SAAS,MAAM,EAO7D,CAAC;
|
|
1
|
+
{"version":3,"file":"gate-wiring.d.ts","sourceRoot":"","sources":["../../src/permissions/gate-wiring.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,15 +51,27 @@ export const NATIVE_PERMISSION_PROMPT_MARKERS = [
|
|
|
51
51
|
"1. Yes",
|
|
52
52
|
"No, and tell Claude",
|
|
53
53
|
];
|
|
54
|
+
/**
|
|
55
|
+
* Story 054 (R6) — the native SUBAGENT permission prompt header. claude renders a subagent tool's
|
|
56
|
+
* permission box with a "Tool use · from the <name> agent" header, distinct from the main-chain
|
|
57
|
+
* "Do you want to proceed?" markers above. Without this marker {@link textShowsNativePrompt} misses
|
|
58
|
+
* the subagent box, {@link clearNativePrompt} returns `'suppressed'` and types nothing, and the inner
|
|
59
|
+
* subagent tool hangs. The substring is specific enough not to match ordinary subagent narration
|
|
60
|
+
* ("the … agent finished its work"). The exact middot/wording is confirmed in the deferred in-Zed
|
|
61
|
+
* proof (task 8); kept separate from the verbatim Degrau-0 probe markers above.
|
|
62
|
+
*/
|
|
63
|
+
export const SUBAGENT_PROMPT_MARKER = "Tool use · from the";
|
|
54
64
|
/** Strip CSI / common ANSI escape sequences so prompt markers match the plain text (e-gate probe). */
|
|
55
65
|
function stripAnsiText(s) {
|
|
56
66
|
// eslint-disable-next-line no-control-regex
|
|
57
67
|
return s.replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, "");
|
|
58
68
|
}
|
|
59
|
-
/** True iff any native-prompt marker appears in `text`
|
|
69
|
+
/** True iff any native-prompt marker — main-chain or the story-054 subagent box — appears in `text`
|
|
70
|
+
* (after ANSI stripping). */
|
|
60
71
|
export function textShowsNativePrompt(text) {
|
|
61
72
|
const stripped = stripAnsiText(text);
|
|
62
|
-
return NATIVE_PERMISSION_PROMPT_MARKERS.some((m) => stripped.includes(m))
|
|
73
|
+
return (NATIVE_PERMISSION_PROMPT_MARKERS.some((m) => stripped.includes(m)) ||
|
|
74
|
+
stripped.includes(SUBAGENT_PROMPT_MARKER));
|
|
63
75
|
}
|
|
64
76
|
/** Default bounded wait for the JSONL `tool_use` correlation to land after a hook fires (ms).
|
|
65
77
|
* The hook fires AFTER claude appended the assistant `tool_use` line, but the fs-watch → pump
|
|
@@ -68,6 +80,12 @@ export function textShowsNativePrompt(text) {
|
|
|
68
80
|
export const DEFAULT_CORRELATION_WAIT_MS = 5000;
|
|
69
81
|
/** Default poll interval for the correlation wait (ms). */
|
|
70
82
|
export const DEFAULT_CORRELATION_POLL_MS = 50;
|
|
83
|
+
/** Story 054 — re-nudge cadence inside the correlation wait (ms): a sidechain inner tool_use line can
|
|
84
|
+
* materialize MID-WAIT (after the first nudge) — periodically re-kicking the pump sources + registers
|
|
85
|
+
* that lagging row before the wait expires, so the subagent tool reaches a clean match instead of a
|
|
86
|
+
* fail-closed timeout deny. Tracked separately from the poll interval (the poll is 10-50ms; nudging on
|
|
87
|
+
* every poll would hammer the pump) — a nudge fires only once ~250ms has elapsed since the last one. */
|
|
88
|
+
export const DEFAULT_CORRELATION_RENUDGE_MS = 250;
|
|
71
89
|
/** Default window for the native prompt to APPEAR after an allow decision (#52822 sweep, ms).
|
|
72
90
|
* If no marker renders within it, allow-suppression held (the 2.1.161 case) — nothing to clear. */
|
|
73
91
|
export const DEFAULT_PROMPT_APPEAR_MS = 1500;
|
|
@@ -100,6 +118,10 @@ class SessionGateImpl {
|
|
|
100
118
|
this.outputTail = "";
|
|
101
119
|
this.totalOutput = 0;
|
|
102
120
|
this.torndown = false;
|
|
121
|
+
/** Story 054 (R5) — per-session serial queue: the request+sweep critical section runs one at a
|
|
122
|
+
* time so two parallel subagent dialogs never cross their shared-PTY keystrokes. The wait/
|
|
123
|
+
* correlate/resolve prelude stays concurrent (only the raise+inject section serializes). */
|
|
124
|
+
this.permissionQueue = Promise.resolve();
|
|
103
125
|
}
|
|
104
126
|
get isTorndown() {
|
|
105
127
|
return this.torndown;
|
|
@@ -110,6 +132,15 @@ class SessionGateImpl {
|
|
|
110
132
|
get schedule() {
|
|
111
133
|
return this.opts.schedule ?? defaultSchedule;
|
|
112
134
|
}
|
|
135
|
+
/** Story 054 (R5) — append `fn` to the per-session serial chain so it runs only after the
|
|
136
|
+
* previous critical section settles (success OR failure), serializing concurrent decides'
|
|
137
|
+
* request+sweep sections. The chain is kept alive (and its errors swallowed) so one rejected
|
|
138
|
+
* permission never poisons the next; the returned promise still surfaces `fn`'s own result. */
|
|
139
|
+
enqueuePermission(fn) {
|
|
140
|
+
const run = this.permissionQueue.then(fn, fn);
|
|
141
|
+
this.permissionQueue = run.then(() => undefined, () => undefined);
|
|
142
|
+
return run;
|
|
143
|
+
}
|
|
113
144
|
/** Start the hook server, then write the scratch settings (server first, so the URL the settings
|
|
114
145
|
* point at is live before claude can ever read them; settings BEFORE the spawn is the caller's
|
|
115
146
|
* ordering contract — blocker c). */
|
|
@@ -138,9 +169,10 @@ class SessionGateImpl {
|
|
|
138
169
|
throw err;
|
|
139
170
|
}
|
|
140
171
|
}
|
|
141
|
-
bindSession(sessionId, nudge) {
|
|
172
|
+
bindSession(sessionId, nudge, resolveSubagentRelay) {
|
|
142
173
|
this.sessionId = sessionId;
|
|
143
174
|
this.nudge = nudge;
|
|
175
|
+
this.resolveSubagentRelay = resolveSubagentRelay;
|
|
144
176
|
}
|
|
145
177
|
bindPty(pty) {
|
|
146
178
|
this.pty = pty;
|
|
@@ -189,38 +221,92 @@ class SessionGateImpl {
|
|
|
189
221
|
return "deny";
|
|
190
222
|
}
|
|
191
223
|
await this.waitForCorrelation(call.toolUseId);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
224
|
+
// === Story 054 (§9 subagent relay) — AFTER the correlation wait, BEFORE the ACP prompt. ========
|
|
225
|
+
// The hook payload carries NO parent id (ForwardedToolCall has no parent_tool_use_id); the ONLY
|
|
226
|
+
// source of a subagent inner tool's parent is the session's sidechainParentMap, read lazily via
|
|
227
|
+
// the bound resolver. An undefined relay = a MAIN-CHAIN tool → both fields stay undefined and the
|
|
228
|
+
// requestPermission call below is byte-identical to today (U1). A KNOWN subagent inner tool relays
|
|
229
|
+
// its dialog under the parent Task id Zed already rendered (R1/R2) — UNLESS it cannot be safely
|
|
230
|
+
// relayed (orphan parent, or it never became a clean JSONL match within the wait window), in which
|
|
231
|
+
// case we fail LOUD (R4): a VISIBLE deny through the gate's warn surface (→ this.logger.error),
|
|
232
|
+
// naming the subagent + inner tool, and return "deny" WITHOUT raising a dialog against a bogus id.
|
|
233
|
+
const relay = this.resolveSubagentRelay?.(call.toolUseId);
|
|
234
|
+
let dialogToolCallId;
|
|
235
|
+
let subagentLabel;
|
|
236
|
+
if (relay) {
|
|
237
|
+
// isCleanMatch PROBES (does not consume); requestPermission's correlator.decide still consumes
|
|
238
|
+
// the inner id. The orphan branch short-circuits BEFORE the probe via `||`.
|
|
239
|
+
if (relay.parentId === null || !this.correlator.isCleanMatch(call.toolUseId)) {
|
|
240
|
+
this.warn(`[gate §9 subagent] FAIL CLOSED: subagent (${relay.subagentLabel}) tool "${call.toolName}" ` +
|
|
241
|
+
`(tool_use ${call.toolUseId}) ${relay.parentId === null
|
|
242
|
+
? "is an orphan — no parent Task to attach the permission dialog to"
|
|
243
|
+
: "never correlated in the JSONL within the wait window"} — denying (R4 visible deny).`);
|
|
244
|
+
return "deny";
|
|
245
|
+
}
|
|
246
|
+
dialogToolCallId = relay.parentId;
|
|
247
|
+
subagentLabel = relay.subagentLabel;
|
|
206
248
|
}
|
|
207
|
-
|
|
249
|
+
// === Story 054 (R5) — SERIALIZE only the raise+inject critical section. ========================
|
|
250
|
+
// dialogToolCallId/subagentLabel were computed above in the CONCURRENT prelude, so each enqueued
|
|
251
|
+
// request still carries its own parent Task id regardless of interleaving. Two parallel subagent
|
|
252
|
+
// decides therefore resolve INDEPENDENTLY (distinct inner ids in the correlator) but run their
|
|
253
|
+
// requestPermission + armAllowSweep one at a time — no native-prompt keystroke crossing on the
|
|
254
|
+
// shared PTY. A single sequential main-chain tool is a no-op through the queue (U1).
|
|
255
|
+
return this.enqueuePermission(async () => {
|
|
256
|
+
const decision = await requestPermission({
|
|
257
|
+
client: this.opts.client,
|
|
258
|
+
sessionId,
|
|
259
|
+
toolCall: {
|
|
260
|
+
toolUseId: call.toolUseId,
|
|
261
|
+
toolName: call.toolName,
|
|
262
|
+
toolInput: call.toolInput,
|
|
263
|
+
},
|
|
264
|
+
correlator: this.correlator,
|
|
265
|
+
onWarn: (m) => this.warn(m),
|
|
266
|
+
dialogToolCallId,
|
|
267
|
+
subagentLabel,
|
|
268
|
+
});
|
|
269
|
+
if (decision === "allow") {
|
|
270
|
+
// Return the allow body FIRST (claude is blocked on this response); sweep out of band.
|
|
271
|
+
this.armAllowSweep(call);
|
|
272
|
+
}
|
|
273
|
+
return decision;
|
|
274
|
+
});
|
|
208
275
|
}
|
|
209
276
|
/** Bounded poll until the pump has registered `toolUseId` as a clean single JSONL match. On
|
|
210
|
-
* expiry, resolve anyway — `requestPermission` then fails closed on the missing correlation.
|
|
277
|
+
* expiry, resolve anyway — `requestPermission` then fails closed on the missing correlation.
|
|
278
|
+
*
|
|
279
|
+
* Story 054 — re-nudge the pump on a ~{@link DEFAULT_CORRELATION_RENUDGE_MS} cadence (tracked
|
|
280
|
+
* SEPARATELY from the poll interval) so a sidechain inner tool_use line materializing MID-WAIT is
|
|
281
|
+
* sourced + registered before expiry — turning a would-be timeout deny into a clean subagent match.
|
|
282
|
+
* The nudge is best-effort: a throw never rejects the wait (it only widens the correlation window). */
|
|
211
283
|
waitForCorrelation(toolUseId) {
|
|
212
284
|
const waitMs = this.opts.correlationWaitMs ?? DEFAULT_CORRELATION_WAIT_MS;
|
|
213
285
|
const pollMs = this.opts.correlationPollMs ?? DEFAULT_CORRELATION_POLL_MS;
|
|
286
|
+
const renudgeMs = this.opts.correlationRenudgeMs ?? DEFAULT_CORRELATION_RENUDGE_MS;
|
|
214
287
|
if (this.correlator.isCleanMatch(toolUseId))
|
|
215
288
|
return Promise.resolve();
|
|
216
289
|
return new Promise((resolve) => {
|
|
217
290
|
let elapsed = 0;
|
|
291
|
+
let sinceNudge = 0;
|
|
218
292
|
const poll = () => {
|
|
219
293
|
if (this.torndown || this.correlator.isCleanMatch(toolUseId)) {
|
|
220
294
|
resolve();
|
|
221
295
|
return;
|
|
222
296
|
}
|
|
223
297
|
elapsed += pollMs;
|
|
298
|
+
// Re-nudge on its own cadence (NOT every poll): a lagging sidechain row gets re-sourced so it
|
|
299
|
+
// can register before the wait elapses. A nudge failure must never reject the wait.
|
|
300
|
+
sinceNudge += pollMs;
|
|
301
|
+
if (sinceNudge >= renudgeMs) {
|
|
302
|
+
sinceNudge = 0;
|
|
303
|
+
try {
|
|
304
|
+
this.nudge?.();
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// a nudge failure only widens the correlation wait; never rejects or decides by itself
|
|
308
|
+
}
|
|
309
|
+
}
|
|
224
310
|
if (elapsed >= waitMs) {
|
|
225
311
|
this.warn(`[gate §9] correlation wait expired (${waitMs}ms) for tool_use ${toolUseId} — the JSONL ` +
|
|
226
312
|
`tool_use line never reached the pump; the decision will fail closed (deny).`);
|
|
@@ -89,6 +89,11 @@ export interface RequestPermissionOptions {
|
|
|
89
89
|
correlator: ToolUseCorrelator;
|
|
90
90
|
/** Optional sink for the fail-closed diagnostics (defaults to no-op; production wires the logger). */
|
|
91
91
|
onWarn?: (message: string) => void;
|
|
92
|
+
/** Story 054 — when set, the ACP prompt attaches to this PARENT Task tool_call id (the id Zed already
|
|
93
|
+
* rendered) instead of the inner tool_use id; the correlator STILL decides on the inner id. */
|
|
94
|
+
dialogToolCallId?: string;
|
|
95
|
+
/** Story 054 — the subagent's label, named in the prompt title alongside the inner tool. */
|
|
96
|
+
subagentLabel?: string;
|
|
92
97
|
}
|
|
93
98
|
/**
|
|
94
99
|
* Correlate a forwarded tool call by `tool_use.id` and raise ACP `session/request_permission`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-permission.d.ts","sourceRoot":"","sources":["../../src/permissions/request-permission.ts"],"names":[],"mappings":"AAoBA,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC;AAEnG,oGAAoG;AACpG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,oBAAoB,CAAC;CAC5B;AAED,6FAA6F;AAC7F,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,yDAAyD;AACzD,MAAM,MAAM,wBAAwB,GAChC;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,GACxB;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,wBAAwB,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CACtF;AAED,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wFAAwF;AACxF,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC,gFAAgF;AAChF,wBAAgB,sBAAsB,IAAI,gBAAgB,EAAE,CAK3D;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAC5B,8FAA8F;IAC9F,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,qGAAqG;IACrG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAE9C;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMpC,iGAAiG;IACjG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM;CAS9C;AAED,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,sFAAsF;IACtF,UAAU,EAAE,iBAAiB,CAAC;IAC9B,sGAAsG;IACtG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"request-permission.d.ts","sourceRoot":"","sources":["../../src/permissions/request-permission.ts"],"names":[],"mappings":"AAoBA,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC;AAEnG,oGAAoG;AACpG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,oBAAoB,CAAC;CAC5B;AAED,6FAA6F;AAC7F,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,yDAAyD;AACzD,MAAM,MAAM,wBAAwB,GAChC;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,GACxB;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,wBAAwB,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CACtF;AAED,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wFAAwF;AACxF,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC,gFAAgF;AAChF,wBAAgB,sBAAsB,IAAI,gBAAgB,EAAE,CAK3D;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAC5B,8FAA8F;IAC9F,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,qGAAqG;IACrG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAE9C;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMpC,iGAAiG;IACjG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM;CAS9C;AAED,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,sFAAsF;IACtF,UAAU,EAAE,iBAAiB,CAAC;IAC9B,sGAAsG;IACtG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;oGACgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAuDjG"}
|
|
@@ -81,7 +81,7 @@ export class ToolUseCorrelator {
|
|
|
81
81
|
* `'deny'` otherwise.
|
|
82
82
|
*/
|
|
83
83
|
export async function requestPermission(opts) {
|
|
84
|
-
const { client, sessionId, toolCall, correlator, onWarn } = opts;
|
|
84
|
+
const { client, sessionId, toolCall, correlator, onWarn, dialogToolCallId, subagentLabel } = opts;
|
|
85
85
|
// 1) Correlate by tool_use.id BEFORE asking — an uncorrelated/duplicate call is denied, not prompted.
|
|
86
86
|
const correlation = correlator.decide(toolCall.toolUseId);
|
|
87
87
|
if (correlation === "deny") {
|
|
@@ -96,8 +96,13 @@ export async function requestPermission(opts) {
|
|
|
96
96
|
result = await client.requestPermission({
|
|
97
97
|
sessionId,
|
|
98
98
|
toolCall: {
|
|
99
|
-
|
|
100
|
-
title
|
|
99
|
+
// Story 054: a subagent inner tool relays under the PARENT Task id Zed already rendered
|
|
100
|
+
// (dialogToolCallId), naming the inner tool + subagent in the title. A main-chain call (no
|
|
101
|
+
// dialogToolCallId) is byte-identical to today: toolCallId = inner id, title = bare tool name.
|
|
102
|
+
toolCallId: dialogToolCallId ?? toolCall.toolUseId,
|
|
103
|
+
title: dialogToolCallId !== undefined
|
|
104
|
+
? `${toolCall.toolName} · from the ${subagentLabel ?? "subagent"} agent`
|
|
105
|
+
: toolCall.toolName,
|
|
101
106
|
rawInput: toolCall.toolInput,
|
|
102
107
|
},
|
|
103
108
|
options: buildPermissionOptions(),
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SessionMessage } from "./engine-watcher.js";
|
|
2
|
+
import type { ToolUseCorrelator } from "./permissions/request-permission.js";
|
|
3
|
+
/**
|
|
4
|
+
* One inner subagent `tool_use` extracted from a sidechain row — the unit the gate correlator is fed
|
|
5
|
+
* and the dialog is built from.
|
|
6
|
+
*/
|
|
7
|
+
export interface SidechainToolUse {
|
|
8
|
+
/** The inner `tool_use.id` — the correlation key fed into the gate correlator. */
|
|
9
|
+
id: string;
|
|
10
|
+
/** The spawning `Task`/`Agent` `tool_use.id` (the row's `parent_tool_use_id`); `null` = orphan. */
|
|
11
|
+
parentId: string | null;
|
|
12
|
+
/** The inner tool name (e.g. `"Bash"`, `"perplexity"`) — shown in the Zed prompt title. */
|
|
13
|
+
toolName: string;
|
|
14
|
+
/** The inner tool's raw input — forwarded to the dialog (R7). */
|
|
15
|
+
toolInput: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Collect every inner subagent `tool_use` from the pump's sidechain `rows` (R3, R7).
|
|
19
|
+
*
|
|
20
|
+
* Walks each SIDECHAIN `type === "assistant"` row's `message.content` and emits one
|
|
21
|
+
* {@link SidechainToolUse} per `tool_use` block, in encounter order:
|
|
22
|
+
* - `id` ← block.id
|
|
23
|
+
* - `parentId` ← row.parent_tool_use_id ?? null (a row with NO parent field → `null`, an orphan)
|
|
24
|
+
* - `toolName` ← block.name
|
|
25
|
+
* - `toolInput` ← block.input (raw, for the dialog — R7)
|
|
26
|
+
*
|
|
27
|
+
* A row counts as a SIDECHAIN row when flagged `isSidechain === true` (raw-shaped fixtures) OR — in the
|
|
28
|
+
* SDK's reduced LIVE shape, which carries NO `isSidechain` field — when it has a non-empty string
|
|
29
|
+
* `parent_tool_use_id` (the only sidechain signal in the reduced shape; mirrors `linearize.ts`
|
|
30
|
+
* `isSidechainMsg`, which the proven story-041 nested render relies on). The spawning `Task`/`Agent`
|
|
31
|
+
* `tool_use` lives on the MAIN chain (no `parent_tool_use_id`, no `isSidechain`), so it is excluded —
|
|
32
|
+
* the gate owns the main chain separately. (In production the pump hands us sidechain-only rows from
|
|
33
|
+
* `sourceSubagentRows`; the guard also keeps the helper correct when fed a full transcript.)
|
|
34
|
+
*
|
|
35
|
+
* Non-`tool_use` content blocks (text, tool_result, …) contribute nothing — a text-only sidechain row
|
|
36
|
+
* yields no entries (the live fixture's sidechain rows are text-only → `[]`). Tolerant of the reduced
|
|
37
|
+
* shape in the {@link import("./subagent-source.js").hasSubagentSpawn} style: non-object rows/messages
|
|
38
|
+
* and non-array `content` are simply skipped.
|
|
39
|
+
*/
|
|
40
|
+
export declare function collectSidechainToolUses(rows: SessionMessage[]): SidechainToolUse[];
|
|
41
|
+
/**
|
|
42
|
+
* Feed each collected {@link SidechainToolUse} into the gate `correlator` EXACTLY ONCE (R3).
|
|
43
|
+
*
|
|
44
|
+
* For every `use` whose `id` is NOT already in the `registered` dedup Set:
|
|
45
|
+
* - `correlator.register(use.id)` — record the id in the JSONL correlation map so a subsequent hook
|
|
46
|
+
* tool call is a clean single match (its return value is ignored; the Set is the dedup truth);
|
|
47
|
+
* - `registered.add(use.id)` — mark it fed for this session;
|
|
48
|
+
* - `parentMap.set(use.id, use)` — map the inner id to its use entry (carries parentId + input).
|
|
49
|
+
*
|
|
50
|
+
* Ids already in `registered` are SKIPPED. The pump re-reads overlapping rows on each pass; a naive
|
|
51
|
+
* re-`register` of the same id would increment its count to 2 → the correlator treats it as a DUPLICATE
|
|
52
|
+
* → fail-closed deny. The dedup Set is what keeps every clean id `isCleanMatch === true` across those
|
|
53
|
+
* overlapping re-reads.
|
|
54
|
+
*
|
|
55
|
+
* Mutates `correlator`, `registered`, and `parentMap` in place; returns nothing.
|
|
56
|
+
*/
|
|
57
|
+
export declare function registerSidechainGateToolUses(uses: SidechainToolUse[], correlator: ToolUseCorrelator, registered: Set<string>, parentMap: Map<string, SidechainToolUse>): void;
|
|
58
|
+
//# sourceMappingURL=subagent-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-gate.d.ts","sourceRoot":"","sources":["../src/subagent-gate.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,mGAAmG;IACnG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;CACpB;AAOD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAgCnF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,gBAAgB,EAAE,EACxB,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACvC,IAAI,CAON"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Story 054 / Group 1 (tasks 1.1 + 1.2) — pure helpers that turn the pump's already-sourced sidechain
|
|
2
|
+
// rows into the gate correlator's feed.
|
|
3
|
+
//
|
|
4
|
+
// The original `canUseTool` path covered subagent tool calls automatically; the JSONL+PTY rewrite's
|
|
5
|
+
// gate (request-permission.ts) only correlates ids it has been fed from the MAIN chain, so a subagent
|
|
6
|
+
// tool call has no clean match and fails closed (deny) — the gap proven by the story-053 in-Zed run.
|
|
7
|
+
// This module closes that gap by sourcing the inner `tool_use` ids from the sidechain rows the pump
|
|
8
|
+
// already reads (subagent-source.ts `sourceSubagentRows`) and registering each into the correlator
|
|
9
|
+
// EXACTLY ONCE, so the subagent tool call becomes a clean single match and reaches the ACP prompt with
|
|
10
|
+
// the inner tool's input (R3, R7).
|
|
11
|
+
//
|
|
12
|
+
// MODULE LOCATION (intentional, frozen by the pre-authored test): design.md/tasks.md name this
|
|
13
|
+
// `src/permissions/subagent-gate.ts`, but the test imports `../dist/subagent-gate.js` (the ROOT of
|
|
14
|
+
// dist/). With tsconfig rootDir:src → outDir:dist this module MUST live at `src/subagent-gate.ts` so it
|
|
15
|
+
// compiles to `dist/subagent-gate.js`. The test's import line is immutable; the file location bends to
|
|
16
|
+
// it (call-surface only, no behavior change).
|
|
17
|
+
//
|
|
18
|
+
// Pure: no I/O, no logging, no SDK eval. The only effects are the mutations of the passed-in
|
|
19
|
+
// `correlator` / `registered` Set / `parentMap` (the per-session feed state the pump owns).
|
|
20
|
+
/** Narrowing helper: a non-null, non-array plain object (so we can read string-keyed props safely). */
|
|
21
|
+
function isObject(value) {
|
|
22
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Collect every inner subagent `tool_use` from the pump's sidechain `rows` (R3, R7).
|
|
26
|
+
*
|
|
27
|
+
* Walks each SIDECHAIN `type === "assistant"` row's `message.content` and emits one
|
|
28
|
+
* {@link SidechainToolUse} per `tool_use` block, in encounter order:
|
|
29
|
+
* - `id` ← block.id
|
|
30
|
+
* - `parentId` ← row.parent_tool_use_id ?? null (a row with NO parent field → `null`, an orphan)
|
|
31
|
+
* - `toolName` ← block.name
|
|
32
|
+
* - `toolInput` ← block.input (raw, for the dialog — R7)
|
|
33
|
+
*
|
|
34
|
+
* A row counts as a SIDECHAIN row when flagged `isSidechain === true` (raw-shaped fixtures) OR — in the
|
|
35
|
+
* SDK's reduced LIVE shape, which carries NO `isSidechain` field — when it has a non-empty string
|
|
36
|
+
* `parent_tool_use_id` (the only sidechain signal in the reduced shape; mirrors `linearize.ts`
|
|
37
|
+
* `isSidechainMsg`, which the proven story-041 nested render relies on). The spawning `Task`/`Agent`
|
|
38
|
+
* `tool_use` lives on the MAIN chain (no `parent_tool_use_id`, no `isSidechain`), so it is excluded —
|
|
39
|
+
* the gate owns the main chain separately. (In production the pump hands us sidechain-only rows from
|
|
40
|
+
* `sourceSubagentRows`; the guard also keeps the helper correct when fed a full transcript.)
|
|
41
|
+
*
|
|
42
|
+
* Non-`tool_use` content blocks (text, tool_result, …) contribute nothing — a text-only sidechain row
|
|
43
|
+
* yields no entries (the live fixture's sidechain rows are text-only → `[]`). Tolerant of the reduced
|
|
44
|
+
* shape in the {@link import("./subagent-source.js").hasSubagentSpawn} style: non-object rows/messages
|
|
45
|
+
* and non-array `content` are simply skipped.
|
|
46
|
+
*/
|
|
47
|
+
export function collectSidechainToolUses(rows) {
|
|
48
|
+
const uses = [];
|
|
49
|
+
for (const row of rows) {
|
|
50
|
+
if (!isObject(row))
|
|
51
|
+
continue;
|
|
52
|
+
if (row.type !== "assistant")
|
|
53
|
+
continue;
|
|
54
|
+
// Sidechain detection: `isSidechain === true` (raw-shaped fixtures) OR a non-empty string
|
|
55
|
+
// `parent_tool_use_id` — the ONLY sidechain signal in the SDK's reduced LIVE shape, which omits
|
|
56
|
+
// `isSidechain` (mirrors linearize.ts `isSidechainMsg`). A row with no `parent_tool_use_id` field is
|
|
57
|
+
// an orphan → parentId is `null`, not `undefined`.
|
|
58
|
+
const rawParent = row.parent_tool_use_id;
|
|
59
|
+
const parentId = typeof rawParent === "string" && rawParent.length > 0 ? rawParent : null;
|
|
60
|
+
// The main-chain Task/Agent spawn has neither the flag nor a parent → excluded; the gate owns it.
|
|
61
|
+
if (row.isSidechain !== true && parentId === null)
|
|
62
|
+
continue;
|
|
63
|
+
const inner = row.message;
|
|
64
|
+
if (!isObject(inner))
|
|
65
|
+
continue;
|
|
66
|
+
const content = inner.content;
|
|
67
|
+
if (!Array.isArray(content))
|
|
68
|
+
continue;
|
|
69
|
+
for (const block of content) {
|
|
70
|
+
if (!isObject(block))
|
|
71
|
+
continue;
|
|
72
|
+
if (block.type !== "tool_use")
|
|
73
|
+
continue;
|
|
74
|
+
if (typeof block.id !== "string" || typeof block.name !== "string")
|
|
75
|
+
continue;
|
|
76
|
+
uses.push({
|
|
77
|
+
id: block.id,
|
|
78
|
+
parentId,
|
|
79
|
+
toolName: block.name,
|
|
80
|
+
toolInput: block.input,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return uses;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Feed each collected {@link SidechainToolUse} into the gate `correlator` EXACTLY ONCE (R3).
|
|
88
|
+
*
|
|
89
|
+
* For every `use` whose `id` is NOT already in the `registered` dedup Set:
|
|
90
|
+
* - `correlator.register(use.id)` — record the id in the JSONL correlation map so a subsequent hook
|
|
91
|
+
* tool call is a clean single match (its return value is ignored; the Set is the dedup truth);
|
|
92
|
+
* - `registered.add(use.id)` — mark it fed for this session;
|
|
93
|
+
* - `parentMap.set(use.id, use)` — map the inner id to its use entry (carries parentId + input).
|
|
94
|
+
*
|
|
95
|
+
* Ids already in `registered` are SKIPPED. The pump re-reads overlapping rows on each pass; a naive
|
|
96
|
+
* re-`register` of the same id would increment its count to 2 → the correlator treats it as a DUPLICATE
|
|
97
|
+
* → fail-closed deny. The dedup Set is what keeps every clean id `isCleanMatch === true` across those
|
|
98
|
+
* overlapping re-reads.
|
|
99
|
+
*
|
|
100
|
+
* Mutates `correlator`, `registered`, and `parentMap` in place; returns nothing.
|
|
101
|
+
*/
|
|
102
|
+
export function registerSidechainGateToolUses(uses, correlator, registered, parentMap) {
|
|
103
|
+
for (const use of uses) {
|
|
104
|
+
if (registered.has(use.id))
|
|
105
|
+
continue; // already fed this session — never double-register.
|
|
106
|
+
correlator.register(use.id);
|
|
107
|
+
registered.add(use.id);
|
|
108
|
+
parentMap.set(use.id, use);
|
|
109
|
+
}
|
|
110
|
+
}
|
package/package.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
7
|
-
"description": "Run the official Claude Code TUI in Zed's agent panel on your Claude Pro/Max subscription — an ACP-over-PTY bridge created for Anthropic's
|
|
6
|
+
"version": "0.5.0",
|
|
7
|
+
"description": "Run the official Claude Code TUI in Zed's agent panel on your Claude Pro/Max subscription — an ACP-over-PTY bridge created for Anthropic's billing split (paused June 15; see README).",
|
|
8
8
|
"main": "dist/lib.js",
|
|
9
9
|
"types": "dist/lib.d.ts",
|
|
10
10
|
"bin": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"format:check": "prettier --check .",
|
|
37
37
|
"check": "npm run lint && npm run format:check",
|
|
38
38
|
"test": "npm run build && node --experimental-strip-types --test test/*.test.ts",
|
|
39
|
+
"smoke:live": "node experiments/smoke-live.mjs",
|
|
39
40
|
"prepublishOnly": "npm run build"
|
|
40
41
|
},
|
|
41
42
|
"keywords": [
|
|
@@ -59,18 +60,18 @@
|
|
|
59
60
|
"author": "lucascouts",
|
|
60
61
|
"license": "Apache-2.0",
|
|
61
62
|
"dependencies": {
|
|
62
|
-
"@agentclientprotocol/sdk": "0.
|
|
63
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
63
|
+
"@agentclientprotocol/sdk": "0.28.1",
|
|
64
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.183",
|
|
64
65
|
"node-pty": "1.1.0",
|
|
65
66
|
"zod": "^3.25.0 || ^4.0.0"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
|
-
"@anthropic-ai/sdk": "0.
|
|
69
|
+
"@anthropic-ai/sdk": "0.105.0",
|
|
69
70
|
"@eslint/js": "10.0.1",
|
|
70
|
-
"@types/node": "
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "8.61.
|
|
72
|
-
"@typescript-eslint/parser": "8.61.
|
|
73
|
-
"eslint": "10.
|
|
71
|
+
"@types/node": "26.0.0",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "8.61.1",
|
|
73
|
+
"@typescript-eslint/parser": "8.61.1",
|
|
74
|
+
"eslint": "10.5.0",
|
|
74
75
|
"eslint-config-prettier": "10.1.8",
|
|
75
76
|
"globals": "17.6.0",
|
|
76
77
|
"prettier": "3.8.4",
|