xiaotime 0.2.1 → 0.4.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/__tests__/approval_menu.test.d.ts +15 -0
- package/dist/__tests__/approval_menu.test.d.ts.map +1 -0
- package/dist/__tests__/approval_menu.test.js +107 -0
- package/dist/__tests__/approval_menu.test.js.map +1 -0
- package/dist/__tests__/legacy_compat.test.d.ts +2 -0
- package/dist/__tests__/legacy_compat.test.d.ts.map +1 -0
- package/dist/__tests__/legacy_compat.test.js +36 -0
- package/dist/__tests__/legacy_compat.test.js.map +1 -0
- package/dist/__tests__/server_tool_render.test.d.ts +17 -0
- package/dist/__tests__/server_tool_render.test.d.ts.map +1 -0
- package/dist/__tests__/server_tool_render.test.js +74 -0
- package/dist/__tests__/server_tool_render.test.js.map +1 -0
- package/dist/__tests__/settings.test.d.ts +16 -0
- package/dist/__tests__/settings.test.d.ts.map +1 -0
- package/dist/__tests__/settings.test.js +289 -0
- package/dist/__tests__/settings.test.js.map +1 -0
- package/dist/__tests__/tool_result_client.test.d.ts +20 -0
- package/dist/__tests__/tool_result_client.test.d.ts.map +1 -0
- package/dist/__tests__/tool_result_client.test.js +142 -0
- package/dist/__tests__/tool_result_client.test.js.map +1 -0
- package/dist/__tests__/tools.test.d.ts +17 -0
- package/dist/__tests__/tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools.test.js +381 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/display.d.ts +19 -0
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +23 -0
- package/dist/display.js.map +1 -1
- package/dist/settings.d.ts +109 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +332 -0
- package/dist/settings.js.map +1 -0
- package/dist/tool_result_client.d.ts +72 -0
- package/dist/tool_result_client.d.ts.map +1 -0
- package/dist/tool_result_client.js +123 -0
- package/dist/tool_result_client.js.map +1 -0
- package/dist/tools.d.ts +11 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +96 -33
- package/dist/tools.js.map +1 -1
- package/dist/ui_state.d.ts +134 -0
- package/dist/ui_state.d.ts.map +1 -0
- package/dist/ui_state.js +460 -0
- package/dist/ui_state.js.map +1 -0
- package/dist/ws.d.ts +15 -0
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +180 -75
- package/dist/ws.js.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* REST POST client for tool_result delivery.
|
|
4
|
+
*
|
|
5
|
+
* SPRINT-TERMINAL-CLIENT-OWNED-DISPATCH-1 (#6565) PR3.
|
|
6
|
+
*
|
|
7
|
+
* Pre-#6565 the CLI sent tool_result back to terminal-orchestrator
|
|
8
|
+
* over the WebSocket — the server awaited each one inline with a
|
|
9
|
+
* 120s timeout. Any approval taking >2 min wedged the session
|
|
10
|
+
* (the wedge class observed live 2026-05-20 during #6509 PR1
|
|
11
|
+
* canary).
|
|
12
|
+
*
|
|
13
|
+
* Post-#6565 the CLI POSTs results to the new REST endpoint:
|
|
14
|
+
*
|
|
15
|
+
* POST <ORCHESTRATOR_URL>/terminal/sessions/{session_id}/tool_results
|
|
16
|
+
* Headers: x-api-key: <cli_token>
|
|
17
|
+
* Body: {"results": [{tool_use_id, content, is_error}, ...]}
|
|
18
|
+
*
|
|
19
|
+
* Server-side: atomic across the batch. Any unknown `tool_use_id`
|
|
20
|
+
* → 400 `unknown_tool_use_id` + no rows mutated. On success,
|
|
21
|
+
* ``mark_completed_batch.all_completed=True`` signals the WS
|
|
22
|
+
* handler (waiting on the per-session resume queue) to assemble
|
|
23
|
+
* tool_result blocks + resume the model stream.
|
|
24
|
+
*
|
|
25
|
+
* Retry policy: 3 attempts with 100ms→200ms→400ms exponential
|
|
26
|
+
* backoff for transient 5xx + network errors. 4xx errors are
|
|
27
|
+
* non-retriable (the server's rejection is durable — the
|
|
28
|
+
* tool_use_id IS unknown, retrying won't change that).
|
|
29
|
+
*
|
|
30
|
+
* Failure mode if all retries exhaust: the tool_result is lost
|
|
31
|
+
* from the server's perspective; the corresponding row stays as
|
|
32
|
+
* `status='pending'` in `terminal_pending_tool_calls` until the
|
|
33
|
+
* future expiry sweep (PR5). The user-visible symptom is a
|
|
34
|
+
* session that appears frozen (model never resumes). Tightening
|
|
35
|
+
* this is the WS-reconnect-replay work in PR4 — on the next WS
|
|
36
|
+
* connect, server re-emits pending tool_call events and the CLI
|
|
37
|
+
* can re-attempt the POST after re-rendering the menu.
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.DurableHttpError = void 0;
|
|
41
|
+
exports.postToolResults = postToolResults;
|
|
42
|
+
const config_js_1 = require("./config.js");
|
|
43
|
+
const auth_js_1 = require("./auth.js");
|
|
44
|
+
/**
|
|
45
|
+
* Thrown on durable (4xx) HTTP rejections that retrying won't fix.
|
|
46
|
+
* #6573 CR-r1: replaces the pre-r1 string-prefix matching on the
|
|
47
|
+
* Error message (`startsWith("POST tool_results rejected")`) which
|
|
48
|
+
* was fragile to message-format drift. The retry loop checks
|
|
49
|
+
* `instanceof DurableHttpError` and re-throws without retry; all
|
|
50
|
+
* other thrown errors are treated as transient + retried.
|
|
51
|
+
*/
|
|
52
|
+
class DurableHttpError extends Error {
|
|
53
|
+
status;
|
|
54
|
+
body;
|
|
55
|
+
constructor(status, body) {
|
|
56
|
+
super(`POST tool_results rejected (${status}): ${body}`);
|
|
57
|
+
this.name = "DurableHttpError";
|
|
58
|
+
this.status = status;
|
|
59
|
+
this.body = body;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.DurableHttpError = DurableHttpError;
|
|
63
|
+
const MAX_ATTEMPTS = 3;
|
|
64
|
+
const BACKOFF_BASE_MS = 100;
|
|
65
|
+
/**
|
|
66
|
+
* POST a batch of tool_results to the orchestrator. Retries on
|
|
67
|
+
* 5xx / network errors with exponential backoff; throws on
|
|
68
|
+
* 4xx (non-retriable) or after retries exhaust.
|
|
69
|
+
*
|
|
70
|
+
* Most callers pass a single-result batch (one tool finished, POST
|
|
71
|
+
* the result, move to next). Batch form exists so a future
|
|
72
|
+
* client-side allowlist-auto-execute path could fire multiple
|
|
73
|
+
* results in one POST.
|
|
74
|
+
*/
|
|
75
|
+
async function postToolResults(sessionId, results) {
|
|
76
|
+
const url = `${config_js_1.ORCHESTRATOR_URL}/terminal/sessions/${sessionId}/tool_results`;
|
|
77
|
+
const headers = {
|
|
78
|
+
"Content-Type": "application/json",
|
|
79
|
+
"x-api-key": (0, auth_js_1.getToken)(),
|
|
80
|
+
};
|
|
81
|
+
const body = JSON.stringify({ results });
|
|
82
|
+
let lastErr = null;
|
|
83
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(url, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers,
|
|
88
|
+
body,
|
|
89
|
+
});
|
|
90
|
+
if (response.ok) {
|
|
91
|
+
return (await response.json());
|
|
92
|
+
}
|
|
93
|
+
// 4xx is durable — server rejected the payload, retrying
|
|
94
|
+
// won't change the outcome. Throw a typed DurableHttpError
|
|
95
|
+
// (caught + re-raised below via instanceof check, never
|
|
96
|
+
// retried).
|
|
97
|
+
if (response.status >= 400 && response.status < 500) {
|
|
98
|
+
const errBody = await response.text();
|
|
99
|
+
throw new DurableHttpError(response.status, errBody);
|
|
100
|
+
}
|
|
101
|
+
// 5xx — retriable.
|
|
102
|
+
lastErr = new Error(`POST tool_results failed (${response.status}): ${await response.text()}`);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
// #6573 CR-r1: type-check the rejection class instead of
|
|
106
|
+
// string-matching the Error message. DurableHttpError means
|
|
107
|
+
// "server told us no, retrying won't change that" — re-raise
|
|
108
|
+
// immediately. Everything else (network error, fetch
|
|
109
|
+
// failure, unexpected throw) is treated as transient +
|
|
110
|
+
// retried below.
|
|
111
|
+
if (err instanceof DurableHttpError) {
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
115
|
+
}
|
|
116
|
+
if (attempt < MAX_ATTEMPTS) {
|
|
117
|
+
const delay = BACKOFF_BASE_MS * 2 ** (attempt - 1);
|
|
118
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
throw lastErr ?? new Error("POST tool_results failed (unknown)");
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tool_result_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool_result_client.js","sourceRoot":"","sources":["../src/tool_result_client.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;;;AAiDH,0CAsDC;AArGD,2CAA+C;AAC/C,uCAAqC;AAcrC;;;;;;;GAOG;AACH,MAAa,gBAAiB,SAAQ,KAAK;IAChC,MAAM,CAAS;IACf,IAAI,CAAS;IACtB,YAAY,MAAc,EAAE,IAAY;QACtC,KAAK,CAAC,+BAA+B,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AATD,4CASC;AAED,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B;;;;;;;;;GASG;AACI,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,OAA0B;IAE1B,MAAM,GAAG,GAAG,GAAG,4BAAgB,sBAAsB,SAAS,eAAe,CAAC;IAC9E,MAAM,OAAO,GAAG;QACd,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,IAAA,kBAAQ,GAAE;KACxB,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAEzC,IAAI,OAAO,GAAiB,IAAI,CAAC;IACjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI;aACL,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA4B,CAAC;YAC5D,CAAC;YACD,yDAAyD;YACzD,2DAA2D;YAC3D,wDAAwD;YACxD,YAAY;YACZ,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACpD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACtC,MAAM,IAAI,gBAAgB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvD,CAAC;YACD,mBAAmB;YACnB,OAAO,GAAG,IAAI,KAAK,CACjB,6BAA6B,QAAQ,CAAC,MAAM,MAAM,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAC1E,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yDAAyD;YACzD,4DAA4D;YAC5D,6DAA6D;YAC7D,qDAAqD;YACrD,uDAAuD;YACvD,iBAAiB;YACjB,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;gBACpC,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,OAAO,GAAG,YAAY,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,eAAe,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACnD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACnE,CAAC"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local tool execution + approval gate.
|
|
3
3
|
*
|
|
4
|
-
* All tools execute on Harvey's machine. write_file
|
|
5
|
-
*
|
|
4
|
+
* All tools execute on Harvey's machine. write_file, shell_command,
|
|
5
|
+
* and git_commit pass through `_gateApproval` which checks the
|
|
6
|
+
* persisted allowlist (`~/.xiaotime/settings.json`) before prompting.
|
|
7
|
+
* Matching allowlist entries short-circuit the menu; the post-execute
|
|
8
|
+
* status line is suffixed with ` (auto-approved)` so the user can
|
|
9
|
+
* see which calls bypassed the prompt (ISC-6509-004).
|
|
10
|
+
*
|
|
11
|
+
* Read-only tools (`read_file`, `list_directory`, `git_status`,
|
|
12
|
+
* `git_diff`) never gate (ISC-6509-006).
|
|
6
13
|
*/
|
|
14
|
+
import type { SessionUI } from "./ui_state.js";
|
|
7
15
|
export interface ToolCall {
|
|
8
16
|
tool_use_id: string;
|
|
9
17
|
name: string;
|
|
@@ -15,5 +23,5 @@ export interface ToolResult {
|
|
|
15
23
|
is_error: boolean;
|
|
16
24
|
}
|
|
17
25
|
export declare function setSessionCwd(cwd: string): void;
|
|
18
|
-
export declare function executeTool(call: ToolCall): Promise<ToolResult>;
|
|
26
|
+
export declare function executeTool(call: ToolCall, ui: SessionUI): Promise<ToolResult>;
|
|
19
27
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS/C,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,QAExC;AA2ED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,UAAU,CAAC,CA2KrB"}
|
package/dist/tools.js
CHANGED
|
@@ -2,8 +2,15 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Local tool execution + approval gate.
|
|
4
4
|
*
|
|
5
|
-
* All tools execute on Harvey's machine. write_file
|
|
6
|
-
*
|
|
5
|
+
* All tools execute on Harvey's machine. write_file, shell_command,
|
|
6
|
+
* and git_commit pass through `_gateApproval` which checks the
|
|
7
|
+
* persisted allowlist (`~/.xiaotime/settings.json`) before prompting.
|
|
8
|
+
* Matching allowlist entries short-circuit the menu; the post-execute
|
|
9
|
+
* status line is suffixed with ` (auto-approved)` so the user can
|
|
10
|
+
* see which calls bypassed the prompt (ISC-6509-004).
|
|
11
|
+
*
|
|
12
|
+
* Read-only tools (`read_file`, `list_directory`, `git_status`,
|
|
13
|
+
* `git_diff`) never gate (ISC-6509-006).
|
|
7
14
|
*/
|
|
8
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -47,9 +54,9 @@ exports.executeTool = executeTool;
|
|
|
47
54
|
const fs = __importStar(require("fs"));
|
|
48
55
|
const path = __importStar(require("path"));
|
|
49
56
|
const child_process = __importStar(require("child_process"));
|
|
50
|
-
const readline = __importStar(require("readline"));
|
|
51
57
|
const diff_1 = require("diff");
|
|
52
58
|
const chalk_1 = __importDefault(require("chalk"));
|
|
59
|
+
const settings_js_1 = require("./settings.js");
|
|
53
60
|
// Session cwd — set on connect
|
|
54
61
|
let sessionCwd = process.cwd();
|
|
55
62
|
function setSessionCwd(cwd) {
|
|
@@ -58,19 +65,59 @@ function setSessionCwd(cwd) {
|
|
|
58
65
|
function resolvePath(p) {
|
|
59
66
|
return path.isAbsolute(p) ? p : path.resolve(sessionCwd, p);
|
|
60
67
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Approval gate for the 3 prompting client-side tools. Checks the
|
|
70
|
+
* persisted allowlist first; if no match, prompts via the
|
|
71
|
+
* SessionUI menu; if the user chose "Run and don't ask again",
|
|
72
|
+
* persists the derived pattern.
|
|
73
|
+
*
|
|
74
|
+
* The header is printed in both paths (allowlist hit + menu prompt)
|
|
75
|
+
* so the user always sees what's about to run. The `(auto-approved)`
|
|
76
|
+
* indicator is appended to the caller's post-execute status line —
|
|
77
|
+
* not added by this helper — so tool-specific status text
|
|
78
|
+
* (`✓ Written` / `✓ Ran` / `✓ Committed`) stays where the tool
|
|
79
|
+
* defines it.
|
|
80
|
+
*/
|
|
81
|
+
async function _gateApproval(ui, tool, input, header) {
|
|
82
|
+
const allowlist = (0, settings_js_1.loadAllowlist)();
|
|
83
|
+
const match = (0, settings_js_1.matchAllowlist)(tool, input, allowlist);
|
|
84
|
+
if (match) {
|
|
85
|
+
// Print the header so the user sees what's about to run, then
|
|
86
|
+
// short-circuit the menu.
|
|
87
|
+
process.stdout.write(header);
|
|
88
|
+
return { approved: true, autoApproved: true };
|
|
89
|
+
}
|
|
90
|
+
const result = await ui.promptApprovalMenu(header);
|
|
91
|
+
if (!result.approved) {
|
|
92
|
+
return { approved: false, rejectReason: result.rejectReason };
|
|
93
|
+
}
|
|
94
|
+
if (result.allowlistRequested) {
|
|
95
|
+
const pattern = (0, settings_js_1.derivePattern)(tool, input);
|
|
96
|
+
if (pattern !== null) {
|
|
97
|
+
// #6538 CR-r1: wrap the persist call so a disk-full /
|
|
98
|
+
// permission-denied / chmod failure doesn't abort the tool
|
|
99
|
+
// run. The user already approved the action; the allowlist
|
|
100
|
+
// write is a UX convenience, not a correctness gate. Log a
|
|
101
|
+
// yellow warning to stderr so the failure isn't silent.
|
|
102
|
+
try {
|
|
103
|
+
(0, settings_js_1.appendAllowlist)({ tool, pattern });
|
|
104
|
+
process.stdout.write(chalk_1.default.dim(` (allowlist updated: ${tool} → ${pattern})\n`));
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
process.stderr.write(chalk_1.default.yellow(` (failed to persist allowlist: ${msg})\n`));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { approved: true, autoApproved: false };
|
|
113
|
+
}
|
|
114
|
+
function _approvedSuffix(gate) {
|
|
115
|
+
if (gate.approved && gate.autoApproved) {
|
|
116
|
+
return chalk_1.default.dim(" (auto-approved)");
|
|
117
|
+
}
|
|
118
|
+
return "";
|
|
72
119
|
}
|
|
73
|
-
async function executeTool(call) {
|
|
120
|
+
async function executeTool(call, ui) {
|
|
74
121
|
const { tool_use_id, name, input } = call;
|
|
75
122
|
try {
|
|
76
123
|
switch (name) {
|
|
@@ -101,15 +148,20 @@ async function executeTool(call) {
|
|
|
101
148
|
return chalk_1.default.red(l);
|
|
102
149
|
return chalk_1.default.dim(l);
|
|
103
150
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
if (!approved) {
|
|
108
|
-
|
|
151
|
+
const header = chalk_1.default.yellow(`\n[write_file] ${filePath}\n`) +
|
|
152
|
+
colored.join("\n") + "\n";
|
|
153
|
+
const gate = await _gateApproval(ui, "write_file", input, header);
|
|
154
|
+
if (!gate.approved) {
|
|
155
|
+
const tail = gate.rejectReason ? `: ${gate.rejectReason}` : ".";
|
|
156
|
+
return {
|
|
157
|
+
tool_use_id,
|
|
158
|
+
content: `Rejected by user${tail}`,
|
|
159
|
+
is_error: false,
|
|
160
|
+
};
|
|
109
161
|
}
|
|
110
162
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
111
163
|
fs.writeFileSync(filePath, newContent, "utf-8");
|
|
112
|
-
console.log(chalk_1.default.green(` ✓ Written`));
|
|
164
|
+
console.log(chalk_1.default.green(` ✓ Written`) + _approvedSuffix(gate));
|
|
113
165
|
return { tool_use_id, content: `File written: ${filePath}`, is_error: false };
|
|
114
166
|
}
|
|
115
167
|
case "list_directory": {
|
|
@@ -137,11 +189,16 @@ async function executeTool(call) {
|
|
|
137
189
|
case "shell_command": {
|
|
138
190
|
const command = input.command;
|
|
139
191
|
const cwd = input.cwd ? resolvePath(input.cwd) : sessionCwd;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
if (!approved) {
|
|
144
|
-
|
|
192
|
+
const header = chalk_1.default.yellow(`\n[shell_command] ${command}\n`) +
|
|
193
|
+
chalk_1.default.dim(` cwd: ${cwd}\n`);
|
|
194
|
+
const gate = await _gateApproval(ui, "shell_command", input, header);
|
|
195
|
+
if (!gate.approved) {
|
|
196
|
+
const tail = gate.rejectReason ? `: ${gate.rejectReason}` : ".";
|
|
197
|
+
return {
|
|
198
|
+
tool_use_id,
|
|
199
|
+
content: `Rejected by user${tail}`,
|
|
200
|
+
is_error: false,
|
|
201
|
+
};
|
|
145
202
|
}
|
|
146
203
|
const result = child_process.execSync(command, {
|
|
147
204
|
cwd,
|
|
@@ -149,6 +206,7 @@ async function executeTool(call) {
|
|
|
149
206
|
stdio: ["pipe", "pipe", "pipe"],
|
|
150
207
|
timeout: 60000,
|
|
151
208
|
});
|
|
209
|
+
console.log(chalk_1.default.green(` ✓ Ran`) + _approvedSuffix(gate));
|
|
152
210
|
console.log(chalk_1.default.dim(result.slice(0, 500)));
|
|
153
211
|
return { tool_use_id, content: result, is_error: false };
|
|
154
212
|
}
|
|
@@ -179,15 +237,20 @@ async function executeTool(call) {
|
|
|
179
237
|
cwd: sessionCwd,
|
|
180
238
|
encoding: "utf-8",
|
|
181
239
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
if (!approved) {
|
|
187
|
-
|
|
240
|
+
const header = chalk_1.default.yellow(`\n[git_commit]\n`) +
|
|
241
|
+
chalk_1.default.dim(`Staged:\n${staged}\n`) +
|
|
242
|
+
chalk_1.default.dim(`Message: ${message}\n`);
|
|
243
|
+
const gate = await _gateApproval(ui, "git_commit", input, header);
|
|
244
|
+
if (!gate.approved) {
|
|
245
|
+
const tail = gate.rejectReason ? `: ${gate.rejectReason}` : ".";
|
|
246
|
+
return {
|
|
247
|
+
tool_use_id,
|
|
248
|
+
content: `Rejected by user${tail}`,
|
|
249
|
+
is_error: false,
|
|
250
|
+
};
|
|
188
251
|
}
|
|
189
252
|
const out = child_process.execSync(`git commit -m ${JSON.stringify(message)}`, { cwd: sessionCwd, encoding: "utf-8" });
|
|
190
|
-
console.log(chalk_1.default.green(` ✓ Committed`));
|
|
253
|
+
console.log(chalk_1.default.green(` ✓ Committed`) + _approvedSuffix(gate));
|
|
191
254
|
return { tool_use_id, content: out, is_error: false };
|
|
192
255
|
}
|
|
193
256
|
default:
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-UI state machine for the xiaotime dev CLI.
|
|
3
|
+
*
|
|
4
|
+
* SPRINT-CLI-STATE-MACHINE-1 (#6163 / closes #6127) shipped the original
|
|
5
|
+
* state machine + raw-mode approval prompt. That fix eliminated the
|
|
6
|
+
* defaults-to-N half of the "yy" double-echo bug but the visible-yy half
|
|
7
|
+
* persisted because `readline.createInterface({ terminal: true })` attaches
|
|
8
|
+
* its own keypress handler to stdin that echoes characters via its own
|
|
9
|
+
* stdout writes; `rl.pause()` stops `line` events but does NOT detach that
|
|
10
|
+
* echo path, and `setRawMode(true)` only suppresses kernel-level echo, not
|
|
11
|
+
* readline's.
|
|
12
|
+
*
|
|
13
|
+
* SPRINT-CLI-APPROVAL-MENU-1 (#6509) replaces `promptApproval`'s `[y/N]`
|
|
14
|
+
* one-shot prompt with `promptApprovalMenu` — a three-option numbered menu
|
|
15
|
+
* (Run / Run + allowlist / Reject + feedback). The rl is explicitly
|
|
16
|
+
* **closed and recreated** around the menu render so its keypress echo
|
|
17
|
+
* physically can't fire (the rl object is gone for the duration of the
|
|
18
|
+
* menu). Persistent close listeners survive the recreation via
|
|
19
|
+
* `onRlClose()` — callers that need a stable close hook register through
|
|
20
|
+
* that instead of `getRl().on("close", ...)`.
|
|
21
|
+
*
|
|
22
|
+
* The state machine has four states:
|
|
23
|
+
*
|
|
24
|
+
* IDLE — at the `you:` prompt, awaiting user input.
|
|
25
|
+
* GENERATING — model is streaming tokens (or about to). Spinner.
|
|
26
|
+
* RUNNING_TOOL — a server-side tool is running. Spinner.
|
|
27
|
+
* AWAITING_APPROVAL — user must navigate the approval menu for a
|
|
28
|
+
* client-side tool. Main rl is closed; raw stdin
|
|
29
|
+
* captures keystrokes.
|
|
30
|
+
*
|
|
31
|
+
* The WS handler in `ws.ts` is the sole driver. Transitions:
|
|
32
|
+
*
|
|
33
|
+
* IDLE -- user line received -> GENERATING
|
|
34
|
+
* GENERATING -- text_delta -> GENERATING (refresh)
|
|
35
|
+
* GENERATING -- tool_call (server) -> RUNNING_TOOL
|
|
36
|
+
* GENERATING -- tool_call (client+approval) -> AWAITING_APPROVAL
|
|
37
|
+
* AWAITING_APPROVAL -- menu selection -> RUNNING_TOOL
|
|
38
|
+
* RUNNING_TOOL -- tool_result sent -> GENERATING
|
|
39
|
+
* GENERATING -- message_stop -> IDLE
|
|
40
|
+
* ANY -- error -> IDLE
|
|
41
|
+
*/
|
|
42
|
+
import * as readline from "readline";
|
|
43
|
+
export type CliState = "idle" | "generating" | "running_tool" | "awaiting_approval";
|
|
44
|
+
export type ApprovalMenuResult = {
|
|
45
|
+
approved: true;
|
|
46
|
+
allowlistRequested: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
approved: false;
|
|
49
|
+
rejectReason: string;
|
|
50
|
+
};
|
|
51
|
+
export declare class SessionUI {
|
|
52
|
+
private state;
|
|
53
|
+
private spinnerTimer;
|
|
54
|
+
private spinnerFrame;
|
|
55
|
+
private spinnerStartedAt;
|
|
56
|
+
private spinnerLabel;
|
|
57
|
+
private spinnerLineDirty;
|
|
58
|
+
private rl;
|
|
59
|
+
private lineListener;
|
|
60
|
+
/**
|
|
61
|
+
* Close-listener callbacks that should survive rl recreations. The
|
|
62
|
+
* approval-menu path closes + recreates `rl` to physically detach
|
|
63
|
+
* readline's keypress echo. ws.ts registers its "Session paused"
|
|
64
|
+
* resume hint here so it stays attached across recreations.
|
|
65
|
+
*/
|
|
66
|
+
private closeListeners;
|
|
67
|
+
constructor();
|
|
68
|
+
/** Hand the underlying readline to callers that need it for cleanup. */
|
|
69
|
+
getRl(): readline.Interface;
|
|
70
|
+
/**
|
|
71
|
+
* Register a callback to fire when the rl reports a non-suppressed
|
|
72
|
+
* `close` event (the only one users observe is Ctrl+C at the main
|
|
73
|
+
* prompt — close-during-approval is suppressed via removeAllListeners
|
|
74
|
+
* before `rl.close()`). Callbacks are re-attached on every rl
|
|
75
|
+
* recreation so they outlive `promptApprovalMenu`.
|
|
76
|
+
*/
|
|
77
|
+
onRlClose(listener: () => void): void;
|
|
78
|
+
/** Set the explicit current state. Drives spinner start/stop. */
|
|
79
|
+
setState(next: CliState): void;
|
|
80
|
+
getState(): CliState;
|
|
81
|
+
/** Wait for one line of user input on the main rl. */
|
|
82
|
+
promptLine(): Promise<string>;
|
|
83
|
+
/**
|
|
84
|
+
* Three-option numbered approval menu. Replaces the pre-#6509
|
|
85
|
+
* `[y/N]` one-shot prompt.
|
|
86
|
+
*
|
|
87
|
+
* Visual:
|
|
88
|
+
* ❯ 1. Run
|
|
89
|
+
* 2. Run and don't ask again
|
|
90
|
+
* 3. Reject and tell Claude why
|
|
91
|
+
* (1-3, ↑↓ Enter, Esc to reject)
|
|
92
|
+
*
|
|
93
|
+
* Controls:
|
|
94
|
+
* - Number key 1/2/3 — one-shot select
|
|
95
|
+
* - Arrow Up/Down — move focus
|
|
96
|
+
* - Enter — select focused
|
|
97
|
+
* - Esc — equivalent to option 3 (reject)
|
|
98
|
+
* - Ctrl+C — reject + propagate SIGINT (cancels session)
|
|
99
|
+
*
|
|
100
|
+
* The rl is closed before the menu render and recreated after. This
|
|
101
|
+
* physically removes readline's keypress echo from stdin for the
|
|
102
|
+
* duration of the menu — the bug fix the #6163 patch attempted via
|
|
103
|
+
* `rl.pause()` (which only stops `line` events, not the keypress
|
|
104
|
+
* echo). Persistent close listeners are stashed in
|
|
105
|
+
* `this.closeListeners` and re-attached on recreate; the close event
|
|
106
|
+
* triggered by THIS close() is suppressed via removeAllListeners
|
|
107
|
+
* before the call so it doesn't fire the "Session paused" hint.
|
|
108
|
+
*
|
|
109
|
+
* For option 3, after the menu resolves the recreated rl prompts
|
|
110
|
+
* once for a free-form rejection reason (line-mode). Empty input is
|
|
111
|
+
* allowed.
|
|
112
|
+
*
|
|
113
|
+
* The returned `allowlistRequested: true` (option 2) is a signal to
|
|
114
|
+
* the caller — PR2 wires it to write the pattern to
|
|
115
|
+
* `~/.xiaotime/settings.json`. PR1 callers may ignore it.
|
|
116
|
+
*/
|
|
117
|
+
promptApprovalMenu(toolHeader?: string): Promise<ApprovalMenuResult>;
|
|
118
|
+
private _makeRl;
|
|
119
|
+
private _renderMenuAndGetSelection;
|
|
120
|
+
/** Total lines the menu occupies: one per option + one hint line. */
|
|
121
|
+
private _menuLineCount;
|
|
122
|
+
private _renderMenu;
|
|
123
|
+
private _rerenderMenu;
|
|
124
|
+
private _clearMenu;
|
|
125
|
+
private startSpinner;
|
|
126
|
+
private renderSpinnerFrame;
|
|
127
|
+
private stopSpinner;
|
|
128
|
+
/** Called by the text_delta renderer the first time a real model
|
|
129
|
+
* token arrives during a `generating` state. Clears the spinner so
|
|
130
|
+
* the token prints cleanly, but leaves the state at `generating`
|
|
131
|
+
* (token streaming continues without re-spinning). */
|
|
132
|
+
onFirstToken(): void;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=ui_state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui_state.d.ts","sourceRoot":"","sources":["../src/ui_state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,YAAY,GACZ,cAAc,GACd,mBAAmB,CAAC;AAExB,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAa9C,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,YAAY,CAAM;IAK1B,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,YAAY,CAAyC;IAC7D;;;;;OAKG;IACH,OAAO,CAAC,cAAc,CAAyB;;IAM/C,wEAAwE;IACxE,KAAK,IAAI,QAAQ,CAAC,SAAS;IAI3B;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAKrC,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAoB9B,QAAQ,IAAI,QAAQ;IAIpB,sDAAsD;IACtD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAe7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACG,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgD1E,OAAO,CAAC,OAAO;YAYD,0BAA0B;IAmIxC,qEAAqE;IACrE,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,WAAW;IAYnB;;;0DAGsD;IACtD,YAAY,IAAI,IAAI;CAUrB"}
|