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.
Files changed (53) hide show
  1. package/dist/__tests__/approval_menu.test.d.ts +15 -0
  2. package/dist/__tests__/approval_menu.test.d.ts.map +1 -0
  3. package/dist/__tests__/approval_menu.test.js +107 -0
  4. package/dist/__tests__/approval_menu.test.js.map +1 -0
  5. package/dist/__tests__/legacy_compat.test.d.ts +2 -0
  6. package/dist/__tests__/legacy_compat.test.d.ts.map +1 -0
  7. package/dist/__tests__/legacy_compat.test.js +36 -0
  8. package/dist/__tests__/legacy_compat.test.js.map +1 -0
  9. package/dist/__tests__/server_tool_render.test.d.ts +17 -0
  10. package/dist/__tests__/server_tool_render.test.d.ts.map +1 -0
  11. package/dist/__tests__/server_tool_render.test.js +74 -0
  12. package/dist/__tests__/server_tool_render.test.js.map +1 -0
  13. package/dist/__tests__/settings.test.d.ts +16 -0
  14. package/dist/__tests__/settings.test.d.ts.map +1 -0
  15. package/dist/__tests__/settings.test.js +289 -0
  16. package/dist/__tests__/settings.test.js.map +1 -0
  17. package/dist/__tests__/tool_result_client.test.d.ts +20 -0
  18. package/dist/__tests__/tool_result_client.test.d.ts.map +1 -0
  19. package/dist/__tests__/tool_result_client.test.js +142 -0
  20. package/dist/__tests__/tool_result_client.test.js.map +1 -0
  21. package/dist/__tests__/tools.test.d.ts +17 -0
  22. package/dist/__tests__/tools.test.d.ts.map +1 -0
  23. package/dist/__tests__/tools.test.js +381 -0
  24. package/dist/__tests__/tools.test.js.map +1 -0
  25. package/dist/config.d.ts +7 -0
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +8 -1
  28. package/dist/config.js.map +1 -1
  29. package/dist/display.d.ts +19 -0
  30. package/dist/display.d.ts.map +1 -1
  31. package/dist/display.js +23 -0
  32. package/dist/display.js.map +1 -1
  33. package/dist/settings.d.ts +109 -0
  34. package/dist/settings.d.ts.map +1 -0
  35. package/dist/settings.js +332 -0
  36. package/dist/settings.js.map +1 -0
  37. package/dist/tool_result_client.d.ts +72 -0
  38. package/dist/tool_result_client.d.ts.map +1 -0
  39. package/dist/tool_result_client.js +123 -0
  40. package/dist/tool_result_client.js.map +1 -0
  41. package/dist/tools.d.ts +11 -3
  42. package/dist/tools.d.ts.map +1 -1
  43. package/dist/tools.js +96 -33
  44. package/dist/tools.js.map +1 -1
  45. package/dist/ui_state.d.ts +134 -0
  46. package/dist/ui_state.d.ts.map +1 -0
  47. package/dist/ui_state.js +460 -0
  48. package/dist/ui_state.js.map +1 -0
  49. package/dist/ws.d.ts +15 -0
  50. package/dist/ws.d.ts.map +1 -1
  51. package/dist/ws.js +180 -75
  52. package/dist/ws.js.map +1 -1
  53. package/package.json +6 -3
package/dist/ws.js CHANGED
@@ -1,67 +1,129 @@
1
1
  "use strict";
2
2
  /**
3
3
  * WebSocket connection and main message loop.
4
+ *
5
+ * SPRINT-CLI-STATE-MACHINE-1 (#6163 / closes #6127) — drives the
6
+ * SessionUI state machine from incoming WS events so the user gets
7
+ * a spinner while the model is generating / a tool is running, and
8
+ * approval prompts don't race the main rl on keystrokes.
9
+ *
10
+ * SPRINT-TERMINAL-CLIENT-OWNED-DISPATCH-1 (#6565) PR3 — tool_result
11
+ * delivery moved off the WebSocket: results POST to
12
+ * /terminal/sessions/{id}/tool_results via the new REST endpoint.
13
+ * The WS now carries only inbound (server→client) `tool_call`
14
+ * events as informational triggers. Tool calls drain serially
15
+ * through a local queue so concurrent menus can't corrupt
16
+ * SessionUI state — the pre-#6565 `inFlightToolUseId` reject-on-
17
+ * overlap guard is gone (it caused the wedge observed in the
18
+ * #6509 PR1 canary).
4
19
  */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
