@heyditto/cli 2.40.0 → 2.42.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.
@@ -0,0 +1,39 @@
1
+ import { type ClaudeToolResultAnchor } from "./claude-tool-results.js";
2
+ interface ToolOperation {
3
+ origin?: object;
4
+ key: string;
5
+ session: string;
6
+ signature: string;
7
+ toolUseId: string;
8
+ anchor: Promise<ClaudeToolResultAnchor | undefined>;
9
+ }
10
+ export interface ClaudePermissionToken {
11
+ origin?: object;
12
+ session: string;
13
+ signature: string;
14
+ operation?: ToolOperation;
15
+ ambiguous: boolean;
16
+ resolved: boolean;
17
+ }
18
+ /** Correlates only this input epoch. Ambiguous/missing metadata never clears a dialog. */
19
+ export declare class ClaudePermissionTracker {
20
+ private readonly resolved;
21
+ private readonly operations;
22
+ private active?;
23
+ private timer?;
24
+ private epoch;
25
+ constructor(resolved: (token: ClaudePermissionToken) => void);
26
+ get pending(): boolean;
27
+ get toolBusy(): boolean;
28
+ reset(): void;
29
+ preTool(payload: Record<string, unknown>, origin?: object): void;
30
+ permissionRequest(payload: Record<string, unknown>): void;
31
+ question(payload: Record<string, unknown>): ClaudePermissionToken | undefined;
32
+ notification(payload: Record<string, unknown>): ClaudePermissionToken | undefined;
33
+ private commonOrigin;
34
+ toolFinished(payload: Record<string, unknown>): void;
35
+ answered(token: ClaudePermissionToken | undefined): void;
36
+ private complete;
37
+ private poll;
38
+ }
39
+ export {};
@@ -0,0 +1,149 @@
1
+ import { createHash } from "node:crypto";
2
+ import { captureClaudeToolResultAnchor, readClaudeToolResults } from "./claude-tool-results.js";
3
+ function canonical(value, depth = 0) {
4
+ if (depth > 32)
5
+ throw new Error("tool metadata too deep");
6
+ if (Array.isArray(value))
7
+ return value.map(item => canonical(item, depth + 1));
8
+ if (value && typeof value === "object")
9
+ return Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key], depth + 1)]));
10
+ return value;
11
+ }
12
+ function metadata(payload) {
13
+ const session = payload.session_id;
14
+ if (typeof session !== "string" || !/^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/i.test(session))
15
+ return;
16
+ if (typeof payload.agent_id === "string" && payload.agent_id && payload.agent_id !== session)
17
+ return;
18
+ if (typeof payload.tool_name !== "string" || payload.tool_name.length > 256)
19
+ return;
20
+ try {
21
+ const input = JSON.stringify([payload.tool_name, payload.tool_input]);
22
+ if (Buffer.byteLength(input) > 65536)
23
+ return;
24
+ const normalized = JSON.stringify(canonical(JSON.parse(input)));
25
+ return { session, signature: createHash("sha256").update(normalized).digest("hex") };
26
+ }
27
+ catch {
28
+ return;
29
+ }
30
+ }
31
+ /** Correlates only this input epoch. Ambiguous/missing metadata never clears a dialog. */
32
+ export class ClaudePermissionTracker {
33
+ resolved;
34
+ operations = new Map();
35
+ active;
36
+ timer;
37
+ epoch = 0;
38
+ constructor(resolved) {
39
+ this.resolved = resolved;
40
+ }
41
+ get pending() { return Boolean(this.active && !this.active.resolved); }
42
+ get toolBusy() { return this.operations.size > 0; }
43
+ reset() {
44
+ this.epoch++;
45
+ clearTimeout(this.timer);
46
+ this.timer = undefined;
47
+ this.active = undefined;
48
+ this.operations.clear();
49
+ }
50
+ preTool(payload, origin) {
51
+ const meta = metadata(payload);
52
+ const id = payload.tool_use_id;
53
+ if (!meta || typeof id !== "string" || !id || id.length > 256 || typeof payload.transcript_path !== "string")
54
+ return;
55
+ const key = `${meta.session}:${id}`;
56
+ if (this.operations.has(key))
57
+ return;
58
+ const operation = { ...meta, key, toolUseId: id, origin, anchor: captureClaudeToolResultAnchor(payload.transcript_path, meta.session) };
59
+ this.operations.set(key, operation);
60
+ while (this.operations.size > 128)
61
+ this.operations.delete(this.operations.keys().next().value);
62
+ const active = this.active;
63
+ if (active && !active.resolved && active.session === meta.session && active.signature === meta.signature) {
64
+ if (active.operation && active.operation !== operation)
65
+ active.ambiguous = true;
66
+ else if (!active.ambiguous)
67
+ active.operation = operation;
68
+ active.origin = this.commonOrigin([...this.operations.values()].filter(op => op.session === meta.session && op.signature === meta.signature));
69
+ }
70
+ }
71
+ permissionRequest(payload) {
72
+ const meta = metadata(payload);
73
+ if (!meta)
74
+ return;
75
+ const matches = [...this.operations.values()].filter(op => op.session === meta.session && op.signature === meta.signature);
76
+ if (this.active && !this.active.resolved && this.active.operation === matches[0] && matches.length === 1)
77
+ return;
78
+ const alreadyPending = this.pending;
79
+ this.active = { ...meta, origin: this.commonOrigin(matches), operation: matches.length === 1 ? matches[0] : undefined, ambiguous: alreadyPending || matches.length > 1, resolved: false };
80
+ this.poll(this.active, this.epoch);
81
+ }
82
+ question(payload) {
83
+ const meta = metadata(payload);
84
+ if (!meta || typeof payload.tool_use_id !== "string")
85
+ return;
86
+ const operation = this.operations.get(`${meta.session}:${payload.tool_use_id}`);
87
+ if (!operation)
88
+ return;
89
+ this.active = { ...meta, origin: operation.origin, operation, ambiguous: this.pending, resolved: false };
90
+ this.poll(this.active, this.epoch);
91
+ return this.active;
92
+ }
93
+ notification(payload) {
94
+ if (typeof payload.agent_id === "string" && payload.agent_id && payload.agent_id !== payload.session_id)
95
+ return;
96
+ return this.active?.session === payload.session_id ? this.active : undefined;
97
+ }
98
+ commonOrigin(operations) {
99
+ const origin = operations[0]?.origin;
100
+ return origin && operations.every(operation => operation.origin === origin) ? origin : undefined;
101
+ }
102
+ toolFinished(payload) {
103
+ const meta = metadata(payload);
104
+ const id = payload.tool_use_id;
105
+ if (!meta || typeof id !== "string")
106
+ return;
107
+ const operation = this.operations.get(`${meta.session}:${id}`);
108
+ if (!operation || operation.signature !== meta.signature)
109
+ return;
110
+ const active = this.active;
111
+ if (active && !active.ambiguous && active.operation === operation)
112
+ this.complete(active);
113
+ this.operations.delete(operation.key);
114
+ }
115
+ answered(token) {
116
+ // An explicit answer retains the old user-controlled answer behavior.
117
+ if (token && token === this.active) {
118
+ token.ambiguous = false;
119
+ this.complete(token);
120
+ }
121
+ }
122
+ complete(token) {
123
+ if (token !== this.active || token.resolved || token.ambiguous)
124
+ return;
125
+ token.resolved = true;
126
+ if (token.operation)
127
+ this.operations.delete(token.operation.key);
128
+ clearTimeout(this.timer);
129
+ this.timer = undefined;
130
+ this.resolved(token);
131
+ }
132
+ poll(token, epoch) {
133
+ clearTimeout(this.timer);
134
+ this.timer = setTimeout(async () => {
135
+ if (token !== this.active || token.resolved || epoch !== this.epoch)
136
+ return;
137
+ if (!token.ambiguous && token.operation) {
138
+ const anchor = await token.operation.anchor;
139
+ const results = anchor ? await readClaudeToolResults(anchor, [token.operation.toolUseId]) : [];
140
+ if (token === this.active && epoch === this.epoch && !token.ambiguous && results.some(result => result.toolUseId === token.operation?.toolUseId))
141
+ this.complete(token);
142
+ }
143
+ if (token === this.active && !token.resolved && epoch === this.epoch)
144
+ this.poll(token, epoch);
145
+ }, 500);
146
+ this.timer.unref();
147
+ }
148
+ }
149
+ //# sourceMappingURL=claude-permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-permissions.js","sourceRoot":"","sources":["../../src/remote/claude-permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface ClaudeToolResultAnchor {
2
+ file: string;
3
+ projectsRoot: string;
4
+ nativeSessionId: string;
5
+ device: number;
6
+ inode: number;
7
+ offset: number;
8
+ prefixHash: string;
9
+ prefixBytes: number;
10
+ lineBoundary: boolean;
11
+ }
12
+ /** Capture before permission execution; old results before this offset cannot resolve it. */
13
+ export declare function captureClaudeToolResultAnchor(file: string, nativeSessionId: string, configDir?: string): Promise<ClaudeToolResultAnchor | undefined>;
14
+ /** Bounded metadata only. No directory discovery or raw tool content is returned. */
15
+ export declare function readClaudeToolResults(anchor: ClaudeToolResultAnchor, expectedIds: readonly string[]): Promise<Array<{
16
+ toolUseId: string;
17
+ isError: boolean;
18
+ }>>;
@@ -0,0 +1,116 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { lstat, open, realpath } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ const UUID = /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/i;
7
+ const MAX_READ = 256 * 1024;
8
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
9
+ /** Only a main-session UUID file immediately below the owned projects root. */
10
+ async function openTranscript(file, nativeSessionId, projectsRoot) {
11
+ if (!path.isAbsolute(file) || !UUID.test(nativeSessionId) || path.basename(file) !== `${nativeSessionId}.jsonl`)
12
+ return;
13
+ const parent = path.dirname(path.resolve(file));
14
+ const entry = await lstat(parent);
15
+ if (!entry.isDirectory() || entry.isSymbolicLink())
16
+ return;
17
+ const canonicalParent = await realpath(parent);
18
+ if (path.dirname(canonicalParent) !== projectsRoot)
19
+ return;
20
+ const before = await lstat(file);
21
+ if (!before.isFile() || before.isSymbolicLink())
22
+ return;
23
+ const handle = await open(file, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
24
+ try {
25
+ const info = await handle.stat();
26
+ const after = await lstat(file);
27
+ if (!info.isFile() || info.dev !== before.dev || info.ino !== before.ino || after.isSymbolicLink() || after.dev !== info.dev || after.ino !== info.ino || await realpath(parent) !== canonicalParent) {
28
+ await handle.close();
29
+ return;
30
+ }
31
+ return { handle, info };
32
+ }
33
+ catch (error) {
34
+ await handle.close();
35
+ throw error;
36
+ }
37
+ }
38
+ /** Capture before permission execution; old results before this offset cannot resolve it. */
39
+ export async function captureClaudeToolResultAnchor(file, nativeSessionId, configDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude")) {
40
+ try {
41
+ const projectsRoot = await realpath(path.join(configDir, "projects"));
42
+ const opened = await openTranscript(file, nativeSessionId, projectsRoot);
43
+ if (!opened)
44
+ return;
45
+ const { handle, info } = opened;
46
+ try {
47
+ const prefixBytes = Math.min(info.size, 64);
48
+ const prefix = Buffer.alloc(prefixBytes);
49
+ const read = await handle.read(prefix, 0, prefixBytes, info.size - prefixBytes);
50
+ if (read.bytesRead !== prefixBytes)
51
+ return;
52
+ return { file, projectsRoot, nativeSessionId, device: info.dev, inode: info.ino, offset: info.size, prefixBytes, prefixHash: hash(prefix), lineBoundary: info.size === 0 || prefix.at(-1) === 10 };
53
+ }
54
+ finally {
55
+ await handle.close();
56
+ }
57
+ }
58
+ catch {
59
+ return;
60
+ }
61
+ }
62
+ /** Bounded metadata only. No directory discovery or raw tool content is returned. */
63
+ export async function readClaudeToolResults(anchor, expectedIds) {
64
+ if (expectedIds.length > 16 || expectedIds.some(id => typeof id !== "string" || id.length === 0 || id.length > 256))
65
+ return [];
66
+ try {
67
+ const opened = await openTranscript(anchor.file, anchor.nativeSessionId, anchor.projectsRoot);
68
+ if (!opened)
69
+ return [];
70
+ const { handle, info } = opened;
71
+ try {
72
+ if (info.dev !== anchor.device || info.ino !== anchor.inode || info.size < anchor.offset)
73
+ return [];
74
+ const prefix = Buffer.alloc(anchor.prefixBytes);
75
+ if ((await handle.read(prefix, 0, prefix.length, anchor.offset - prefix.length)).bytesRead !== prefix.length || hash(prefix) !== anchor.prefixHash)
76
+ return [];
77
+ const start = Math.max(anchor.offset, info.size - MAX_READ);
78
+ const bytes = Buffer.alloc(Math.min(MAX_READ, info.size - start));
79
+ const { bytesRead } = await handle.read(bytes, 0, bytes.length, start);
80
+ let text = bytes.subarray(0, bytesRead).toString("utf8");
81
+ if (start > anchor.offset || !anchor.lineBoundary) {
82
+ const boundary = text.indexOf("\n");
83
+ if (boundary < 0)
84
+ return [];
85
+ text = text.slice(boundary + 1);
86
+ }
87
+ // Never accept an unfinished append; complete rows end in a newline.
88
+ text = text.slice(0, text.lastIndexOf("\n") + 1);
89
+ const ids = new Set(expectedIds);
90
+ const found = new Map();
91
+ for (const line of text.split("\n")) {
92
+ let row;
93
+ try {
94
+ row = JSON.parse(line);
95
+ }
96
+ catch {
97
+ continue;
98
+ }
99
+ if (row?.type !== "user" || row.isSidechain === true || row.sessionId !== anchor.nativeSessionId || row.message?.role !== "user" || !Array.isArray(row.message.content))
100
+ continue;
101
+ for (const block of row.message.content) {
102
+ if (block?.type === "tool_result" && typeof block.tool_use_id === "string" && ids.has(block.tool_use_id))
103
+ found.set(block.tool_use_id, block.is_error === true);
104
+ }
105
+ }
106
+ return [...found].map(([toolUseId, isError]) => ({ toolUseId, isError }));
107
+ }
108
+ finally {
109
+ await handle.close();
110
+ }
111
+ }
112
+ catch {
113
+ return [];
114
+ }
115
+ }
116
+ //# sourceMappingURL=claude-tool-results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-tool-results.js","sourceRoot":"","sources":["../../src/remote/claude-tool-results.ts"],"names":[],"mappings":"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"}
@@ -34,11 +34,23 @@ export declare class RemoteSession {
34
34
  private runHeadless?;
35
35
  private readonly queue;
36
36
  private current?;
37
+ private inputReady;
38
+ private steering?;
39
+ private readonly pendingSteers;
40
+ private readonly canceledSteers;
41
+ private nativeBusy;
42
+ private stopHooksUncorrelated;
43
+ private nativeEpoch;
44
+ private nativeIdleTimer?;
45
+ private readonly idleWaiters;
37
46
  private draining;
38
47
  private stopped;
39
48
  private catalog;
40
49
  private stopWatching?;
41
50
  private pending?;
51
+ private pendingPermission?;
52
+ private nativeInputOrigin;
53
+ private readonly claudePermissions;
42
54
  constructor(ctx: RemoteSessionContext, hooks?: HookServer);
43
55
  attachTui(pty: PtySession): void;
44
56
  attachHeadless(run: (prompt: string) => HeadlessTurn): void;
@@ -51,10 +63,19 @@ export declare class RemoteSession {
51
63
  private finish;
52
64
  private onTurn;
53
65
  private onInterrupt;
66
+ private pruneCanceledSteers;
54
67
  private onCheckpoint;
55
68
  private onHook;
56
69
  private turnEnded;
70
+ private nativeIdle;
71
+ /** After steering, unscoped Stop hooks remain ambiguous even for successors.
72
+ * Local keyboard activity has no receipt to await, so bound its FIFO hold by
73
+ * the same quiet fallback instead of waiting forever for a trusted hook.
74
+ */
75
+ private watchLocalQuietFallback;
76
+ private hasQuestion;
57
77
  private requestQuestion;
78
+ private promptGeneration;
58
79
  private requestPrompt;
59
80
  private clearPending;
60
81
  /** `prompt.answer` frame: inject the keystrokes for the pending prompt. */