@lucascouts/claude-agent-tui 0.1.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/LICENSE +191 -0
- package/NOTICE +14 -0
- package/README.md +50 -0
- package/dist/acp-agent.d.ts +594 -0
- package/dist/acp-agent.d.ts.map +1 -0
- package/dist/acp-agent.js +2139 -0
- package/dist/ansi-mirror.d.ts +42 -0
- package/dist/ansi-mirror.d.ts.map +1 -0
- package/dist/ansi-mirror.js +61 -0
- package/dist/besteffort.d.ts +44 -0
- package/dist/besteffort.d.ts.map +1 -0
- package/dist/besteffort.js +100 -0
- package/dist/billing/entrypoint-guard.d.ts +97 -0
- package/dist/billing/entrypoint-guard.d.ts.map +1 -0
- package/dist/billing/entrypoint-guard.js +166 -0
- package/dist/claude-path.d.ts +12 -0
- package/dist/claude-path.d.ts.map +1 -0
- package/dist/claude-path.js +61 -0
- package/dist/diff-enriched-reader.d.ts +41 -0
- package/dist/diff-enriched-reader.d.ts.map +1 -0
- package/dist/diff-enriched-reader.js +106 -0
- package/dist/diff-source.d.ts +104 -0
- package/dist/diff-source.d.ts.map +1 -0
- package/dist/diff-source.js +164 -0
- package/dist/end-of-turn.d.ts +172 -0
- package/dist/end-of-turn.d.ts.map +1 -0
- package/dist/end-of-turn.js +415 -0
- package/dist/engine-lifecycle.d.ts +222 -0
- package/dist/engine-lifecycle.d.ts.map +1 -0
- package/dist/engine-lifecycle.js +236 -0
- package/dist/engine-pty.d.ts +143 -0
- package/dist/engine-pty.d.ts.map +1 -0
- package/dist/engine-pty.js +222 -0
- package/dist/engine-watcher.d.ts +83 -0
- package/dist/engine-watcher.d.ts.map +1 -0
- package/dist/engine-watcher.js +173 -0
- package/dist/engine.d.ts +30 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +34 -0
- package/dist/event-switch.d.ts +164 -0
- package/dist/event-switch.d.ts.map +1 -0
- package/dist/event-switch.js +206 -0
- package/dist/gate/port.d.ts +38 -0
- package/dist/gate/port.d.ts.map +1 -0
- package/dist/gate/port.js +126 -0
- package/dist/gate/settings-writer.d.ts +130 -0
- package/dist/gate/settings-writer.d.ts.map +1 -0
- package/dist/gate/settings-writer.js +349 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/jsonl.d.ts +267 -0
- package/dist/jsonl.d.ts.map +1 -0
- package/dist/jsonl.js +527 -0
- package/dist/lib.d.ts +6 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +5 -0
- package/dist/linearize.d.ts +219 -0
- package/dist/linearize.d.ts.map +1 -0
- package/dist/linearize.js +444 -0
- package/dist/live-diff-env.d.ts +7 -0
- package/dist/live-diff-env.d.ts.map +1 -0
- package/dist/live-diff-env.js +18 -0
- package/dist/live-subagent-env.d.ts +7 -0
- package/dist/live-subagent-env.d.ts.map +1 -0
- package/dist/live-subagent-env.js +19 -0
- package/dist/permissions/allow-inject.d.ts +67 -0
- package/dist/permissions/allow-inject.d.ts.map +1 -0
- package/dist/permissions/allow-inject.js +85 -0
- package/dist/permissions/deny.d.ts +60 -0
- package/dist/permissions/deny.d.ts.map +1 -0
- package/dist/permissions/deny.js +81 -0
- package/dist/permissions/gate-wiring.d.ts +112 -0
- package/dist/permissions/gate-wiring.d.ts.map +1 -0
- package/dist/permissions/gate-wiring.js +350 -0
- package/dist/permissions/hook-server.d.ts +72 -0
- package/dist/permissions/hook-server.d.ts.map +1 -0
- package/dist/permissions/hook-server.js +179 -0
- package/dist/permissions/permission-mode.d.ts +67 -0
- package/dist/permissions/permission-mode.d.ts.map +1 -0
- package/dist/permissions/permission-mode.js +100 -0
- package/dist/permissions/request-permission.d.ts +102 -0
- package/dist/permissions/request-permission.d.ts.map +1 -0
- package/dist/permissions/request-permission.js +124 -0
- package/dist/settings.d.ts +68 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +182 -0
- package/dist/stop-reason-map.d.ts +17 -0
- package/dist/stop-reason-map.d.ts.map +1 -0
- package/dist/stop-reason-map.js +33 -0
- package/dist/subagent-source.d.ts +63 -0
- package/dist/subagent-source.d.ts.map +1 -0
- package/dist/subagent-source.js +132 -0
- package/dist/subagent-watcher.d.ts +40 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +108 -0
- package/dist/tools.d.ts +119 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +729 -0
- package/dist/usage-env.d.ts +7 -0
- package/dist/usage-env.d.ts.map +1 -0
- package/dist/usage-env.js +16 -0
- package/dist/usage.d.ts +54 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +53 -0
- package/dist/utils.d.ts +16 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +83 -0
- package/dist/zed-register.d.ts +26 -0
- package/dist/zed-register.d.ts.map +1 -0
- package/dist/zed-register.js +106 -0
- package/package.json +79 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 043 (R2.2) — the LIVE_DIFF entrypoint flag parse. Defaults ON: only the explicit
|
|
3
|
+
* opt-out values "0"/"false" disable it (unset/empty/any other value → ON). Pure + testable;
|
|
4
|
+
* index.ts calls this so the truth table is unit-checkable without running the entrypoint.
|
|
5
|
+
*/
|
|
6
|
+
export declare function liveDiffEnabled(env?: Record<string, string | undefined>): boolean;
|
|
7
|
+
//# sourceMappingURL=live-diff-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-diff-env.d.ts","sourceRoot":"","sources":["../src/live-diff-env.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO,CAE9F"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Story 043 / Task 2.1 (R2.2) — the LIVE_DIFF entrypoint flag parse. Defaults ON: the live Edit/Write
|
|
2
|
+
// diff (the story-021 structuredPatch diff, hydrated onto the reduced-shape JSONL via the diff-enriched
|
|
3
|
+
// reader — see diff-enriched-reader.ts) is emitted by default on BOTH the live pump and the session/load
|
|
4
|
+
// replay, and only the explicit opt-out values "0"/"false" disable it (unset / empty / any other value
|
|
5
|
+
// → ON). This is the v2 default per the FORK.md 4.2 rationale: with the PTY engine the PostToolUse hook
|
|
6
|
+
// that once produced diffs is GONE, so the reduced shape renders no diff unless we hydrate `toolUseResult`
|
|
7
|
+
// by uuid; defaulting ON restores the story-021 diff for live Edit/Write. OFF → byte-for-byte the pre-043
|
|
8
|
+
// reduced reader (R5.1). Kept a self-contained, PURE module (cf. usage-env.ts) so the truth table is
|
|
9
|
+
// unit-checkable without booting the entrypoint; index.ts calls it and threads the result through
|
|
10
|
+
// runAcp → AgentDeps → the agent. It does NOT go through lib.ts (the frozen upstream export surface).
|
|
11
|
+
/**
|
|
12
|
+
* Story 043 (R2.2) — the LIVE_DIFF entrypoint flag parse. Defaults ON: only the explicit
|
|
13
|
+
* opt-out values "0"/"false" disable it (unset/empty/any other value → ON). Pure + testable;
|
|
14
|
+
* index.ts calls this so the truth table is unit-checkable without running the entrypoint.
|
|
15
|
+
*/
|
|
16
|
+
export function liveDiffEnabled(env = process.env) {
|
|
17
|
+
return env.LIVE_DIFF !== "0" && env.LIVE_DIFF !== "false";
|
|
18
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 044 (R4.1) — the FORK_LIVE_SUBAGENT_WATCH entrypoint flag parse. Defaults ON: only the
|
|
3
|
+
* explicit opt-out values "0"/"false" disable it (unset/empty/any other value → ON). Pure + testable;
|
|
4
|
+
* index.ts calls this so the truth table is unit-checkable without running the entrypoint.
|
|
5
|
+
*/
|
|
6
|
+
export declare function liveSubagentWatchEnabled(env?: Record<string, string | undefined>): boolean;
|
|
7
|
+
//# sourceMappingURL=live-subagent-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-subagent-env.d.ts","sourceRoot":"","sources":["../src/live-subagent-env.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO,CAEvG"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Story 044 / Task 2.1 (R4.1, R4.2) — the FORK_LIVE_SUBAGENT_WATCH entrypoint flag parse. Defaults
|
|
2
|
+
// ON: the live sub-agent watcher (the story-044 Option-B 2nd watcher that POLLs the SDK sidechain
|
|
3
|
+
// readers while a turn is in flight, feeding the story-024 detector's noteActivity() seam and the
|
|
4
|
+
// incremental nested render) is armed by default, and only the explicit opt-out values "0"/"false"
|
|
5
|
+
// disable it (unset / empty / any other value → ON). This closes the story-041 R4.2 live gap: a
|
|
6
|
+
// long-running sub-agent (e.g. a ~7-minute `Agent` Task) writes only subagents/*.jsonl while the
|
|
7
|
+
// MAIN transcript stays silent, so the turn watchdog false-stalls a turn that is actually
|
|
8
|
+
// progressing. OFF → byte-for-byte today's pull-only path: NO 2nd watcher armed (R4.2). Kept a
|
|
9
|
+
// self-contained, PURE module (cf. usage-env.ts / live-diff-env.ts) so the truth table is
|
|
10
|
+
// unit-checkable without booting the entrypoint; index.ts calls it and threads the result through
|
|
11
|
+
// runAcp → AgentDeps → the agent. It does NOT go through lib.ts (the frozen upstream export surface).
|
|
12
|
+
/**
|
|
13
|
+
* Story 044 (R4.1) — the FORK_LIVE_SUBAGENT_WATCH entrypoint flag parse. Defaults ON: only the
|
|
14
|
+
* explicit opt-out values "0"/"false" disable it (unset/empty/any other value → ON). Pure + testable;
|
|
15
|
+
* index.ts calls this so the truth table is unit-checkable without running the entrypoint.
|
|
16
|
+
*/
|
|
17
|
+
export function liveSubagentWatchEnabled(env = process.env) {
|
|
18
|
+
return env.FORK_LIVE_SUBAGENT_WATCH !== "0" && env.FORK_LIVE_SUBAGENT_WATCH !== "false";
|
|
19
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** The story-032 PTY input primitive this module needs — structurally satisfied by node-pty's IPty. */
|
|
2
|
+
export interface PtyWriter {
|
|
3
|
+
write(data: string): void;
|
|
4
|
+
}
|
|
5
|
+
/** The keystrokes the native TUI permission prompt accepts (§9): Yes = `'1\r'`, refusal types `'No'`. */
|
|
6
|
+
export declare const KEYSTROKE_YES = "1\r";
|
|
7
|
+
export declare const KEYSTROKE_NO = "No";
|
|
8
|
+
/** Default time (ms) to wait for the native prompt to clear after a keystroke before warning. */
|
|
9
|
+
export declare const DEFAULT_INJECT_TIMEOUT_MS = 2000;
|
|
10
|
+
/** Default poll interval (ms) between prompt-cleared probes. */
|
|
11
|
+
export declare const DEFAULT_INJECT_POLL_MS = 50;
|
|
12
|
+
/**
|
|
13
|
+
* Pick the keystroke for a decision (R3.1). `'allow'` → `'1\r'` (Yes / first option); `'deny'` →
|
|
14
|
+
* `'No'` (refusal). Exposed as a pure function so the choice is unit-testable without a PTY.
|
|
15
|
+
*
|
|
16
|
+
* @param decision the gate's enforced decision.
|
|
17
|
+
* @returns the keystroke string to type into the native prompt.
|
|
18
|
+
*/
|
|
19
|
+
export declare function keystrokeFor(decision: "allow" | "deny"): string;
|
|
20
|
+
/** Injectable timer seam (the same `schedule`/clock discipline as end-of-turn + sendPrompt). */
|
|
21
|
+
export type Schedule = (fn: () => void, ms: number) => void;
|
|
22
|
+
/** The outcome of an allow-path keystroke injection. */
|
|
23
|
+
export type InjectResult = {
|
|
24
|
+
status: "cleared";
|
|
25
|
+
keystroke: string;
|
|
26
|
+
} | {
|
|
27
|
+
status: "suppressed";
|
|
28
|
+
} | {
|
|
29
|
+
status: "stuck";
|
|
30
|
+
keystroke: string;
|
|
31
|
+
};
|
|
32
|
+
/** Options for {@link clearNativePrompt}. */
|
|
33
|
+
export interface ClearNativePromptOptions {
|
|
34
|
+
/** The story-032 PTY input primitive (production: the session's IPty). */
|
|
35
|
+
pty: PtyWriter;
|
|
36
|
+
/** The gate's enforced decision (`'allow'` types Yes; `'deny'` types No). */
|
|
37
|
+
decision: "allow" | "deny";
|
|
38
|
+
/**
|
|
39
|
+
* Probe whether the native TUI prompt is CURRENTLY shown. Production wires this to an ANSI-mirror /
|
|
40
|
+
* TUI-state check; injected so a unit test models "prompt shown → cleared after keystroke" or
|
|
41
|
+
* "prompt stuck". Called before injecting (to skip the suppressed case) and after (to confirm it
|
|
42
|
+
* cleared).
|
|
43
|
+
*/
|
|
44
|
+
isPromptShown: () => boolean;
|
|
45
|
+
/** Max ms to wait for the prompt to clear before warning (default {@link DEFAULT_INJECT_TIMEOUT_MS}). */
|
|
46
|
+
timeoutMs?: number;
|
|
47
|
+
/** Poll interval (ms) between cleared-probes (default {@link DEFAULT_INJECT_POLL_MS}). */
|
|
48
|
+
pollMs?: number;
|
|
49
|
+
/** Injectable timer (default setTimeout). */
|
|
50
|
+
schedule?: Schedule;
|
|
51
|
+
/** Warning sink for the stuck-prompt case (default no-op; production wires the logger). */
|
|
52
|
+
onWarn?: (message: string) => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Clear the native TUI prompt for an allow/deny decision when it is NOT suppressed (#52822 mitigation).
|
|
56
|
+
*
|
|
57
|
+
* 1. If `isPromptShown()` is already false, the native prompt was suppressed (the 2.1.161 case) — return
|
|
58
|
+
* `'suppressed'` WITHOUT typing anything (we never type into a prompt that is not there).
|
|
59
|
+
* 2. Otherwise type the keystroke (`'1\r'`=Yes for allow, `'No'` for deny) via the PTY writer, then
|
|
60
|
+
* poll `isPromptShown()` until it clears or the timeout elapses.
|
|
61
|
+
* 3. On clear → `'cleared'`. On timeout → surface a stuck-prompt warning and return `'stuck'` (the
|
|
62
|
+
* caller must NOT treat this as an approval — R3.2: no silent approve).
|
|
63
|
+
*
|
|
64
|
+
* @returns an {@link InjectResult}: `'suppressed'` | `'cleared'` | `'stuck'`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function clearNativePrompt(opts: ClearNativePromptOptions): Promise<InjectResult>;
|
|
67
|
+
//# sourceMappingURL=allow-inject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allow-inject.d.ts","sourceRoot":"","sources":["../../src/permissions/allow-inject.ts"],"names":[],"mappings":"AAsBA,uGAAuG;AACvG,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,yGAAyG;AACzG,eAAO,MAAM,aAAa,QAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAE/D;AAED,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;AAM5D,wDAAwD;AACxD,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GACxB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3C,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,0EAA0E;IAC1E,GAAG,EAAE,SAAS,CAAC;IACf,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC;IAC7B,yGAAyG;IACzG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4CvF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Story 033 / Task 3.1 — hybrid ALLOW path: on a non-suppressed native prompt (#52822), inject the
|
|
2
|
+
// keystroke into the PTY via the story-032 input driver; on timeout, WARN — never silently approve
|
|
3
|
+
// (R3.1, R3.2).
|
|
4
|
+
//
|
|
5
|
+
// WHY (IMPLEMENTACAO-FORK-ACP.md §9 / GATE_FINDINGS.md #52822): allow does NOT reliably suppress the
|
|
6
|
+
// native TUI prompt. The Degrau-0 probe saw suppression on claude 2.1.161, but that is VERSION-FRAGILE
|
|
7
|
+
// (it may depend on the absence of an `ask` rule + the user's own permissions.allow rules) and is NOT
|
|
8
|
+
// guaranteed. So after the gate returns `allow`, if the native prompt is STILL shown we clear it by
|
|
9
|
+
// typing the keystroke into the PTY: `'1\r'` = Yes (the first/affirmative option), or `'No'` for a
|
|
10
|
+
// refusal. We NEVER assume suppression, and we NEVER spoof an affirmative keystroke for a tool the user
|
|
11
|
+
// actually denied.
|
|
12
|
+
//
|
|
13
|
+
// FAIL CLOSED (design.md): if the injection does not clear the prompt within a timeout, we surface a
|
|
14
|
+
// stuck-prompt warning and HOLD — we do NOT report success / silently approve. The caller treats a
|
|
15
|
+
// stuck prompt as unresolved, not as an allow.
|
|
16
|
+
//
|
|
17
|
+
// REUSE: the keystroke goes through the story-032 PTY input primitive (`IPty.write` — the same
|
|
18
|
+
// primitive `sendPrompt` and the cancel ladder `interrupt`/`escape` use). We write the raw keystroke
|
|
19
|
+
// directly (NOT via `sendPrompt`, which would append its own delayed `\r` for a normal prompt); the
|
|
20
|
+
// `'1\r'` already carries its Enter. Injected behind a minimal `PtyWriter` seam so this is unit-testable
|
|
21
|
+
// OFFLINE with a fake PTY.
|
|
22
|
+
/** The keystrokes the native TUI permission prompt accepts (§9): Yes = `'1\r'`, refusal types `'No'`. */
|
|
23
|
+
export const KEYSTROKE_YES = "1\r";
|
|
24
|
+
export const KEYSTROKE_NO = "No";
|
|
25
|
+
/** Default time (ms) to wait for the native prompt to clear after a keystroke before warning. */
|
|
26
|
+
export const DEFAULT_INJECT_TIMEOUT_MS = 2000;
|
|
27
|
+
/** Default poll interval (ms) between prompt-cleared probes. */
|
|
28
|
+
export const DEFAULT_INJECT_POLL_MS = 50;
|
|
29
|
+
/**
|
|
30
|
+
* Pick the keystroke for a decision (R3.1). `'allow'` → `'1\r'` (Yes / first option); `'deny'` →
|
|
31
|
+
* `'No'` (refusal). Exposed as a pure function so the choice is unit-testable without a PTY.
|
|
32
|
+
*
|
|
33
|
+
* @param decision the gate's enforced decision.
|
|
34
|
+
* @returns the keystroke string to type into the native prompt.
|
|
35
|
+
*/
|
|
36
|
+
export function keystrokeFor(decision) {
|
|
37
|
+
return decision === "allow" ? KEYSTROKE_YES : KEYSTROKE_NO;
|
|
38
|
+
}
|
|
39
|
+
const defaultSchedule = (fn, ms) => {
|
|
40
|
+
setTimeout(fn, ms);
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Clear the native TUI prompt for an allow/deny decision when it is NOT suppressed (#52822 mitigation).
|
|
44
|
+
*
|
|
45
|
+
* 1. If `isPromptShown()` is already false, the native prompt was suppressed (the 2.1.161 case) — return
|
|
46
|
+
* `'suppressed'` WITHOUT typing anything (we never type into a prompt that is not there).
|
|
47
|
+
* 2. Otherwise type the keystroke (`'1\r'`=Yes for allow, `'No'` for deny) via the PTY writer, then
|
|
48
|
+
* poll `isPromptShown()` until it clears or the timeout elapses.
|
|
49
|
+
* 3. On clear → `'cleared'`. On timeout → surface a stuck-prompt warning and return `'stuck'` (the
|
|
50
|
+
* caller must NOT treat this as an approval — R3.2: no silent approve).
|
|
51
|
+
*
|
|
52
|
+
* @returns an {@link InjectResult}: `'suppressed'` | `'cleared'` | `'stuck'`.
|
|
53
|
+
*/
|
|
54
|
+
export function clearNativePrompt(opts) {
|
|
55
|
+
const { pty, decision, isPromptShown, timeoutMs = DEFAULT_INJECT_TIMEOUT_MS, pollMs = DEFAULT_INJECT_POLL_MS, schedule = defaultSchedule, onWarn, } = opts;
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
// (1) Already suppressed → nothing to clear; never type into a non-existent prompt.
|
|
58
|
+
if (!isPromptShown()) {
|
|
59
|
+
resolve({ status: "suppressed" });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// (2) Type the keystroke for the decision. We NEVER spoof Yes for a denied tool: deny types No.
|
|
63
|
+
const keystroke = keystrokeFor(decision);
|
|
64
|
+
pty.write(keystroke);
|
|
65
|
+
// (3) Poll for the prompt to clear, bounded by timeoutMs. On timeout → stuck warning, HOLD.
|
|
66
|
+
const deadline = timeoutMs;
|
|
67
|
+
let elapsed = 0;
|
|
68
|
+
const poll = () => {
|
|
69
|
+
if (!isPromptShown()) {
|
|
70
|
+
resolve({ status: "cleared", keystroke });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
elapsed += pollMs;
|
|
74
|
+
if (elapsed >= deadline) {
|
|
75
|
+
onWarn?.(`[gate §9] STUCK PROMPT: injected "${JSON.stringify(keystroke)}" but the native TUI ` +
|
|
76
|
+
`permission prompt did not clear within ${timeoutMs}ms (#52822). NOT approving silently — ` +
|
|
77
|
+
`holding for manual resolution.`);
|
|
78
|
+
resolve({ status: "stuck", keystroke });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
schedule(poll, pollMs);
|
|
82
|
+
};
|
|
83
|
+
schedule(poll, pollMs);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** The §9 hook `permissionDecision` values (the allow path is best-effort — see allow-inject.ts). */
|
|
2
|
+
export type PermissionDecision = "allow" | "deny";
|
|
3
|
+
/** Process exit code that a PreToolUse hook uses to intercept the tool (the exit-2 form, §9). */
|
|
4
|
+
export declare const HOOK_DENY_EXIT_CODE = 2;
|
|
5
|
+
/** The §9 PreToolUse hook-specific output block carried in a decision-body response. */
|
|
6
|
+
export interface HookSpecificOutput {
|
|
7
|
+
hookEventName: "PreToolUse";
|
|
8
|
+
permissionDecision: PermissionDecision;
|
|
9
|
+
/** Human-readable reason surfaced to the TUI/log; never silently empty on a deny. */
|
|
10
|
+
permissionDecisionReason: string;
|
|
11
|
+
}
|
|
12
|
+
/** The JSON body a PreToolUse http hook returns to claude (the decision-body form). */
|
|
13
|
+
export interface HookResponse {
|
|
14
|
+
hookSpecificOutput: HookSpecificOutput;
|
|
15
|
+
}
|
|
16
|
+
/** Minimal view of the tool call a deny decision is built for (the hook-payload subset). */
|
|
17
|
+
export interface DenyToolCall {
|
|
18
|
+
/** The tool name from the hook payload / JSONL `tool_use.name` (e.g. `Bash`, `Edit`). */
|
|
19
|
+
toolName: string;
|
|
20
|
+
/** The correlation key — hook `tool_use_id` == JSONL `tool_use.id`. */
|
|
21
|
+
toolUseId: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Default deny reason when the caller supplies none. Names the tool so the TUI/log is never a blank
|
|
25
|
+
* "denied" — a silent deny is as confusing as a silent approve.
|
|
26
|
+
*/
|
|
27
|
+
export declare function defaultDenyReason(toolCall: DenyToolCall): string;
|
|
28
|
+
/**
|
|
29
|
+
* Translate a `deny` outcome into the §9 hook decision body that INTERCEPTS the tool before it runs
|
|
30
|
+
* (R2.3). The returned object is the JSON the loopback hook server writes back to claude.
|
|
31
|
+
*
|
|
32
|
+
* @param toolCall the tool the decision is for (names it in the default reason).
|
|
33
|
+
* @param reason optional explicit reason; defaults to {@link defaultDenyReason} (never blank).
|
|
34
|
+
* @returns `{ hookSpecificOutput: { hookEventName:'PreToolUse', permissionDecision:'deny', … } }`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function denyDecision(toolCall: DenyToolCall, reason?: string): HookResponse;
|
|
37
|
+
/**
|
|
38
|
+
* Translate an `allow` outcome into the §9 hook decision body. NOTE: per #52822 an allow body does
|
|
39
|
+
* NOT reliably suppress the native TUI prompt — the allow path also drives the keystroke-injection
|
|
40
|
+
* mitigation (allow-inject.ts). This helper only produces the body half.
|
|
41
|
+
*
|
|
42
|
+
* @param toolCall the tool the decision is for.
|
|
43
|
+
* @param reason optional explicit reason; defaults to a tool-naming allow reason.
|
|
44
|
+
* @returns `{ hookSpecificOutput: { hookEventName:'PreToolUse', permissionDecision:'allow', … } }`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function allowDecision(toolCall: DenyToolCall, reason?: string): HookResponse;
|
|
47
|
+
/**
|
|
48
|
+
* Matcher-scoped deny predicate (R2.3 NUANCE): does this deny matcher target the given tool?
|
|
49
|
+
*
|
|
50
|
+
* `"*"` matches every tool (the broad shape the Degrau-0 probe fired, which masked per-tool reliability
|
|
51
|
+
* by denying a precursor tool). A specific matcher (e.g. `"Edit"`, `"Bash"`) matches ONLY that tool, so
|
|
52
|
+
* #37210 (Edit) / #33106 (MCP) can be isolated and characterized at wire time. Matching is exact and
|
|
53
|
+
* case-sensitive on the tool name — the same convention the §9 settings matcher uses.
|
|
54
|
+
*
|
|
55
|
+
* @param matcher the deny matcher (`"*"` or an exact tool name).
|
|
56
|
+
* @param toolName the tool from the hook payload.
|
|
57
|
+
* @returns true iff the matcher scopes the deny to this tool.
|
|
58
|
+
*/
|
|
59
|
+
export declare function denyMatchesTool(matcher: string, toolName: string): boolean;
|
|
60
|
+
//# sourceMappingURL=deny.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deny.d.ts","sourceRoot":"","sources":["../../src/permissions/deny.ts"],"names":[],"mappings":"AAsBA,qGAAqG;AACrG,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,wFAAwF;AACxF,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,YAAY,CAAC;IAC5B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,qFAAqF;IACrF,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,kBAAkB,EAAE,kBAAkB,CAAC;CACxC;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAKhE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAQlF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CASnF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1E"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Story 033 / Task 2.3 — deny enforcement: map a `deny` decision to a hook response that intercepts
|
|
2
|
+
// BEFORE the tool runs (R2.3), and a matcher-scoped deny so per-tool reliability can be characterized.
|
|
3
|
+
//
|
|
4
|
+
// BINDING Degrau-0 finding (experiments/GATE_FINDINGS.md / IMPLEMENTACAO-FORK-ACP.md §9): a
|
|
5
|
+
// `PreToolUse` `permissionDecision:'deny'` body (or process exit code 2) INTERCEPTS the tool before it
|
|
6
|
+
// executes — `intercepted=true` across Bash/Edit/MCP. DENY is the load-bearing capability of the
|
|
7
|
+
// hybrid gate; ALLOW is best-effort (story 033 allow-inject). This module owns ONLY the deny→response
|
|
8
|
+
// translation and the matcher scope; the loopback server is hook-server.ts and the ACP correlation is
|
|
9
|
+
// request-permission.ts.
|
|
10
|
+
//
|
|
11
|
+
// Two response forms, both honored by claude (§9):
|
|
12
|
+
// - DECISION BODY: `{ hookSpecificOutput: { hookEventName:'PreToolUse', permissionDecision:'deny',
|
|
13
|
+
// permissionDecisionReason } }` returned as the http hook's JSON response (preferred — carries a
|
|
14
|
+
// reason the TUI/log can show);
|
|
15
|
+
// - EXIT CODE 2: a process-exit form for a command/exec hook. Captured here as a constant + helper so
|
|
16
|
+
// a caller that drives an exec-style hook can fail closed with the right code.
|
|
17
|
+
//
|
|
18
|
+
// NUANCE (#37210 Edit / #33106 MCP — review #18453): the broad `"*"` matcher denied the PRECURSOR tool
|
|
19
|
+
// claude attempted first (Read before Edit; ToolSearch before the MCP), so per-tool deny reliability
|
|
20
|
+
// was NOT isolated in Degrau 0. A MATCHER-SCOPED deny ({@link denyMatchesTool}) targets the intended
|
|
21
|
+
// tool so its reliability can be characterized at wire time (story 034) instead of re-masking it.
|
|
22
|
+
/** Process exit code that a PreToolUse hook uses to intercept the tool (the exit-2 form, §9). */
|
|
23
|
+
export const HOOK_DENY_EXIT_CODE = 2;
|
|
24
|
+
/**
|
|
25
|
+
* Default deny reason when the caller supplies none. Names the tool so the TUI/log is never a blank
|
|
26
|
+
* "denied" — a silent deny is as confusing as a silent approve.
|
|
27
|
+
*/
|
|
28
|
+
export function defaultDenyReason(toolCall) {
|
|
29
|
+
return (`Denied by the Zed permission gate (tool "${toolCall.toolName}", tool_use ${toolCall.toolUseId}). ` +
|
|
30
|
+
`The tool was intercepted before it ran.`);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Translate a `deny` outcome into the §9 hook decision body that INTERCEPTS the tool before it runs
|
|
34
|
+
* (R2.3). The returned object is the JSON the loopback hook server writes back to claude.
|
|
35
|
+
*
|
|
36
|
+
* @param toolCall the tool the decision is for (names it in the default reason).
|
|
37
|
+
* @param reason optional explicit reason; defaults to {@link defaultDenyReason} (never blank).
|
|
38
|
+
* @returns `{ hookSpecificOutput: { hookEventName:'PreToolUse', permissionDecision:'deny', … } }`.
|
|
39
|
+
*/
|
|
40
|
+
export function denyDecision(toolCall, reason) {
|
|
41
|
+
return {
|
|
42
|
+
hookSpecificOutput: {
|
|
43
|
+
hookEventName: "PreToolUse",
|
|
44
|
+
permissionDecision: "deny",
|
|
45
|
+
permissionDecisionReason: reason ?? defaultDenyReason(toolCall),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Translate an `allow` outcome into the §9 hook decision body. NOTE: per #52822 an allow body does
|
|
51
|
+
* NOT reliably suppress the native TUI prompt — the allow path also drives the keystroke-injection
|
|
52
|
+
* mitigation (allow-inject.ts). This helper only produces the body half.
|
|
53
|
+
*
|
|
54
|
+
* @param toolCall the tool the decision is for.
|
|
55
|
+
* @param reason optional explicit reason; defaults to a tool-naming allow reason.
|
|
56
|
+
* @returns `{ hookSpecificOutput: { hookEventName:'PreToolUse', permissionDecision:'allow', … } }`.
|
|
57
|
+
*/
|
|
58
|
+
export function allowDecision(toolCall, reason) {
|
|
59
|
+
return {
|
|
60
|
+
hookSpecificOutput: {
|
|
61
|
+
hookEventName: "PreToolUse",
|
|
62
|
+
permissionDecision: "allow",
|
|
63
|
+
permissionDecisionReason: reason ?? `Allowed by the Zed permission gate (tool "${toolCall.toolName}").`,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Matcher-scoped deny predicate (R2.3 NUANCE): does this deny matcher target the given tool?
|
|
69
|
+
*
|
|
70
|
+
* `"*"` matches every tool (the broad shape the Degrau-0 probe fired, which masked per-tool reliability
|
|
71
|
+
* by denying a precursor tool). A specific matcher (e.g. `"Edit"`, `"Bash"`) matches ONLY that tool, so
|
|
72
|
+
* #37210 (Edit) / #33106 (MCP) can be isolated and characterized at wire time. Matching is exact and
|
|
73
|
+
* case-sensitive on the tool name — the same convention the §9 settings matcher uses.
|
|
74
|
+
*
|
|
75
|
+
* @param matcher the deny matcher (`"*"` or an exact tool name).
|
|
76
|
+
* @param toolName the tool from the hook payload.
|
|
77
|
+
* @returns true iff the matcher scopes the deny to this tool.
|
|
78
|
+
*/
|
|
79
|
+
export function denyMatchesTool(matcher, toolName) {
|
|
80
|
+
return matcher === "*" || matcher === toolName;
|
|
81
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ToolUseCorrelator, type PermissionClient } from "./request-permission.js";
|
|
2
|
+
import { type PtyWriter, type Schedule } from "./allow-inject.js";
|
|
3
|
+
/**
|
|
4
|
+
* Substrings that evidence the native TUI permission prompt (the bordered "Do you want to
|
|
5
|
+
* proceed?" box with numbered options), matched case-sensitively against the ANSI-stripped recent
|
|
6
|
+
* PTY output. COPIED VERBATIM from the Degrau-0 billed probe (`experiments/e-gate.ts`
|
|
7
|
+
* `NATIVE_PERMISSION_PROMPT_MARKERS`, claude 2.1.161) — the only empirical characterization of the
|
|
8
|
+
* prompt's rendering we have. ANY hit ⇒ the native prompt is showing (#52822 reproduced).
|
|
9
|
+
*/
|
|
10
|
+
export declare const NATIVE_PERMISSION_PROMPT_MARKERS: readonly string[];
|
|
11
|
+
/** True iff any native-prompt marker appears in `text` (after ANSI stripping). */
|
|
12
|
+
export declare function textShowsNativePrompt(text: string): boolean;
|
|
13
|
+
/** Default bounded wait for the JSONL `tool_use` correlation to land after a hook fires (ms).
|
|
14
|
+
* The hook fires AFTER claude appended the assistant `tool_use` line, but the fs-watch → pump
|
|
15
|
+
* re-read is asynchronous — this window absorbs that lag. On expiry the decider proceeds and
|
|
16
|
+
* request-permission fails closed (deny) on the still-missing correlation. */
|
|
17
|
+
export declare const DEFAULT_CORRELATION_WAIT_MS = 5000;
|
|
18
|
+
/** Default poll interval for the correlation wait (ms). */
|
|
19
|
+
export declare const DEFAULT_CORRELATION_POLL_MS = 50;
|
|
20
|
+
/** Default window for the native prompt to APPEAR after an allow decision (#52822 sweep, ms).
|
|
21
|
+
* If no marker renders within it, allow-suppression held (the 2.1.161 case) — nothing to clear. */
|
|
22
|
+
export declare const DEFAULT_PROMPT_APPEAR_MS = 1500;
|
|
23
|
+
/** Default poll interval for the sweep's appear/clear phases (ms). */
|
|
24
|
+
export declare const DEFAULT_PROMPT_POLL_MS = 100;
|
|
25
|
+
/** Default budget for the keystroke to clear the prompt before the stuck warning (ms). */
|
|
26
|
+
export declare const DEFAULT_INJECT_TIMEOUT_MS = 2000;
|
|
27
|
+
/** Default bounded wait for the hook server to close on teardown (ms) — teardown never hangs on a
|
|
28
|
+
* socket held open by an in-flight decider; on expiry it warns and proceeds (the process-level
|
|
29
|
+
* close still completes in the background). */
|
|
30
|
+
export declare const DEFAULT_CLOSE_TIMEOUT_MS = 2000;
|
|
31
|
+
/** Filename prefix of the per-session scratch settings file (diagnosable in `ls /tmp`). */
|
|
32
|
+
export declare const SCRATCH_SETTINGS_PREFIX = "fork-acp-gate-settings-";
|
|
33
|
+
/** The minimal PTY surface the gate needs: a raw writer (allow keystroke) and, when available, an
|
|
34
|
+
* `onData` tap feeding the native-prompt probe. Structurally satisfied by node-pty's IPty; the
|
|
35
|
+
* replay-only noop PTY also satisfies it (but replay-only sessions never get a gate). */
|
|
36
|
+
export interface GatePty extends PtyWriter {
|
|
37
|
+
onData?(cb: (data: string) => void): {
|
|
38
|
+
dispose(): void;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Options for {@link setupSessionGate}. Timing knobs are injectable for offline tests. */
|
|
42
|
+
export interface SessionGateOptions {
|
|
43
|
+
/** The ACP client surface (`AgentSideConnection` satisfies it: `requestPermission(params)`). */
|
|
44
|
+
client: PermissionClient;
|
|
45
|
+
/** Diagnostics sink for every fail-closed / stuck-prompt warning (production: logger.error). */
|
|
46
|
+
onWarn?: (message: string) => void;
|
|
47
|
+
/** Injectable timer seam (same discipline as allow-inject/end-of-turn). Default: setTimeout. */
|
|
48
|
+
schedule?: Schedule;
|
|
49
|
+
/** Directory for the per-session scratch settings file. Default: `os.tmpdir()`. */
|
|
50
|
+
settingsDir?: string;
|
|
51
|
+
/** Hook timeout written into the scratch settings, in SECONDS (claude default 600). */
|
|
52
|
+
hookTimeoutSeconds?: number;
|
|
53
|
+
/** Hook-server decider budget (ms) before it fails closed; default per hook-server. */
|
|
54
|
+
deciderTimeoutMs?: number;
|
|
55
|
+
/** See {@link DEFAULT_CORRELATION_WAIT_MS}. */
|
|
56
|
+
correlationWaitMs?: number;
|
|
57
|
+
/** See {@link DEFAULT_CORRELATION_POLL_MS}. */
|
|
58
|
+
correlationPollMs?: number;
|
|
59
|
+
/** See {@link DEFAULT_PROMPT_APPEAR_MS}. */
|
|
60
|
+
promptAppearMs?: number;
|
|
61
|
+
/** See {@link DEFAULT_PROMPT_POLL_MS}. */
|
|
62
|
+
promptPollMs?: number;
|
|
63
|
+
/** See {@link DEFAULT_INJECT_TIMEOUT_MS}. */
|
|
64
|
+
injectTimeoutMs?: number;
|
|
65
|
+
/** See {@link DEFAULT_CLOSE_TIMEOUT_MS}. */
|
|
66
|
+
closeTimeoutMs?: number;
|
|
67
|
+
/** Injectable port allocator (default: the story-032 `findFreePort`). */
|
|
68
|
+
findPort?: () => Promise<number>;
|
|
69
|
+
}
|
|
70
|
+
/** The per-session gate runtime handle `createSession` owns and `teardownSession` disposes. */
|
|
71
|
+
export interface SessionGate {
|
|
72
|
+
/** The verified-free loopback port the hook server bound (== the port in the scratch hook URL). */
|
|
73
|
+
port: number;
|
|
74
|
+
/** Absolute path of the per-session scratch settings file (hand to the spawn as `--settings`). */
|
|
75
|
+
settingsPath: string;
|
|
76
|
+
/** The per-session `tool_use.id` correlation map. The live pump REGISTERS every JSONL `tool_use`
|
|
77
|
+
* id here (`correlator.register(id)`) so a hook call can be matched before it is approved. */
|
|
78
|
+
correlator: ToolUseCorrelator;
|
|
79
|
+
/**
|
|
80
|
+
* Bind the AUTHORITATIVE ACP session id (known only AFTER the engine spawn on the fresh path)
|
|
81
|
+
* and an optional `nudge` invoked on every hook arrival to force an immediate pump re-read
|
|
82
|
+
* (shrinking the JSONL-correlation race). MUST be called before the first tool call can be
|
|
83
|
+
* approved — an unbound gate fails closed (deny).
|
|
84
|
+
*/
|
|
85
|
+
bindSession(sessionId: string, nudge?: () => void): void;
|
|
86
|
+
/** Bind the live PTY: stores the raw writer for the allow keystroke and (when the PTY exposes
|
|
87
|
+
* `onData`) attaches the recent-output tap feeding the native-prompt probe. */
|
|
88
|
+
bindPty(pty: GatePty): void;
|
|
89
|
+
/** Idempotent teardown: close the hook server (bounded) and restore/delete the scratch settings.
|
|
90
|
+
* Safe to call from BOTH `teardownSession` and the PTY `onExit` hook. */
|
|
91
|
+
teardown(): Promise<void>;
|
|
92
|
+
/** True once {@link teardown} has run. */
|
|
93
|
+
readonly isTorndown: boolean;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Set up the per-session HYBRID gate runtime (story 034 wiring): allocate a verified-free loopback
|
|
97
|
+
* port, start the fail-closed `PreToolUse` hook server with the REAL story-033 decider chain, and
|
|
98
|
+
* write the per-session scratch settings file the spawn consumes via `--settings "<file>"`.
|
|
99
|
+
*
|
|
100
|
+
* ORDERING CONTRACT (GATE_FINDINGS blocker c): the caller MUST `await setupSessionGate(...)` and
|
|
101
|
+
* pass {@link SessionGate.settingsPath} to the spawn BEFORE the claude PTY is spawned — claude reads
|
|
102
|
+
* settings only at startup, so a late write misses the first tool call. After the spawn the caller
|
|
103
|
+
* binds the authoritative session id ({@link SessionGate.bindSession}) and the live PTY
|
|
104
|
+
* ({@link SessionGate.bindPty}), and disposes via {@link SessionGate.teardown} on session teardown
|
|
105
|
+
* AND PTY exit (idempotent).
|
|
106
|
+
*
|
|
107
|
+
* On a setup failure (port exhaustion, bind error, settings write error) the promise REJECTS with
|
|
108
|
+
* everything already cleaned up — the caller fails the session creation LOUDLY rather than spawning
|
|
109
|
+
* an ungated claude that LOOKS gated (the blocker-b hazard). `FORK_GATE=off` is the escape hatch.
|
|
110
|
+
*/
|
|
111
|
+
export declare function setupSessionGate(opts: SessionGateOptions): Promise<SessionGate>;
|
|
112
|
+
//# sourceMappingURL=gate-wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-wiring.d.ts","sourceRoot":"","sources":["../../src/permissions/gate-wiring.ts"],"names":[],"mappings":"AAyCA,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;AAQF,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;;+EAG+E;AAC/E,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,2DAA2D;AAC3D,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C;oGACoG;AACpG,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,0FAA0F;AAC1F,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C;;gDAEgD;AAChD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAI7C,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE;;0FAE0F;AAC1F,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC;CAC1D;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,MAAM,EAAE,gBAAgB,CAAC;IACzB,gGAAgG;IAChG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,+FAA+F;AAC/F,MAAM,WAAW,WAAW;IAC1B,mGAAmG;IACnG,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,YAAY,EAAE,MAAM,CAAC;IACrB;mGAC+F;IAC/F,UAAU,EAAE,iBAAiB,CAAC;IAC9B;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACzD;oFACgF;IAChF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B;8EAC0E;IAC1E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AA2RD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAIrF"}
|