20
  var __importDefault = (this && this.__importDefault) || function (mod) {
39
21
  return (mod && mod.__esModule) ? mod : { "default": mod };
40
22
  };
41
23
  Object.defineProperty(exports, "__esModule", { value: true });
42
24
  exports.runSession = runSession;
43
25
  const ws_1 = __importDefault(require("ws"));
44
- const readline = __importStar(require("readline"));
45
26
  const config_js_1 = require("./config.js");
46
27
  const auth_js_1 = require("./auth.js");
47
28
  const tools_js_1 = require("./tools.js");
29
+ const tool_result_client_js_1 = require("./tool_result_client.js");
48
30
  const display_js_1 = require("./display.js");
31
+ const ui_state_js_1 = require("./ui_state.js");
32
+ const chalk_1 = __importDefault(require("chalk"));
49
33
  async function runSession(sessionId) {
50
34
  const wsUrl = `${config_js_1.WS_URL}/terminal/sessions/${sessionId}/stream`;
51
35
  return new Promise((resolve, reject) => {
52
36
  const ws = new ws_1.default(wsUrl);
53
37
  let connected = false;
54
- let waitingForToolResult = false;
55
- let pendingResolve = null;
56
- // ── Readline for user input ───────────────────────────────────
57
- const rl = readline.createInterface({
58
- input: process.stdin,
59
- output: process.stdout,
60
- terminal: true,
61
- });
38
+ const ui = new ui_state_js_1.SessionUI();
39
+ let firstTokenThisTurn = true;
40
+ // #6565 PR3 serial drain queue. The server may emit multiple
41
+ // tool_call events back-to-back (one per tool_use block in the
42
+ // model's batch). Executing concurrently would corrupt
43
+ // SessionUI state (two menus rendering on top of each other);
44
+ // queueing + draining one-at-a-time gives clean approval flows
45
+ // while still parallelizable across the server (server emits
46
+ // all N then awaits the resume signal — order of completion
47
+ // doesn't matter to the server, only that all N land via POST).
48
+ const toolCallQueue = [];
49
+ let drainRunning = false;
50
+ async function drainToolCallQueue() {
51
+ if (drainRunning)
52
+ return;
53
+ drainRunning = true;
54
+ try {
55
+ while (toolCallQueue.length > 0) {
56
+ const tc = toolCallQueue.shift();
57
+ ui.setState("running_tool");
58
+ const result = await (0, tools_js_1.executeTool)({
59
+ tool_use_id: tc.tool_use_id,
60
+ name: tc.name,
61
+ input: tc.input,
62
+ }, ui);
63
+ let postFailed = false;
64
+ try {
65
+ await (0, tool_result_client_js_1.postToolResults)(sessionId, [
66
+ {
67
+ tool_use_id: result.tool_use_id,
68
+ content: result.content,
69
+ is_error: result.is_error,
70
+ },
71
+ ]);
72
+ }
73
+ catch (err) {
74
+ // POST exhausted retries (transient 5xx / network) OR
75
+ // 4xx (durable rejection, e.g. unknown_tool_use_id from
76
+ // a server restart that lost the pending row). Tool
77
+ // result is lost from the server's perspective; the
78
+ // pending row stays as `pending` until PR5's expiry
79
+ // sweep. PR4's WS-reconnect replay path will re-emit
80
+ // the tool_call on next session connect for a retry.
81
+ const msg = err instanceof Error ? err.message : String(err);
82
+ process.stderr.write(chalk_1.default.yellow(` (tool_result POST failed: ${msg})\n`));
83
+ postFailed = true;
84
+ }
85
+ // #6573 CR-r1: on POST failure, the server's resume signal
86
+ // won't fire (server never learns this tool completed).
87
+ // The CLI would sit silently with no further events from
88
+ // the server, looking wedged. Bounce the user back to the
89
+ // prompt with a clear cue + a fresh idle state so they can
90
+ // type `xiaotime dev --session <id>` (resume) or pick a
91
+ // different recovery action. The unfinished pending rows
92
+ // stay durable in the DB for PR4's reconnect replay.
93
+ if (postFailed) {
94
+ ui.setState("idle");
95
+ process.stderr.write(chalk_1.default.yellow(" (session paused — POST failed; reconnect with " +
96
+ "`xiaotime dev --session " +
97
+ sessionId +
98
+ "` to retry pending tool calls)\n"));
99
+ // #6573 CR-r1: a POST failure means the server never got
100
+ // the resume signal — its dispatch state is inconsistent.
101
+ // Close the socket rather than returning to the prompt:
102
+ // the clean recovery is a fresh session, not a retry on a
103
+ // half-dispatched one. ws.close() fires the on("close")
104
+ // handler (rl teardown + resolve), so the user genuinely
105
+ // re-runs `xiaotime dev --session <id>`. Pending rows stay
106
+ // durable in the DB for PR4's reconnect replay; draining
107
+ // stops here because the loop is abandoned with the session.
108
+ ws.close();
109
+ return;
110
+ }
111
+ // Don't transition state back to "generating" here — the
112
+ // model may already be streaming on the next turn (the
113
+ // server's resume happens as soon as all batch results
114
+ // land via POST). The next text_delta clears the spinner
115
+ // via onFirstToken.
116
+ firstTokenThisTurn = true;
117
+ }
118
+ }
119
+ finally {
120
+ drainRunning = false;
121
+ }
122
+ }
62
123
  ws.on("open", () => {
63
- // Auth
64
- ws.send(JSON.stringify({ type: "auth", token: (0, auth_js_1.getToken)() }));
124
+ // Auth — #6565 PR5: `version` lets the server reject pre-0.4.0
125
+ // clients that would wedge on the old WS tool_result path.
126
+ ws.send(JSON.stringify({ type: "auth", token: (0, auth_js_1.getToken)(), version: config_js_1.CLI_VERSION }));
65
127
  // Connect with cwd
66
128
  ws.send(JSON.stringify({ type: "connect", cwd: process.cwd() }));
67
129
  });
@@ -72,51 +134,85 @@ async function runSession(sessionId) {
72
134
  connected = true;
73
135
  (0, tools_js_1.setSessionCwd)(process.cwd());
74
136
  (0, display_js_1.printWelcome)(msg.session_id, msg.session_name, msg.resumed, msg.message_count);
75
- promptUser();
137
+ // #6565 PR4b — if the server is replaying tool calls left
138
+ // pending by a prior session (restart / crash mid-approval),
139
+ // defer the prompt loop. The server emits those `tool_call`
140
+ // events next; they drain through the queue, the CLI POSTs
141
+ // results, the server resumes the turn, and that turn's
142
+ // `message_stop` starts the prompt loop. Starting it here
143
+ // would race the replayed approval menus against the prompt.
144
+ if ((msg.pending_tool_calls ?? 0) > 0) {
145
+ process.stderr.write(chalk_1.default.cyan(` (resuming ${msg.pending_tool_calls} pending tool ` +
146
+ `call(s) from a prior session)\n`));
147
+ }
148
+ else {
149
+ startUserPromptLoop();
150
+ }
76
151
  break;
77
152
  case "text_delta":
153
+ if (firstTokenThisTurn) {
154
+ ui.onFirstToken();
155
+ firstTokenThisTurn = false;
156
+ }
78
157
  (0, display_js_1.printTextDelta)(msg.content);
79
158
  break;
80
- case "tool_call":
81
- waitingForToolResult = true;
82
- (0, tools_js_1.executeTool)({
159
+ case "tool_call": {
160
+ // #6565 PR3 — informational event now. Server has already
161
+ // persisted the pending row + is awaiting our POST to
162
+ // /terminal/sessions/{id}/tool_results. Queue the call
163
+ // for serial draining (one menu rendering at a time);
164
+ // POST the result after each drain iteration. The
165
+ // pre-#6565 inFlightToolUseId reject-on-overlap guard is
166
+ // gone — concurrent dispatch is now safe by construction
167
+ // via the drain serialization.
168
+ toolCallQueue.push({
83
169
  tool_use_id: msg.tool_use_id,
84
170
  name: msg.name,
85
171
  input: msg.input,
86
- }).then((result) => {
87
- waitingForToolResult = false;
88
- ws.send(JSON.stringify({
89
- type: "tool_result",
90
- tool_use_id: result.tool_use_id,
91
- content: result.content,
92
- is_error: result.is_error,
93
- }));
94
172
  });
173
+ // Fire-and-forget — drainToolCallQueue is idempotent on
174
+ // concurrent invocation (the drainRunning guard inside).
175
+ drainToolCallQueue();
95
176
  break;
177
+ }
96
178
  case "message_stop":
179
+ ui.setState("idle");
97
180
  (0, display_js_1.printTurnEnd)(msg.cost_usd || 0);
98
- promptUser();
181
+ startUserPromptLoop();
99
182
  break;
100
183
  case "error":
184
+ ui.setState("idle");
101
185
  (0, display_js_1.printError)(msg.message);
102
186
  if (!connected) {
103
187
  ws.close();
104
188
  reject(new Error(msg.message));
105
189
  }
106
190
  else {
107
- promptUser();
191
+ startUserPromptLoop();
108
192
  }
109
193
  break;
194
+ case "server_tool_call":
195
+ // #6509 PR3 — visibility line for the 15 server-side tools
196
+ // in terminal_orchestrator/main.py SERVER_TOOLS. Clear the
197
+ // spinner first so the [server:<name>] line doesn't get
198
+ // overwritten by the spinner's next frame, and pin
199
+ // firstTokenThisTurn=false so a subsequent text_delta
200
+ // doesn't double-clear (onFirstToken is idempotent but
201
+ // the bookkeeping flag should reflect reality).
202
+ ui.onFirstToken();
203
+ firstTokenThisTurn = false;
204
+ (0, display_js_1.printServerToolCall)(msg.name, msg.input_summary || "");
205
+ break;
110
206
  case "pong":
111
207
  break;
112
208
  }
113
209
  });
114
210
  ws.on("close", () => {
115
- rl.close();
211
+ ui.getRl().close();
116
212
  resolve();
117
213
  });
118
214
  ws.on("error", (err) => {
119
- rl.close();
215
+ ui.getRl().close();
120
216
  reject(err);
121
217
  });
122
218
  // ── Ping keepalive ────────────────────────────────────────────
@@ -126,24 +222,33 @@ async function runSession(sessionId) {
126
222
  }
127
223
  }, 30000);
128
224
  ws.on("close", () => clearInterval(pingInterval));
129
- // ── User input ────────────────────────────────────────────────
130
- function promptUser() {
131
- if (!connected || waitingForToolResult)
225
+ // ── User input loop ────────────────────────────────────────────
226
+ async function startUserPromptLoop() {
227
+ if (!connected)
132
228
  return;
133
229
  (0, display_js_1.printPrompt)();
134
- rl.once("line", (line) => {
135
- const text = line.trim();
136
- if (!text) {
137
- promptUser();
138
- return;
139
- }
140
- if (ws.readyState === ws_1.default.OPEN) {
141
- ws.send(JSON.stringify({ type: "message", content: text }));
142
- }
143
- });
230
+ const text = await ui.promptLine();
231
+ if (!text) {
232
+ startUserPromptLoop();
233
+ return;
234
+ }
235
+ if (ws.readyState === ws_1.default.OPEN) {
236
+ // Mark generating BEFORE sending the message — gives the user
237
+ // an immediate spinner while we wait for the first token. The
238
+ // server may take 1-3s before the first text_delta lands;
239
+ // pre-#6163 this was a silent wait that looked like a hang.
240
+ ui.setState("generating");
241
+ firstTokenThisTurn = true;
242
+ ws.send(JSON.stringify({ type: "message", content: text }));
243
+ }
144
244
  }
145
- // Ctrl+C
146
- rl.on("close", () => {
245
+ // Ctrl+C — registered via onRlClose (not getRl().on) so the listener
246
+ // survives the rl close-and-recreate cycle in promptApprovalMenu
247
+ // (SPRINT-CLI-APPROVAL-MENU-1 / #6509 PR1). The intra-menu close is
248
+ // suppressed inside promptApprovalMenu via removeAllListeners before
249
+ // calling rl.close(), so this listener only fires for genuine
250
+ // user-initiated Ctrl+C at the main prompt.
251
+ ui.onRlClose(() => {
147
252
  console.log("\nSession paused. Resume with: xiaotime dev --session " + sessionId);
148
253
  ws.close();
149
254
  });
package/dist/ws.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ws.js","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ws.js","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xiaotime",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "Xiaotime Developer — persistent-memory AI coding assistant",
5
5
  "bin": {
6
6
  "xiaotime": "./dist/index.js"
@@ -12,6 +12,8 @@
12
12
  "scripts": {
13
13
  "build": "tsc",
14
14
  "dev": "ts-node src/index.ts",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
15
17
  "prepublishOnly": "npm run build"
16
18
  },
17
19
  "dependencies": {
@@ -23,9 +25,10 @@
23
25
  "@types/ws": "^8.5.12",
24
26
  "@types/node": "^22.0.0",
25
27
  "typescript": "^5.7.0",
26
- "ts-node": "^10.9.2"
28
+ "ts-node": "^10.9.2",
29
+ "vitest": "^4.1.7"
27
30
  },
28
31
  "engines": {
29
- "node": ">=18.0.0"
32
+ "node": ">=20.19.0"
30
33
  }
31
34
  }