@pentoshi/clai 3.9.3 → 3.9.4

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.
Files changed (94) hide show
  1. package/dist/agent/runner.d.ts +1 -1
  2. package/dist/agent/runner.js +9 -4
  3. package/dist/agent/runner.js.map +1 -1
  4. package/dist/app/adapters/current-interactive-sessions-adapter.d.ts +4 -0
  5. package/dist/app/adapters/current-interactive-sessions-adapter.js +11 -0
  6. package/dist/app/adapters/current-interactive-sessions-adapter.js.map +1 -0
  7. package/dist/app/controllers/cancel-all-result.d.ts +8 -0
  8. package/dist/app/controllers/cancel-all-result.js +32 -0
  9. package/dist/app/controllers/cancel-all-result.js.map +1 -0
  10. package/dist/app/controllers/session-controller.d.ts +8 -0
  11. package/dist/app/controllers/session-controller.js +20 -4
  12. package/dist/app/controllers/session-controller.js.map +1 -1
  13. package/dist/app/ports/interactive-sessions-port.d.ts +21 -0
  14. package/dist/app/ports/interactive-sessions-port.js +9 -0
  15. package/dist/app/ports/interactive-sessions-port.js.map +1 -0
  16. package/dist/index.js +21 -8
  17. package/dist/index.js.map +1 -1
  18. package/dist/interactive-session/artifact-writer.d.ts +54 -0
  19. package/dist/interactive-session/artifact-writer.js +161 -0
  20. package/dist/interactive-session/artifact-writer.js.map +1 -0
  21. package/dist/interactive-session/cleanup.d.ts +36 -0
  22. package/dist/interactive-session/cleanup.js +157 -0
  23. package/dist/interactive-session/cleanup.js.map +1 -0
  24. package/dist/interactive-session/config.d.ts +118 -0
  25. package/dist/interactive-session/config.js +141 -0
  26. package/dist/interactive-session/config.js.map +1 -0
  27. package/dist/interactive-session/input-policy.d.ts +41 -0
  28. package/dist/interactive-session/input-policy.js +163 -0
  29. package/dist/interactive-session/input-policy.js.map +1 -0
  30. package/dist/interactive-session/manager.d.ts +107 -0
  31. package/dist/interactive-session/manager.js +927 -0
  32. package/dist/interactive-session/manager.js.map +1 -0
  33. package/dist/interactive-session/output-store.d.ts +81 -0
  34. package/dist/interactive-session/output-store.js +239 -0
  35. package/dist/interactive-session/output-store.js.map +1 -0
  36. package/dist/interactive-session/output-view.d.ts +20 -0
  37. package/dist/interactive-session/output-view.js +142 -0
  38. package/dist/interactive-session/output-view.js.map +1 -0
  39. package/dist/interactive-session/recovery-journal.d.ts +55 -0
  40. package/dist/interactive-session/recovery-journal.js +115 -0
  41. package/dist/interactive-session/recovery-journal.js.map +1 -0
  42. package/dist/interactive-session/registry.d.ts +59 -0
  43. package/dist/interactive-session/registry.js +170 -0
  44. package/dist/interactive-session/registry.js.map +1 -0
  45. package/dist/interactive-session/runtime.d.ts +107 -0
  46. package/dist/interactive-session/runtime.js +191 -0
  47. package/dist/interactive-session/runtime.js.map +1 -0
  48. package/dist/interactive-session/session-runtime.d.ts +50 -0
  49. package/dist/interactive-session/session-runtime.js +63 -0
  50. package/dist/interactive-session/session-runtime.js.map +1 -0
  51. package/dist/interactive-session/streaming-redactor.d.ts +53 -0
  52. package/dist/interactive-session/streaming-redactor.js +263 -0
  53. package/dist/interactive-session/streaming-redactor.js.map +1 -0
  54. package/dist/interactive-session/telemetry.d.ts +30 -0
  55. package/dist/interactive-session/telemetry.js +47 -0
  56. package/dist/interactive-session/telemetry.js.map +1 -0
  57. package/dist/interactive-session/transport-factory.d.ts +8 -0
  58. package/dist/interactive-session/transport-factory.js +16 -0
  59. package/dist/interactive-session/transport-factory.js.map +1 -0
  60. package/dist/interactive-session/transport-node-pty.d.ts +49 -0
  61. package/dist/interactive-session/transport-node-pty.js +219 -0
  62. package/dist/interactive-session/transport-node-pty.js.map +1 -0
  63. package/dist/interactive-session/transport-pipe.d.ts +9 -0
  64. package/dist/interactive-session/transport-pipe.js +215 -0
  65. package/dist/interactive-session/transport-pipe.js.map +1 -0
  66. package/dist/interactive-session/transport.d.ts +104 -0
  67. package/dist/interactive-session/transport.js +89 -0
  68. package/dist/interactive-session/transport.js.map +1 -0
  69. package/dist/interactive-session/types.d.ts +254 -0
  70. package/dist/interactive-session/types.js +191 -0
  71. package/dist/interactive-session/types.js.map +1 -0
  72. package/dist/os/process-identity.d.ts +46 -0
  73. package/dist/os/process-identity.js +147 -0
  74. package/dist/os/process-identity.js.map +1 -0
  75. package/dist/repl.js +10 -0
  76. package/dist/repl.js.map +1 -1
  77. package/dist/tools/definitions.js +95 -0
  78. package/dist/tools/definitions.js.map +1 -1
  79. package/dist/tools/interactive-session-tools.d.ts +11 -0
  80. package/dist/tools/interactive-session-tools.js +261 -0
  81. package/dist/tools/interactive-session-tools.js.map +1 -0
  82. package/dist/tools/jobs.js +2 -70
  83. package/dist/tools/jobs.js.map +1 -1
  84. package/dist/tools/registry.js +4 -0
  85. package/dist/tools/registry.js.map +1 -1
  86. package/dist/tui-v2/bootstrap/composition-root.d.ts +3 -0
  87. package/dist/tui-v2/bootstrap/composition-root.js +3 -0
  88. package/dist/tui-v2/bootstrap/composition-root.js.map +1 -1
  89. package/dist/tui-v2/bootstrap/start-tui-v2.js +10 -0
  90. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  91. package/dist/types.d.ts +5 -0
  92. package/dist/version.generated.d.ts +2 -2
  93. package/dist/version.generated.js +2 -2
  94. package/package.json +1 -1
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Mutable per-session runtime: the transport, the output store, the ordered
3
+ * input lane, timers, and the single finalization promise.
4
+ *
5
+ * Sessions share no locks, queues, cursors, deadlines, or finalization state, so
6
+ * a failure in one session cannot affect another.
7
+ */
8
+ import type { BoundedArtifactWriter } from "./artifact-writer.js";
9
+ import type { InteractiveSessionConfig } from "./config.js";
10
+ import type { OutputStore } from "./output-store.js";
11
+ import { AsyncMutex, FinalizeOnce, Notifier, OrderedInputQueue, TimerSet, type Clock } from "./runtime.js";
12
+ import type { SessionTransport } from "./transport.js";
13
+ import type { CloseResult, InteractiveSessionRecord, TerminationReason } from "./types.js";
14
+ export interface SessionRuntimeInit {
15
+ readonly record: InteractiveSessionRecord;
16
+ readonly transport: SessionTransport;
17
+ readonly output: OutputStore;
18
+ readonly artifact: BoundedArtifactWriter;
19
+ readonly config: InteractiveSessionConfig;
20
+ readonly clock: Clock;
21
+ readonly idleTimeoutMs: number | undefined;
22
+ readonly lifetimeTimeoutMs: number | undefined;
23
+ readonly onTimeout: (reason: "idle-timeout" | "lifetime-timeout") => void;
24
+ }
25
+ export declare class SessionRuntime {
26
+ readonly record: InteractiveSessionRecord;
27
+ readonly transport: SessionTransport;
28
+ readonly output: OutputStore;
29
+ readonly artifact: BoundedArtifactWriter;
30
+ readonly config: InteractiveSessionConfig;
31
+ readonly clock: Clock;
32
+ readonly input: OrderedInputQueue;
33
+ readonly mutation: AsyncMutex;
34
+ readonly finalize: FinalizeOnce<CloseResult>;
35
+ readonly timers: TimerSet;
36
+ /** Bumped once when the child exits, so waiters can settle immediately. */
37
+ readonly exitSignal: Notifier;
38
+ /** Set once a terminal transition is chosen so late observations only enrich. */
39
+ processExited: boolean;
40
+ exitObserved: TerminationReason | undefined;
41
+ disposed: boolean;
42
+ private readonly unsubscribes;
43
+ private readonly idleTimeoutMs;
44
+ constructor(init: SessionRuntimeInit);
45
+ track(unsubscribe: () => void): void;
46
+ /** Accepted input and observed output both count as activity. */
47
+ touch(): void;
48
+ syncCursors(): void;
49
+ releaseListeners(): void;
50
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Mutable per-session runtime: the transport, the output store, the ordered
3
+ * input lane, timers, and the single finalization promise.
4
+ *
5
+ * Sessions share no locks, queues, cursors, deadlines, or finalization state, so
6
+ * a failure in one session cannot affect another.
7
+ */
8
+ import { AsyncMutex, FinalizeOnce, Notifier, OrderedInputQueue, TimerSet, } from "./runtime.js";
9
+ export class SessionRuntime {
10
+ record;
11
+ transport;
12
+ output;
13
+ artifact;
14
+ config;
15
+ clock;
16
+ input = new OrderedInputQueue();
17
+ mutation = new AsyncMutex();
18
+ finalize = new FinalizeOnce();
19
+ timers;
20
+ /** Bumped once when the child exits, so waiters can settle immediately. */
21
+ exitSignal = new Notifier();
22
+ /** Set once a terminal transition is chosen so late observations only enrich. */
23
+ processExited = false;
24
+ exitObserved;
25
+ disposed = false;
26
+ unsubscribes = [];
27
+ idleTimeoutMs;
28
+ constructor(init) {
29
+ this.record = init.record;
30
+ this.transport = init.transport;
31
+ this.output = init.output;
32
+ this.artifact = init.artifact;
33
+ this.config = init.config;
34
+ this.clock = init.clock;
35
+ this.idleTimeoutMs = init.idleTimeoutMs;
36
+ this.timers = new TimerSet(init.clock, init.onTimeout);
37
+ this.timers.armIdle(init.idleTimeoutMs);
38
+ this.timers.armLifetime(init.lifetimeTimeoutMs);
39
+ }
40
+ track(unsubscribe) {
41
+ this.unsubscribes.push(unsubscribe);
42
+ }
43
+ /** Accepted input and observed output both count as activity. */
44
+ touch() {
45
+ this.record.lastActivityAt = Date.now();
46
+ this.timers.armIdle(this.idleTimeoutMs);
47
+ }
48
+ syncCursors() {
49
+ this.record.earliestCursor = this.output.earliestCursor;
50
+ this.record.latestCursor = this.output.latestCursor;
51
+ }
52
+ releaseListeners() {
53
+ for (const unsubscribe of this.unsubscribes.splice(0)) {
54
+ try {
55
+ unsubscribe();
56
+ }
57
+ catch {
58
+ // Listener teardown is best effort; cleanup must still complete.
59
+ }
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=session-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-runtime.js","sourceRoot":"","sources":["../../src/interactive-session/session-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EACL,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,QAAQ,GAET,MAAM,cAAc,CAAC;AAoBtB,MAAM,OAAO,cAAc;IAChB,MAAM,CAA2B;IACjC,SAAS,CAAmB;IAC5B,MAAM,CAAc;IACpB,QAAQ,CAAwB;IAChC,MAAM,CAA2B;IACjC,KAAK,CAAQ;IACb,KAAK,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAChC,QAAQ,GAAG,IAAI,UAAU,EAAE,CAAC;IAC5B,QAAQ,GAAG,IAAI,YAAY,EAAe,CAAC;IAC3C,MAAM,CAAW;IAC1B,2EAA2E;IAClE,UAAU,GAAG,IAAI,QAAQ,EAAE,CAAC;IAErC,iFAAiF;IACjF,aAAa,GAAG,KAAK,CAAC;IACtB,YAAY,CAAgC;IAC5C,QAAQ,GAAG,KAAK,CAAC;IAEA,YAAY,GAAsB,EAAE,CAAC;IACrC,aAAa,CAAqB;IAEnD,YAAY,IAAwB;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,WAAuB;QAC3B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,iEAAiE;IACjE,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAED,WAAW;QACT,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;IACtD,CAAC;IAED,gBAAgB;QACd,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC;gBACH,WAAW,EAAE,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;YACnE,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Bounded streaming redaction over raw child output.
3
+ *
4
+ * Two lanes run before any byte receives a cursor, so raw sensitive data never
5
+ * reaches memory retention, artifacts, telemetry, or presentation:
6
+ *
7
+ * 1. A byte matcher removes the exact UTF-8 encodings of registered sensitive
8
+ * values across arbitrary chunk splits, including next to invalid UTF-8.
9
+ * 2. A decoder applies the existing textual secret patterns to the valid UTF-8
10
+ * runs of the emitted region.
11
+ *
12
+ * Retention is bounded: the only bytes held back are an incomplete trailing
13
+ * UTF-8 code point and a tail that is still a viable prefix of a registered
14
+ * secret. Prompts without a trailing newline therefore emit immediately.
15
+ */
16
+ import { type SessionOperation } from "./types.js";
17
+ export declare const REDACTION_MARKER = "[redacted]";
18
+ /** Bytes of an incomplete trailing multi-byte UTF-8 sequence, else 0. */
19
+ export declare function trailingIncompleteUtf8Bytes(bytes: Uint8Array): number;
20
+ export interface Utf8Run {
21
+ readonly valid: boolean;
22
+ readonly bytes: Uint8Array;
23
+ }
24
+ /** Split a byte range into maximal valid-UTF-8 runs and invalid byte runs. */
25
+ export declare function splitUtf8Runs(bytes: Uint8Array): Utf8Run[];
26
+ export declare class StreamingSecretRedactor {
27
+ private readonly overlapBytes;
28
+ private pending;
29
+ private readonly secrets;
30
+ private redactedAny;
31
+ private closed;
32
+ constructor(overlapBytes: number);
33
+ get redacted(): boolean;
34
+ /**
35
+ * Register an exact sensitive value. Values longer than the configured overlap
36
+ * bound are rejected before delivery because they could not be matched across
37
+ * chunk splits without unbounded retention.
38
+ */
39
+ registerExactSecret(value: string, operation?: SessionOperation): void;
40
+ /** Longest tail of `bytes` that is a proper prefix of any registered secret. */
41
+ private viablePrefixTail;
42
+ /**
43
+ * Tail that is either a partial secret-pattern prefix or an in-progress token
44
+ * that a pattern could still consume.
45
+ */
46
+ private viablePatternTail;
47
+ /** Feed raw bytes; returns the safe bytes now eligible for cursor assignment. */
48
+ push(raw: Uint8Array): Uint8Array;
49
+ /** Flush retained overlap through both lanes. Idempotent. */
50
+ close(): Uint8Array;
51
+ private transform;
52
+ private applyByteLane;
53
+ }
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Bounded streaming redaction over raw child output.
3
+ *
4
+ * Two lanes run before any byte receives a cursor, so raw sensitive data never
5
+ * reaches memory retention, artifacts, telemetry, or presentation:
6
+ *
7
+ * 1. A byte matcher removes the exact UTF-8 encodings of registered sensitive
8
+ * values across arbitrary chunk splits, including next to invalid UTF-8.
9
+ * 2. A decoder applies the existing textual secret patterns to the valid UTF-8
10
+ * runs of the emitted region.
11
+ *
12
+ * Retention is bounded: the only bytes held back are an incomplete trailing
13
+ * UTF-8 code point and a tail that is still a viable prefix of a registered
14
+ * secret. Prompts without a trailing newline therefore emit immediately.
15
+ */
16
+ import { redactSecrets } from "../llm/provider.js";
17
+ import { throwSessionError } from "./types.js";
18
+ export const REDACTION_MARKER = "[redacted]";
19
+ const MARKER_BYTES = new Uint8Array(Buffer.from(REDACTION_MARKER, "utf8"));
20
+ /** Bytes of an incomplete trailing multi-byte UTF-8 sequence, else 0. */
21
+ export function trailingIncompleteUtf8Bytes(bytes) {
22
+ const len = bytes.length;
23
+ for (let back = 1; back <= 3 && back <= len; back += 1) {
24
+ const byte = bytes[len - back];
25
+ if ((byte & 0xc0) === 0x80)
26
+ continue;
27
+ let expected = 1;
28
+ if ((byte & 0xe0) === 0xc0)
29
+ expected = 2;
30
+ else if ((byte & 0xf0) === 0xe0)
31
+ expected = 3;
32
+ else if ((byte & 0xf8) === 0xf0)
33
+ expected = 4;
34
+ return expected > back ? back : 0;
35
+ }
36
+ return 0;
37
+ }
38
+ /** Split a byte range into maximal valid-UTF-8 runs and invalid byte runs. */
39
+ export function splitUtf8Runs(bytes) {
40
+ const runs = [];
41
+ let index = 0;
42
+ let validStart = 0;
43
+ const pushRun = (valid, start, end) => {
44
+ if (end > start)
45
+ runs.push({ valid, bytes: bytes.subarray(start, end) });
46
+ };
47
+ while (index < bytes.length) {
48
+ const width = utf8SequenceWidth(bytes, index);
49
+ if (width > 0) {
50
+ index += width;
51
+ continue;
52
+ }
53
+ pushRun(true, validStart, index);
54
+ const invalidStart = index;
55
+ while (index < bytes.length && utf8SequenceWidth(bytes, index) === 0)
56
+ index += 1;
57
+ pushRun(false, invalidStart, index);
58
+ validStart = index;
59
+ }
60
+ pushRun(true, validStart, index);
61
+ return runs;
62
+ }
63
+ function utf8SequenceWidth(bytes, index) {
64
+ const byte = bytes[index];
65
+ if (byte < 0x80)
66
+ return 1;
67
+ let width = 0;
68
+ if ((byte & 0xe0) === 0xc0)
69
+ width = 2;
70
+ else if ((byte & 0xf0) === 0xe0)
71
+ width = 3;
72
+ else if ((byte & 0xf8) === 0xf0)
73
+ width = 4;
74
+ else
75
+ return 0;
76
+ if (index + width > bytes.length)
77
+ return 0;
78
+ for (let offset = 1; offset < width; offset += 1) {
79
+ if ((bytes[index + offset] & 0xc0) !== 0x80)
80
+ return 0;
81
+ }
82
+ // Reject overlong encodings, surrogates, and out-of-range code points so a
83
+ // "valid" run always round-trips through UTF-8 without substitution.
84
+ const second = bytes[index + 1];
85
+ if (width === 2 && byte < 0xc2)
86
+ return 0;
87
+ if (width === 3 && byte === 0xe0 && second < 0xa0)
88
+ return 0;
89
+ if (width === 3 && byte === 0xed && second >= 0xa0)
90
+ return 0;
91
+ if (width === 4 && (byte > 0xf4 || (byte === 0xf0 && second < 0x90)))
92
+ return 0;
93
+ if (width === 4 && byte === 0xf4 && second > 0x8f)
94
+ return 0;
95
+ return width;
96
+ }
97
+ function indexOfSequence(haystack, needle, from) {
98
+ return Buffer.from(haystack.buffer, haystack.byteOffset, haystack.byteLength).indexOf(Buffer.from(needle), from);
99
+ }
100
+ /**
101
+ * Literal prefixes of the textual secret patterns applied by `redactSecrets`.
102
+ * They bound how much tail must be retained so a token split across chunks is
103
+ * still matched, without holding back ordinary prompt text.
104
+ */
105
+ const TEXT_SECRET_PREFIXES = ["gsk_", "AIza", "AQ.", "sk-", "nvapi-"];
106
+ const TOKEN_BODY_RE = /^[A-Za-z0-9._-]*$/;
107
+ export class StreamingSecretRedactor {
108
+ overlapBytes;
109
+ pending = new Uint8Array(0);
110
+ secrets = [];
111
+ redactedAny = false;
112
+ closed = false;
113
+ constructor(overlapBytes) {
114
+ this.overlapBytes = overlapBytes;
115
+ }
116
+ get redacted() {
117
+ return this.redactedAny;
118
+ }
119
+ /**
120
+ * Register an exact sensitive value. Values longer than the configured overlap
121
+ * bound are rejected before delivery because they could not be matched across
122
+ * chunk splits without unbounded retention.
123
+ */
124
+ registerExactSecret(value, operation = "send") {
125
+ if (value.length === 0)
126
+ return;
127
+ const bytes = new Uint8Array(Buffer.from(value, "utf8"));
128
+ if (bytes.length > this.overlapBytes) {
129
+ throwSessionError({
130
+ code: "INVALID_CONFIGURATION",
131
+ operation,
132
+ message: "A sensitive value exceeds the configured redaction match span and cannot be redacted safely.",
133
+ details: { field: "redactionOverlapBytes", limitBytes: this.overlapBytes },
134
+ });
135
+ }
136
+ if (this.secrets.some((existing) => Buffer.from(existing).equals(bytes)))
137
+ return;
138
+ this.secrets.push(bytes);
139
+ }
140
+ /** Longest tail of `bytes` that is a proper prefix of any registered secret. */
141
+ viablePrefixTail(bytes) {
142
+ let longest = 0;
143
+ for (const secret of this.secrets) {
144
+ const max = Math.min(secret.length - 1, bytes.length);
145
+ for (let length = max; length > longest; length -= 1) {
146
+ const tail = bytes.subarray(bytes.length - length);
147
+ if (Buffer.from(tail).equals(Buffer.from(secret.subarray(0, length)))) {
148
+ longest = length;
149
+ break;
150
+ }
151
+ }
152
+ }
153
+ return Math.min(longest, this.overlapBytes);
154
+ }
155
+ /**
156
+ * Tail that is either a partial secret-pattern prefix or an in-progress token
157
+ * that a pattern could still consume.
158
+ */
159
+ viablePatternTail(bytes) {
160
+ const window = bytes.subarray(Math.max(0, bytes.length - this.overlapBytes));
161
+ const text = Buffer.from(window).toString("latin1");
162
+ let longest = 0;
163
+ for (const prefix of TEXT_SECRET_PREFIXES) {
164
+ const start = text.lastIndexOf(prefix);
165
+ if (start >= 0 && TOKEN_BODY_RE.test(text.slice(start + prefix.length))) {
166
+ longest = Math.max(longest, text.length - start);
167
+ }
168
+ for (let length = Math.min(prefix.length - 1, text.length); length > longest; length -= 1) {
169
+ if (text.endsWith(prefix.slice(0, length))) {
170
+ longest = length;
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ return Math.min(longest, this.overlapBytes);
176
+ }
177
+ /** Feed raw bytes; returns the safe bytes now eligible for cursor assignment. */
178
+ push(raw) {
179
+ if (this.closed)
180
+ throw new Error("Cannot push into a closed redactor");
181
+ this.pending = concat(this.pending, raw);
182
+ const keepIncomplete = trailingIncompleteUtf8Bytes(this.pending);
183
+ const keepSecret = this.viablePrefixTail(this.pending);
184
+ const keepPattern = this.viablePatternTail(this.pending);
185
+ const keep = Math.min(Math.max(keepIncomplete, keepSecret, keepPattern), Math.min(this.pending.length, this.overlapBytes));
186
+ const emitEnd = this.pending.length - keep;
187
+ if (emitEnd <= 0)
188
+ return new Uint8Array(0);
189
+ const region = this.pending.subarray(0, emitEnd);
190
+ this.pending = new Uint8Array(this.pending.subarray(emitEnd));
191
+ return this.transform(region);
192
+ }
193
+ /** Flush retained overlap through both lanes. Idempotent. */
194
+ close() {
195
+ if (this.closed)
196
+ return new Uint8Array(0);
197
+ this.closed = true;
198
+ const region = this.pending;
199
+ this.pending = new Uint8Array(0);
200
+ return region.length > 0 ? this.transform(region) : new Uint8Array(0);
201
+ }
202
+ transform(region) {
203
+ const byteLane = this.applyByteLane(region);
204
+ const parts = [];
205
+ for (const run of splitUtf8Runs(byteLane)) {
206
+ if (!run.valid) {
207
+ // Binary bytes are preserved verbatim so encoded output and artifacts
208
+ // stay faithful; the byte lane already removed known secrets.
209
+ parts.push(run.bytes);
210
+ continue;
211
+ }
212
+ const text = Buffer.from(run.bytes).toString("utf8");
213
+ const safe = redactSecrets(text);
214
+ if (safe !== text)
215
+ this.redactedAny = true;
216
+ parts.push(new Uint8Array(Buffer.from(safe, "utf8")));
217
+ }
218
+ return concatAll(parts);
219
+ }
220
+ applyByteLane(region) {
221
+ if (this.secrets.length === 0)
222
+ return region;
223
+ let current = region;
224
+ for (const secret of this.secrets) {
225
+ let cursor = 0;
226
+ const parts = [];
227
+ for (;;) {
228
+ const found = indexOfSequence(current, secret, cursor);
229
+ if (found < 0)
230
+ break;
231
+ parts.push(current.subarray(cursor, found), MARKER_BYTES);
232
+ cursor = found + secret.length;
233
+ this.redactedAny = true;
234
+ }
235
+ if (parts.length === 0)
236
+ continue;
237
+ parts.push(current.subarray(cursor));
238
+ current = concatAll(parts);
239
+ }
240
+ return current;
241
+ }
242
+ }
243
+ function concat(a, b) {
244
+ if (a.length === 0)
245
+ return new Uint8Array(b);
246
+ if (b.length === 0)
247
+ return a;
248
+ const out = new Uint8Array(a.length + b.length);
249
+ out.set(a, 0);
250
+ out.set(b, a.length);
251
+ return out;
252
+ }
253
+ function concatAll(parts) {
254
+ const total = parts.reduce((sum, part) => sum + part.length, 0);
255
+ const out = new Uint8Array(total);
256
+ let offset = 0;
257
+ for (const part of parts) {
258
+ out.set(part, offset);
259
+ offset += part.length;
260
+ }
261
+ return out;
262
+ }
263
+ //# sourceMappingURL=streaming-redactor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-redactor.js","sourceRoot":"","sources":["../../src/interactive-session/streaming-redactor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bounded, metadata-only diagnostics.
3
+ *
4
+ * Every field is an explicit scalar. Raw session ids, commands, cwd, environment
5
+ * values, input, output, native error text, confirmation previews, and artifact
6
+ * content are structurally excluded — they are never accepted as arguments.
7
+ */
8
+ import { auditLog } from "../store/logs.js";
9
+ import type { SessionOperation, SessionState, SessionTransportKind, StableErrorCode, TerminationReason } from "./types.js";
10
+ export declare function redactSessionId(sessionId: string | undefined): string | undefined;
11
+ export interface TelemetryEvent {
12
+ readonly operation: SessionOperation;
13
+ readonly sessionId?: string | undefined;
14
+ readonly durationMs: number;
15
+ readonly result: "ok" | StableErrorCode;
16
+ readonly state?: SessionState | undefined;
17
+ readonly transport?: SessionTransportKind | undefined;
18
+ readonly inputBytes?: number | undefined;
19
+ readonly outputBytes?: number | undefined;
20
+ readonly queueDepth?: number | undefined;
21
+ readonly retryCount?: number | undefined;
22
+ readonly terminationReason?: TerminationReason | undefined;
23
+ /** Recorded when Start failed after allocating a process or terminal. */
24
+ readonly cleanupVerified?: boolean | undefined;
25
+ }
26
+ export declare class SessionTelemetry {
27
+ private readonly sink;
28
+ constructor(sink?: typeof auditLog);
29
+ record(event: TelemetryEvent): void;
30
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Bounded, metadata-only diagnostics.
3
+ *
4
+ * Every field is an explicit scalar. Raw session ids, commands, cwd, environment
5
+ * values, input, output, native error text, confirmation previews, and artifact
6
+ * content are structurally excluded — they are never accepted as arguments.
7
+ */
8
+ import { createHmac, randomBytes } from "node:crypto";
9
+ import { auditLog } from "../store/logs.js";
10
+ const AUDIT_EVENT = "tool.terminal_session";
11
+ /** Per-process key so a redacted id cannot be correlated across runs. */
12
+ const idKey = randomBytes(32);
13
+ export function redactSessionId(sessionId) {
14
+ if (!sessionId)
15
+ return undefined;
16
+ return createHmac("sha256", idKey).update(sessionId).digest("hex").slice(0, 12);
17
+ }
18
+ export class SessionTelemetry {
19
+ sink;
20
+ constructor(sink = auditLog) {
21
+ this.sink = sink;
22
+ }
23
+ record(event) {
24
+ const payload = {
25
+ operation: event.operation,
26
+ ...(event.sessionId !== undefined
27
+ ? { session: redactSessionId(event.sessionId) }
28
+ : {}),
29
+ durationMs: Math.max(0, Math.round(event.durationMs)),
30
+ result: event.result,
31
+ ...(event.state !== undefined ? { state: event.state } : {}),
32
+ ...(event.transport !== undefined ? { transport: event.transport } : {}),
33
+ ...(event.inputBytes !== undefined ? { inputBytes: event.inputBytes } : {}),
34
+ ...(event.outputBytes !== undefined ? { outputBytes: event.outputBytes } : {}),
35
+ ...(event.queueDepth !== undefined ? { queueDepth: event.queueDepth } : {}),
36
+ ...(event.retryCount !== undefined ? { retryCount: event.retryCount } : {}),
37
+ ...(event.terminationReason !== undefined
38
+ ? { terminationReason: event.terminationReason }
39
+ : {}),
40
+ ...(event.cleanupVerified !== undefined
41
+ ? { cleanupVerified: event.cleanupVerified }
42
+ : {}),
43
+ };
44
+ void this.sink(AUDIT_EVENT, payload);
45
+ }
46
+ }
47
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/interactive-session/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAS5C,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAC5C,yEAAyE;AACzE,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;AAE9B,MAAM,UAAU,eAAe,CAAC,SAA6B;IAC3D,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IACjC,OAAO,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC;AAkBD,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,OAAwB,QAAQ;QAAhC,SAAI,GAAJ,IAAI,CAA4B;IAAG,CAAC;IAEjE,MAAM,CAAC,KAAqB;QAC1B,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS;gBAC/B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;gBAC/C,CAAC,CAAC,EAAE,CAAC;YACP,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACrD,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS;gBACvC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE;gBAChD,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS;gBACrC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Default transport factory. PTY support stays behind a lazy capability probe so
3
+ * pipe sessions and every legacy shell/job path remain reachable on targets
4
+ * without a verified native artifact.
5
+ */
6
+ import type { SessionTransportFactory } from "./transport.js";
7
+ export declare function createSessionTransportFactory(): SessionTransportFactory;
8
+ export declare const defaultTransportFactory: SessionTransportFactory;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Default transport factory. PTY support stays behind a lazy capability probe so
3
+ * pipe sessions and every legacy shell/job path remain reachable on targets
4
+ * without a verified native artifact.
5
+ */
6
+ import { startPipeTransport } from "./transport-pipe.js";
7
+ import { probePtyCapability, startPtyTransport } from "./transport-node-pty.js";
8
+ export function createSessionTransportFactory() {
9
+ return {
10
+ capability: (platform) => probePtyCapability(platform),
11
+ startPipe: (request) => startPipeTransport(request),
12
+ startPty: (request) => startPtyTransport(request),
13
+ };
14
+ }
15
+ export const defaultTransportFactory = createSessionTransportFactory();
16
+ //# sourceMappingURL=transport-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-factory.js","sourceRoot":"","sources":["../../src/interactive-session/transport-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGhF,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC;QACtD,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC;QACnD,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC;KAClD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,6BAA6B,EAAE,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Optional PTY transport.
3
+ *
4
+ * `node-pty` is an optional dependency loaded through a lazy dynamic import so
5
+ * an absent or unloadable native artifact degrades capability instead of failing
6
+ * application startup. Capability is per-platform and only claimed after the
7
+ * module actually loads in this packaged layout; the release pipeline must prove
8
+ * load/spawn/resize/cleanup on a matching-target runner before advertising it.
9
+ */
10
+ import { type LaunchRequest, type LaunchResult, type PtyCapability } from "./transport.js";
11
+ import type { TerminalDimensions } from "./types.js";
12
+ /** Minimal structural view of the parts of node-pty this adapter uses. */
13
+ export interface PtyProcessLike {
14
+ readonly pid: number;
15
+ onData(listener: (data: string | Buffer) => void): {
16
+ dispose(): void;
17
+ };
18
+ onExit(listener: (event: {
19
+ exitCode: number;
20
+ signal?: number | undefined;
21
+ }) => void): {
22
+ dispose(): void;
23
+ };
24
+ write(data: string): void;
25
+ resize(columns: number, rows: number): void;
26
+ pause(): void;
27
+ resume(): void;
28
+ kill(signal?: string): void;
29
+ }
30
+ export interface NodePtyModuleLike {
31
+ spawn(file: string, args: string[] | string, options: {
32
+ cwd: string;
33
+ env: Record<string, string>;
34
+ cols: number;
35
+ rows: number;
36
+ name?: string;
37
+ useConpty?: boolean;
38
+ }): PtyProcessLike;
39
+ }
40
+ export declare function probePtyCapability(platform?: NodeJS.Platform): Promise<PtyCapability>;
41
+ /** Test seam: reset the memoized load so capability can be re-evaluated. */
42
+ export declare function resetPtyCapabilityCache(): void;
43
+ export interface PtyStartOverrides {
44
+ readonly module?: NodePtyModuleLike | undefined;
45
+ readonly shell?: string | null | undefined;
46
+ }
47
+ export declare function startPtyTransport(request: LaunchRequest & {
48
+ dimensions: TerminalDimensions;
49
+ }, overrides?: PtyStartOverrides): Promise<LaunchResult>;