happy-imou-cloud 2.1.49 → 2.1.51

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 (55) hide show
  1. package/dist/AcpBackend-CqO3D07V.mjs +2619 -0
  2. package/dist/AcpBackend-XPiTd6ph.cjs +2621 -0
  3. package/dist/{BaseReasoningProcessor-Dn9NcoHz.cjs → BaseReasoningProcessor-BD9tiwep.cjs} +1 -144
  4. package/dist/{BaseReasoningProcessor-CAVeOdyo.mjs → BaseReasoningProcessor-CjlayL2f.mjs} +2 -144
  5. package/dist/ConversationHistory-Bl2doTA-.cjs +780 -0
  6. package/dist/ConversationHistory-CI5bBfuA.mjs +771 -0
  7. package/dist/{ProviderSelectionHandler-BJJc7qOR.cjs → ProviderSelectionHandler-C7GE5QjX.cjs} +6 -6
  8. package/dist/{ProviderSelectionHandler-DIYidT13.mjs → ProviderSelectionHandler-uQ8jzdzr.mjs} +2 -2
  9. package/dist/RuntimeShell-BDt42io_.mjs +252 -0
  10. package/dist/RuntimeShell-D_Te12wq.cjs +258 -0
  11. package/dist/bootstrapManagedProviderSession-Bln-TwyB.cjs +147 -0
  12. package/dist/bootstrapManagedProviderSession-D2Z6YU3n.mjs +145 -0
  13. package/dist/claude-BKNT-2fG.cjs +1080 -0
  14. package/dist/claude-CnN5WCWj.mjs +1073 -0
  15. package/dist/codex-DLGP8WF6.mjs +577 -0
  16. package/dist/codex-Fv2eali8.cjs +582 -0
  17. package/dist/{command-VcH4hbhi.cjs → command-BWPlJyCN.cjs} +16 -8
  18. package/dist/{command-CzfRRhVe.mjs → command-CELwsYoG.mjs} +15 -7
  19. package/dist/config-CFL0Gkqt.cjs +184 -0
  20. package/dist/config-ChSPe7p9.mjs +174 -0
  21. package/dist/createDefaultRuntimeShell-BXu3vCvT.cjs +33 -0
  22. package/dist/createDefaultRuntimeShell-DOg6g3-G.mjs +31 -0
  23. package/dist/cursor-Blq1cHdr.cjs +91 -0
  24. package/dist/cursor-CwPNSy_A.mjs +88 -0
  25. package/dist/future-Dq4Ha1Dn.cjs +24 -0
  26. package/dist/future-xRdLl3vf.mjs +22 -0
  27. package/dist/{index-xa1kwZoj.cjs → index-B_JYgMUS.cjs} +189 -5352
  28. package/dist/{index-7Z93BoVn.mjs → index-CX-F_fuk.mjs} +177 -5331
  29. package/dist/index.cjs +2 -2
  30. package/dist/index.mjs +2 -2
  31. package/dist/installFatalProcessHandlers-0vaw9MAz.mjs +55 -0
  32. package/dist/installFatalProcessHandlers-CyURn5Bp.cjs +57 -0
  33. package/dist/launch-BoCCEd5p.mjs +63 -0
  34. package/dist/launch-wZA5BcvS.cjs +66 -0
  35. package/dist/lib.cjs +2 -3
  36. package/dist/lib.d.cts +20 -17
  37. package/dist/lib.d.mts +20 -17
  38. package/dist/lib.mjs +1 -2
  39. package/dist/resolveCommand-B3BGyBE2.mjs +189 -0
  40. package/dist/resolveCommand-DYMd9PNC.cjs +193 -0
  41. package/dist/{runClaude-zCwRhpOw.mjs → runClaude-Be0myF9k.mjs} +8 -5
  42. package/dist/{runClaude-BBGNmGj6.cjs → runClaude-DZJt5er7.cjs} +46 -43
  43. package/dist/{runCodex-BbgLVjb9.mjs → runCodex-BSnyN4m7.mjs} +226 -117
  44. package/dist/{runCodex-jUU6U2tZ.cjs → runCodex-DTCcGRue.cjs} +269 -160
  45. package/dist/runCursor-Bn1PuwJy.cjs +506 -0
  46. package/dist/runCursor-M6dQ6bGF.mjs +504 -0
  47. package/dist/{runGemini-DcwNsudA.mjs → runGemini-BNm4vYKA.mjs} +279 -5
  48. package/dist/{runGemini-C0NT8MHK.cjs → runGemini-Bn3lFhz6.cjs} +309 -35
  49. package/dist/{registerKillSessionHandler-DLDg2EES.mjs → sessionControl-1bT_7OI6.mjs} +1643 -2405
  50. package/dist/{registerKillSessionHandler-CfCya6si.cjs → sessionControl-flKnQrx0.cjs} +1647 -2417
  51. package/dist/{api-DnqaNvyV.mjs → types-B5vtxa38.mjs} +55 -5
  52. package/dist/{api-D7nAeZi7.cjs → types-CttABk32.cjs} +55 -4
  53. package/package.json +2 -2
  54. package/dist/types-CiliQpqS.mjs +0 -52
  55. package/dist/types-DVk3crez.cjs +0 -54
@@ -0,0 +1,1073 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { resolve, join } from 'node:path';
3
+ import { spawn } from 'node:child_process';
4
+ import { createInterface } from 'node:readline';
5
+ import { existsSync } from 'node:fs';
6
+ import { j as getDefaultClaudeCodePath, k as getCleanEnv, l as logDebug, m as streamToStdin, p as projectPath } from './index-CX-F_fuk.mjs';
7
+ import { l as logger } from './types-B5vtxa38.mjs';
8
+ import { F as Future } from './future-xRdLl3vf.mjs';
9
+ import { f as formatDisplayMessage, a as agentRegistry } from './RuntimeShell-BDt42io_.mjs';
10
+
11
+ class Stream {
12
+ constructor(returned) {
13
+ this.returned = returned;
14
+ }
15
+ queue = [];
16
+ readResolve;
17
+ readReject;
18
+ isDone = false;
19
+ hasError;
20
+ started = false;
21
+ /**
22
+ * Implements async iterable protocol
23
+ */
24
+ [Symbol.asyncIterator]() {
25
+ if (this.started) {
26
+ throw new Error("Stream can only be iterated once");
27
+ }
28
+ this.started = true;
29
+ return this;
30
+ }
31
+ /**
32
+ * Gets the next value from the stream
33
+ */
34
+ async next() {
35
+ if (this.queue.length > 0) {
36
+ return Promise.resolve({
37
+ done: false,
38
+ value: this.queue.shift()
39
+ });
40
+ }
41
+ if (this.isDone) {
42
+ return Promise.resolve({ done: true, value: void 0 });
43
+ }
44
+ if (this.hasError) {
45
+ return Promise.reject(this.hasError);
46
+ }
47
+ return new Promise((resolve, reject) => {
48
+ this.readResolve = resolve;
49
+ this.readReject = reject;
50
+ });
51
+ }
52
+ /**
53
+ * Adds a value to the stream
54
+ */
55
+ enqueue(value) {
56
+ if (this.readResolve) {
57
+ const resolve = this.readResolve;
58
+ this.readResolve = void 0;
59
+ this.readReject = void 0;
60
+ resolve({ done: false, value });
61
+ } else {
62
+ this.queue.push(value);
63
+ }
64
+ }
65
+ /**
66
+ * Marks the stream as complete
67
+ */
68
+ done() {
69
+ this.isDone = true;
70
+ if (this.readResolve) {
71
+ const resolve = this.readResolve;
72
+ this.readResolve = void 0;
73
+ this.readReject = void 0;
74
+ resolve({ done: true, value: void 0 });
75
+ }
76
+ }
77
+ /**
78
+ * Propagates an error through the stream
79
+ */
80
+ error(error) {
81
+ this.hasError = error;
82
+ if (this.readReject) {
83
+ const reject = this.readReject;
84
+ this.readResolve = void 0;
85
+ this.readReject = void 0;
86
+ reject(error);
87
+ }
88
+ }
89
+ /**
90
+ * Implements async iterator cleanup
91
+ */
92
+ async return() {
93
+ this.isDone = true;
94
+ if (this.returned) {
95
+ this.returned();
96
+ }
97
+ return Promise.resolve({ done: true, value: void 0 });
98
+ }
99
+ }
100
+
101
+ class AbortError extends Error {
102
+ constructor(message) {
103
+ super(message);
104
+ this.name = "AbortError";
105
+ }
106
+ }
107
+
108
+ class Query {
109
+ constructor(childStdin, childStdout, processExitPromise, canCallTool) {
110
+ this.childStdin = childStdin;
111
+ this.childStdout = childStdout;
112
+ this.processExitPromise = processExitPromise;
113
+ this.canCallTool = canCallTool;
114
+ this.readMessages();
115
+ this.sdkMessages = this.readSdkMessages();
116
+ }
117
+ pendingControlResponses = /* @__PURE__ */ new Map();
118
+ cancelControllers = /* @__PURE__ */ new Map();
119
+ controlTasks = /* @__PURE__ */ new Set();
120
+ sdkMessages;
121
+ inputStream = new Stream();
122
+ canCallTool;
123
+ /**
124
+ * Set an error on the stream
125
+ */
126
+ setError(error) {
127
+ this.inputStream.error(error);
128
+ }
129
+ /**
130
+ * AsyncIterableIterator implementation
131
+ */
132
+ next(...args) {
133
+ return this.sdkMessages.next(...args);
134
+ }
135
+ return(value) {
136
+ if (this.sdkMessages.return) {
137
+ return this.sdkMessages.return(value);
138
+ }
139
+ return Promise.resolve({ done: true, value: void 0 });
140
+ }
141
+ throw(e) {
142
+ if (this.sdkMessages.throw) {
143
+ return this.sdkMessages.throw(e);
144
+ }
145
+ return Promise.reject(e);
146
+ }
147
+ [Symbol.asyncIterator]() {
148
+ return this.sdkMessages;
149
+ }
150
+ /**
151
+ * Read messages from Claude process stdout
152
+ */
153
+ async readMessages() {
154
+ const rl = createInterface({ input: this.childStdout });
155
+ try {
156
+ for await (const line of rl) {
157
+ if (line.trim()) {
158
+ try {
159
+ const message = JSON.parse(line);
160
+ if (message.type === "control_response") {
161
+ const controlResponse = message;
162
+ const handler = this.pendingControlResponses.get(controlResponse.response.request_id);
163
+ if (handler) {
164
+ handler(controlResponse.response);
165
+ }
166
+ continue;
167
+ } else if (message.type === "control_request") {
168
+ const controlTask = this.handleControlRequest(message).catch((error) => {
169
+ logger.debug("[ClaudeSDK] Failed to handle control request:", error);
170
+ }).finally(() => {
171
+ this.controlTasks.delete(controlTask);
172
+ });
173
+ this.controlTasks.add(controlTask);
174
+ continue;
175
+ } else if (message.type === "control_cancel_request") {
176
+ this.handleControlCancelRequest(message);
177
+ continue;
178
+ }
179
+ this.inputStream.enqueue(message);
180
+ } catch (e) {
181
+ logger.debug(line);
182
+ }
183
+ }
184
+ }
185
+ await this.processExitPromise;
186
+ } catch (error) {
187
+ this.inputStream.error(error);
188
+ } finally {
189
+ this.cleanupControllers();
190
+ if (this.controlTasks.size > 0) {
191
+ await Promise.allSettled(Array.from(this.controlTasks));
192
+ }
193
+ this.inputStream.done();
194
+ rl.close();
195
+ }
196
+ }
197
+ /**
198
+ * Async generator for SDK messages
199
+ */
200
+ async *readSdkMessages() {
201
+ for await (const message of this.inputStream) {
202
+ yield message;
203
+ }
204
+ }
205
+ /**
206
+ * Send interrupt request to Claude
207
+ */
208
+ async interrupt() {
209
+ if (!this.childStdin) {
210
+ throw new Error("Interrupt requires --input-format stream-json");
211
+ }
212
+ await this.request({
213
+ subtype: "interrupt"
214
+ }, this.childStdin);
215
+ }
216
+ /**
217
+ * Send control request to Claude process
218
+ */
219
+ request(request, childStdin) {
220
+ const requestId = Math.random().toString(36).substring(2, 15);
221
+ const sdkRequest = {
222
+ request_id: requestId,
223
+ type: "control_request",
224
+ request
225
+ };
226
+ return new Promise((resolve, reject) => {
227
+ this.pendingControlResponses.set(requestId, (response) => {
228
+ if (response.subtype === "success") {
229
+ resolve(response);
230
+ } else {
231
+ reject(new Error(response.error));
232
+ }
233
+ });
234
+ childStdin.write(JSON.stringify(sdkRequest) + "\n");
235
+ });
236
+ }
237
+ /**
238
+ * Handle incoming control requests for tool permissions
239
+ * Replicates the exact logic from the SDK's handleControlRequest method
240
+ */
241
+ async handleControlRequest(request) {
242
+ if (!this.childStdin) {
243
+ logDebug("Cannot handle control request - no stdin available");
244
+ return;
245
+ }
246
+ const controller = new AbortController();
247
+ this.cancelControllers.set(request.request_id, controller);
248
+ try {
249
+ const response = await this.processControlRequest(request, controller.signal);
250
+ const controlResponse = {
251
+ type: "control_response",
252
+ response: {
253
+ subtype: "success",
254
+ request_id: request.request_id,
255
+ response
256
+ }
257
+ };
258
+ this.writeControlResponse(controlResponse);
259
+ } catch (error) {
260
+ const controlErrorResponse = {
261
+ type: "control_response",
262
+ response: {
263
+ subtype: "error",
264
+ request_id: request.request_id,
265
+ error: error instanceof Error ? error.message : String(error)
266
+ }
267
+ };
268
+ this.writeControlResponse(controlErrorResponse);
269
+ } finally {
270
+ this.cancelControllers.delete(request.request_id);
271
+ }
272
+ }
273
+ writeControlResponse(response) {
274
+ if (!this.childStdin || this.childStdin.destroyed || !this.childStdin.writable) {
275
+ return;
276
+ }
277
+ try {
278
+ this.childStdin.write(JSON.stringify(response) + "\n");
279
+ } catch (error) {
280
+ logger.debug("[ClaudeSDK] Failed to write control response:", error);
281
+ }
282
+ }
283
+ /**
284
+ * Handle control cancel requests
285
+ * Replicates the exact logic from the SDK's handleControlCancelRequest method
286
+ */
287
+ handleControlCancelRequest(request) {
288
+ const controller = this.cancelControllers.get(request.request_id);
289
+ if (controller) {
290
+ controller.abort();
291
+ this.cancelControllers.delete(request.request_id);
292
+ }
293
+ }
294
+ /**
295
+ * Process control requests based on subtype
296
+ * Replicates the exact logic from the SDK's processControlRequest method
297
+ */
298
+ async processControlRequest(request, signal) {
299
+ if (request.request.subtype === "can_use_tool") {
300
+ if (!this.canCallTool) {
301
+ throw new Error("canCallTool callback is not provided.");
302
+ }
303
+ return this.canCallTool(request.request.tool_name, request.request.input, {
304
+ signal,
305
+ requestId: request.request_id
306
+ });
307
+ }
308
+ throw new Error("Unsupported control request subtype: " + request.request.subtype);
309
+ }
310
+ /**
311
+ * Cleanup method to abort all pending control requests
312
+ */
313
+ cleanupControllers() {
314
+ for (const [requestId, controller] of this.cancelControllers.entries()) {
315
+ controller.abort();
316
+ this.cancelControllers.delete(requestId);
317
+ }
318
+ }
319
+ }
320
+ function query(config) {
321
+ const {
322
+ prompt,
323
+ options: {
324
+ allowedTools = [],
325
+ appendSystemPrompt,
326
+ customSystemPrompt,
327
+ cwd,
328
+ disallowedTools = [],
329
+ env,
330
+ executable = "node",
331
+ executableArgs = [],
332
+ maxTurns,
333
+ mcpServers,
334
+ pathToClaudeCodeExecutable = getDefaultClaudeCodePath(),
335
+ permissionMode,
336
+ continue: continueConversation,
337
+ resume,
338
+ model,
339
+ fallbackModel,
340
+ strictMcpConfig,
341
+ canCallTool,
342
+ settingsPath,
343
+ extraArgs = []
344
+ } = {}
345
+ } = config;
346
+ if (!process.env.CLAUDE_CODE_ENTRYPOINT) {
347
+ process.env.CLAUDE_CODE_ENTRYPOINT = "sdk-ts";
348
+ }
349
+ const args = [...extraArgs, "--output-format", "stream-json", "--verbose"];
350
+ if (customSystemPrompt) args.push("--system-prompt", customSystemPrompt);
351
+ if (appendSystemPrompt) args.push("--append-system-prompt", appendSystemPrompt);
352
+ if (maxTurns) args.push("--max-turns", maxTurns.toString());
353
+ if (model) args.push("--model", model);
354
+ if (canCallTool) {
355
+ if (typeof prompt === "string") {
356
+ throw new Error("canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable.");
357
+ }
358
+ args.push("--permission-prompt-tool", "stdio");
359
+ }
360
+ if (continueConversation) args.push("--continue");
361
+ if (resume) args.push("--resume", resume);
362
+ if (allowedTools.length > 0) args.push("--allowedTools", allowedTools.join(","));
363
+ if (disallowedTools.length > 0) args.push("--disallowedTools", disallowedTools.join(","));
364
+ if (mcpServers && Object.keys(mcpServers).length > 0) {
365
+ args.push("--mcp-config", JSON.stringify({ mcpServers }));
366
+ }
367
+ if (strictMcpConfig) args.push("--strict-mcp-config");
368
+ if (permissionMode) args.push("--permission-mode", permissionMode);
369
+ if (settingsPath) args.push("--settings", settingsPath);
370
+ if (fallbackModel) {
371
+ if (model && fallbackModel === model) {
372
+ throw new Error("Fallback model cannot be the same as the main model. Please specify a different model for fallbackModel option.");
373
+ }
374
+ args.push("--fallback-model", fallbackModel);
375
+ }
376
+ if (typeof prompt === "string") {
377
+ args.push("--print", prompt.trim());
378
+ } else {
379
+ args.push("--input-format", "stream-json");
380
+ }
381
+ const isJsFile = pathToClaudeCodeExecutable.endsWith(".js") || pathToClaudeCodeExecutable.endsWith(".cjs");
382
+ const isCommandOnly = pathToClaudeCodeExecutable === "claude";
383
+ if (!isCommandOnly && !existsSync(pathToClaudeCodeExecutable)) {
384
+ throw new ReferenceError(`Claude Code executable not found at ${pathToClaudeCodeExecutable}. Is options.pathToClaudeCodeExecutable set?`);
385
+ }
386
+ const spawnCommand = isJsFile ? executable : pathToClaudeCodeExecutable;
387
+ const spawnArgs = isJsFile ? [...executableArgs, pathToClaudeCodeExecutable, ...args] : args;
388
+ const spawnEnv = {
389
+ ...isCommandOnly ? getCleanEnv() : process.env,
390
+ ...env
391
+ };
392
+ logDebug(`Spawning Claude Code process: ${spawnCommand} ${spawnArgs.join(" ")} (using ${isCommandOnly ? "clean" : "normal"} env)`);
393
+ const child = spawn(spawnCommand, spawnArgs, {
394
+ cwd,
395
+ stdio: ["pipe", "pipe", "pipe"],
396
+ signal: config.options?.abort,
397
+ env: spawnEnv,
398
+ // Use shell on Windows for global binaries and command-only mode
399
+ shell: !isJsFile && process.platform === "win32",
400
+ windowsHide: true
401
+ });
402
+ let childStdin = null;
403
+ if (typeof prompt === "string") {
404
+ child.stdin.end();
405
+ } else {
406
+ streamToStdin(prompt, child.stdin, config.options?.abort);
407
+ childStdin = child.stdin;
408
+ }
409
+ if (process.env.DEBUG) {
410
+ child.stderr.on("data", (data) => {
411
+ console.error("Claude Code stderr:", data.toString());
412
+ });
413
+ }
414
+ const cleanup = () => {
415
+ if (!child.killed) {
416
+ child.kill("SIGTERM");
417
+ }
418
+ };
419
+ config.options?.abort?.addEventListener("abort", cleanup);
420
+ process.on("exit", cleanup);
421
+ const processExitPromise = new Promise((resolve) => {
422
+ child.on("close", (code) => {
423
+ if (config.options?.abort?.aborted) {
424
+ query2.setError(new AbortError("Claude Code process aborted by user"));
425
+ }
426
+ if (code !== 0) {
427
+ query2.setError(new Error(`Claude Code process exited with code ${code}`));
428
+ } else {
429
+ resolve();
430
+ }
431
+ });
432
+ });
433
+ const query2 = new Query(childStdin, child.stdout, processExitPromise, canCallTool);
434
+ child.on("error", (error) => {
435
+ if (config.options?.abort?.aborted) {
436
+ query2.setError(new AbortError("Claude Code process aborted by user"));
437
+ } else {
438
+ query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));
439
+ }
440
+ });
441
+ processExitPromise.finally(() => {
442
+ cleanup();
443
+ config.options?.abort?.removeEventListener("abort", cleanup);
444
+ if (process.env.CLAUDE_SDK_MCP_SERVERS) {
445
+ delete process.env.CLAUDE_SDK_MCP_SERVERS;
446
+ }
447
+ });
448
+ return query2;
449
+ }
450
+
451
+ class PushableAsyncIterable {
452
+ queue = [];
453
+ waiters = [];
454
+ isDone = false;
455
+ error = null;
456
+ started = false;
457
+ constructor() {
458
+ }
459
+ /**
460
+ * Push a value to the iterable
461
+ */
462
+ push(value) {
463
+ if (this.isDone) {
464
+ throw new Error("Cannot push to completed iterable");
465
+ }
466
+ if (this.error) {
467
+ throw this.error;
468
+ }
469
+ const waiter = this.waiters.shift();
470
+ if (waiter) {
471
+ waiter.resolve({ done: false, value });
472
+ } else {
473
+ this.queue.push(value);
474
+ }
475
+ }
476
+ /**
477
+ * Mark the iterable as complete
478
+ */
479
+ end() {
480
+ if (this.isDone) {
481
+ return;
482
+ }
483
+ this.isDone = true;
484
+ this.cleanup();
485
+ }
486
+ /**
487
+ * Set an error on the iterable
488
+ */
489
+ setError(err) {
490
+ if (this.isDone) {
491
+ return;
492
+ }
493
+ this.error = err;
494
+ this.isDone = true;
495
+ this.cleanup();
496
+ }
497
+ /**
498
+ * Cleanup waiting consumers
499
+ */
500
+ cleanup() {
501
+ while (this.waiters.length > 0) {
502
+ const waiter = this.waiters.shift();
503
+ if (this.error) {
504
+ waiter.reject(this.error);
505
+ } else {
506
+ waiter.resolve({ done: true, value: void 0 });
507
+ }
508
+ }
509
+ }
510
+ /**
511
+ * AsyncIterableIterator implementation
512
+ */
513
+ async next() {
514
+ if (this.queue.length > 0) {
515
+ return { done: false, value: this.queue.shift() };
516
+ }
517
+ if (this.isDone) {
518
+ if (this.error) {
519
+ throw this.error;
520
+ }
521
+ return { done: true, value: void 0 };
522
+ }
523
+ return new Promise((resolve, reject) => {
524
+ this.waiters.push({ resolve, reject });
525
+ });
526
+ }
527
+ /**
528
+ * AsyncIterableIterator return implementation
529
+ */
530
+ async return(_value) {
531
+ this.end();
532
+ return { done: true, value: void 0 };
533
+ }
534
+ /**
535
+ * AsyncIterableIterator throw implementation
536
+ */
537
+ async throw(e) {
538
+ this.setError(e instanceof Error ? e : new Error(String(e)));
539
+ throw this.error;
540
+ }
541
+ /**
542
+ * Make this iterable
543
+ */
544
+ [Symbol.asyncIterator]() {
545
+ if (this.started) {
546
+ throw new Error("PushableAsyncIterable can only be iterated once");
547
+ }
548
+ this.started = true;
549
+ return this;
550
+ }
551
+ /**
552
+ * Check if the iterable is done
553
+ */
554
+ get done() {
555
+ return this.isDone;
556
+ }
557
+ /**
558
+ * Check if the iterable has an error
559
+ */
560
+ get hasError() {
561
+ return this.error !== null;
562
+ }
563
+ /**
564
+ * Get the current queue size
565
+ */
566
+ get queueSize() {
567
+ return this.queue.length;
568
+ }
569
+ /**
570
+ * Get the number of waiting consumers
571
+ */
572
+ get waiterCount() {
573
+ return this.waiters.length;
574
+ }
575
+ }
576
+
577
+ function normalizeClaudeBackendError(error) {
578
+ const record = typeof error === "object" && error !== null ? error : null;
579
+ const text = formatDisplayMessage(error).trim();
580
+ const stderrText = record ? formatDisplayMessage(record.stderr).trim() : "";
581
+ const detailText = record ? formatDisplayMessage(record.detail).trim() : "";
582
+ const searchable = [text, stderrText, detailText].filter(Boolean).join("\n").trim();
583
+ return searchable || "Claude runtime backend exited unexpectedly";
584
+ }
585
+ function isRecord(value) {
586
+ return typeof value === "object" && value !== null && !Array.isArray(value);
587
+ }
588
+ function extractClaudeToolResultText(value) {
589
+ if (typeof value === "string") {
590
+ return value.length > 0 ? value : null;
591
+ }
592
+ if (Array.isArray(value)) {
593
+ const parts = value.map((item) => extractClaudeToolResultText(item)).filter((item) => Boolean(item));
594
+ return parts.length > 0 ? parts.join("") : null;
595
+ }
596
+ if (!isRecord(value)) {
597
+ return null;
598
+ }
599
+ if (typeof value.text === "string" && value.text.length > 0) {
600
+ return value.text;
601
+ }
602
+ if ("content" in value) {
603
+ return extractClaudeToolResultText(value.content);
604
+ }
605
+ return null;
606
+ }
607
+ function normalizeClaudeToolResultContent(value) {
608
+ if (typeof value === "string") {
609
+ return value;
610
+ }
611
+ const extractedText = extractClaudeToolResultText(value);
612
+ if (extractedText) {
613
+ return extractedText;
614
+ }
615
+ return value;
616
+ }
617
+ function createTimeoutError(timeoutMs) {
618
+ return new Error(`Claude response did not complete within ${timeoutMs}ms`);
619
+ }
620
+ const CLAUDE_RESPONSE_PROGRESS_POLL_MS = 1e3;
621
+ function normalizePermissionResult(input, decision) {
622
+ if (decision === "approved" || decision === "approved_for_session") {
623
+ return {
624
+ behavior: "allow",
625
+ updatedInput: isRecord(input) ? input : {}
626
+ };
627
+ }
628
+ return {
629
+ behavior: "deny",
630
+ message: decision === "denied" ? "The user denied this tool request." : "The tool request was aborted."
631
+ };
632
+ }
633
+ function getClaudeExecutablePath(command) {
634
+ if (command === "claude") {
635
+ return resolve(join(projectPath(), "scripts", "claude_remote_launcher.cjs"));
636
+ }
637
+ return command;
638
+ }
639
+ class ClaudeCodeBackend {
640
+ constructor(options) {
641
+ this.options = options;
642
+ }
643
+ listeners = /* @__PURE__ */ new Set();
644
+ toolNamesByCallId = /* @__PURE__ */ new Map();
645
+ runtimeSessionId = randomUUID();
646
+ messageStream = null;
647
+ queryInstance = null;
648
+ runtimeAbortController = null;
649
+ consumeTask = null;
650
+ activeResponse = null;
651
+ responseCompletionOutcome = null;
652
+ responseLastProgressAt = null;
653
+ disposed = false;
654
+ lastStatus = null;
655
+ onMessage(handler) {
656
+ this.listeners.add(handler);
657
+ }
658
+ offMessage(handler) {
659
+ this.listeners.delete(handler);
660
+ }
661
+ async startSession(initialPrompt) {
662
+ if (initialPrompt) {
663
+ await this.sendPrompt(this.runtimeSessionId, initialPrompt);
664
+ }
665
+ return { sessionId: this.runtimeSessionId };
666
+ }
667
+ async sendPrompt(_sessionId, prompt) {
668
+ if (this.disposed) {
669
+ throw new Error("Claude runtime backend has already been disposed");
670
+ }
671
+ if (this.activeResponse) {
672
+ throw new Error("Claude runtime backend is already processing a prompt");
673
+ }
674
+ await this.ensureQueryStarted();
675
+ this.responseCompletionOutcome = null;
676
+ this.activeResponse = new Future();
677
+ this.responseLastProgressAt = Date.now();
678
+ void this.activeResponse.promise.catch(() => {
679
+ });
680
+ this.emitStatus("running");
681
+ this.messageStream.push({
682
+ type: "user",
683
+ message: {
684
+ role: "user",
685
+ content: prompt
686
+ }
687
+ });
688
+ }
689
+ async cancel(_sessionId) {
690
+ if (!this.queryInstance) {
691
+ return;
692
+ }
693
+ try {
694
+ await this.queryInstance.interrupt();
695
+ } catch (error) {
696
+ logger.debug("[ClaudeRuntimeBackend] Error interrupting Claude query:", error);
697
+ }
698
+ }
699
+ async waitForResponseComplete(timeoutMs = 10 * 6e4) {
700
+ if (this.responseCompletionOutcome) {
701
+ const outcome = this.responseCompletionOutcome;
702
+ if (outcome.kind === "rejected") {
703
+ throw outcome.error;
704
+ }
705
+ return;
706
+ }
707
+ if (!this.activeResponse) {
708
+ return;
709
+ }
710
+ while (this.activeResponse) {
711
+ const elapsedSinceProgress = Date.now() - (this.responseLastProgressAt ?? Date.now());
712
+ const remainingMs = timeoutMs - elapsedSinceProgress;
713
+ if (remainingMs <= 0) {
714
+ const timeoutError = createTimeoutError(timeoutMs);
715
+ this.rejectActiveResponse(timeoutError);
716
+ throw timeoutError;
717
+ }
718
+ await Promise.race([
719
+ this.activeResponse.promise,
720
+ new Promise((resolve2) => {
721
+ setTimeout(resolve2, Math.min(CLAUDE_RESPONSE_PROGRESS_POLL_MS, remainingMs));
722
+ })
723
+ ]);
724
+ }
725
+ const completionOutcome = this.responseCompletionOutcome;
726
+ const rejectedError = completionOutcome && typeof completionOutcome === "object" && "error" in completionOutcome ? completionOutcome.error : null;
727
+ if (rejectedError) {
728
+ throw rejectedError;
729
+ }
730
+ }
731
+ async dispose() {
732
+ if (this.disposed) {
733
+ return;
734
+ }
735
+ this.disposed = true;
736
+ const activeQuery = this.queryInstance;
737
+ this.rejectActiveResponse(new Error("Claude runtime backend disposed"));
738
+ this.messageStream?.end();
739
+ this.runtimeAbortController?.abort();
740
+ if (activeQuery && typeof activeQuery.return === "function") {
741
+ try {
742
+ await activeQuery.return();
743
+ } catch (error) {
744
+ logger.debug("[ClaudeRuntimeBackend] Error closing Claude query iterator:", error);
745
+ }
746
+ }
747
+ try {
748
+ await this.consumeTask;
749
+ } catch (error) {
750
+ logger.debug("[ClaudeRuntimeBackend] Error while disposing backend:", error);
751
+ } finally {
752
+ this.queryInstance = null;
753
+ this.messageStream = null;
754
+ this.runtimeAbortController = null;
755
+ this.consumeTask = null;
756
+ this.toolNamesByCallId.clear();
757
+ this.emitStatus("stopped");
758
+ }
759
+ }
760
+ emit(message) {
761
+ for (const listener of this.listeners) {
762
+ listener(message);
763
+ }
764
+ }
765
+ emitStatus(status, detail) {
766
+ if (this.lastStatus?.status === status && this.lastStatus.detail === detail) {
767
+ return;
768
+ }
769
+ const message = {
770
+ type: "status",
771
+ status,
772
+ ...detail ? { detail } : {}
773
+ };
774
+ this.lastStatus = message;
775
+ this.emit(message);
776
+ }
777
+ async ensureQueryStarted() {
778
+ if (this.queryInstance) {
779
+ return;
780
+ }
781
+ this.emitStatus("starting");
782
+ this.runtimeAbortController = new AbortController();
783
+ this.messageStream = new PushableAsyncIterable();
784
+ this.queryInstance = query({
785
+ prompt: this.messageStream,
786
+ options: {
787
+ cwd: this.options.cwd,
788
+ env: this.options.env,
789
+ allowedTools: this.options.allowedTools,
790
+ appendSystemPrompt: this.options.appendSystemPrompt,
791
+ customSystemPrompt: this.options.customSystemPrompt,
792
+ disallowedTools: this.options.disallowedTools,
793
+ extraArgs: this.options.args,
794
+ fallbackModel: this.options.fallbackModel,
795
+ mcpServers: this.options.mcpServers,
796
+ model: this.options.model,
797
+ pathToClaudeCodeExecutable: getClaudeExecutablePath(this.options.command),
798
+ permissionMode: this.options.permissionMode,
799
+ settingsPath: this.options.settingsPath,
800
+ canCallTool: this.options.permissionHandler ? async (toolName, input, requestOptions) => {
801
+ const requestId = requestOptions.requestId ?? randomUUID();
802
+ this.emit({
803
+ type: "permission-request",
804
+ id: requestId,
805
+ reason: `Claude wants to use ${toolName}`,
806
+ payload: {
807
+ toolName,
808
+ input
809
+ }
810
+ });
811
+ const decision = await this.options.permissionHandler.handleToolCall(requestId, toolName, input);
812
+ this.emit({
813
+ type: "permission-response",
814
+ id: requestId,
815
+ approved: decision.decision === "approved" || decision.decision === "approved_for_session"
816
+ });
817
+ return normalizePermissionResult(input, decision.decision);
818
+ } : void 0,
819
+ abort: this.runtimeAbortController.signal
820
+ }
821
+ });
822
+ this.consumeTask = this.consumeMessages(this.queryInstance);
823
+ }
824
+ async consumeMessages(activeQuery) {
825
+ try {
826
+ for await (const message of activeQuery) {
827
+ this.handleMessage(message);
828
+ }
829
+ } catch (error) {
830
+ const aborted = this.runtimeAbortController?.signal.aborted === true;
831
+ if (!aborted) {
832
+ const detail = normalizeClaudeBackendError(error);
833
+ this.emitStatus("error", detail);
834
+ this.rejectActiveResponse(new Error(detail));
835
+ }
836
+ } finally {
837
+ if (!this.disposed && this.activeResponse) {
838
+ const detail = "Claude runtime backend stopped before completing the response";
839
+ this.emitStatus("error", detail);
840
+ this.rejectActiveResponse(new Error(detail));
841
+ }
842
+ if (!this.disposed) {
843
+ this.queryInstance = null;
844
+ this.messageStream = null;
845
+ this.runtimeAbortController = null;
846
+ this.consumeTask = null;
847
+ this.emitStatus("stopped");
848
+ }
849
+ }
850
+ }
851
+ handleMessage(message) {
852
+ this.markResponseProgress();
853
+ switch (message.type) {
854
+ case "system":
855
+ this.handleSystemMessage(message);
856
+ return;
857
+ case "assistant":
858
+ this.handleAssistantMessage(message);
859
+ return;
860
+ case "user":
861
+ this.handleUserMessage(message);
862
+ return;
863
+ case "result":
864
+ this.handleResultMessage(message);
865
+ return;
866
+ default:
867
+ return;
868
+ }
869
+ }
870
+ handleSystemMessage(message) {
871
+ if (message.subtype === "init") {
872
+ this.emitStatus("running");
873
+ this.emit({
874
+ type: "event",
875
+ name: "session-init",
876
+ payload: {
877
+ sessionId: message.session_id,
878
+ cwd: message.cwd,
879
+ model: message.model,
880
+ tools: message.tools
881
+ }
882
+ });
883
+ }
884
+ }
885
+ handleAssistantMessage(message) {
886
+ for (const block of message.message.content ?? []) {
887
+ if (block.type === "text" && typeof block.text === "string" && block.text.length > 0) {
888
+ this.emit({
889
+ type: "model-output",
890
+ textDelta: block.text
891
+ });
892
+ continue;
893
+ }
894
+ if (block.type === "thinking") {
895
+ const thinkingText = isRecord(block) && typeof block.thinking === "string" ? block.thinking : "";
896
+ if (thinkingText) {
897
+ this.emit({
898
+ type: "event",
899
+ name: "thinking",
900
+ payload: { text: thinkingText }
901
+ });
902
+ }
903
+ continue;
904
+ }
905
+ if (block.type === "tool_use" && block.id && block.name) {
906
+ this.toolNamesByCallId.set(block.id, block.name);
907
+ this.emit({
908
+ type: "tool-call",
909
+ toolName: block.name,
910
+ args: isRecord(block.input) ? block.input : {},
911
+ callId: block.id
912
+ });
913
+ }
914
+ }
915
+ }
916
+ handleUserMessage(message) {
917
+ const content = Array.isArray(message.message.content) ? message.message.content : [];
918
+ for (const block of content) {
919
+ if (block.type !== "tool_result" || !block.tool_use_id) {
920
+ continue;
921
+ }
922
+ const toolName = this.toolNamesByCallId.get(block.tool_use_id) ?? "unknown";
923
+ this.emit({
924
+ type: "tool-result",
925
+ toolName,
926
+ result: normalizeClaudeToolResultContent(block.content),
927
+ callId: block.tool_use_id
928
+ });
929
+ if (toolName === "Bash" && isRecord(message.tool_use_result)) {
930
+ const toolResult = message.tool_use_result;
931
+ const stdout = formatDisplayMessage(toolResult.stdout).trim();
932
+ const stderr = formatDisplayMessage(toolResult.stderr).trim();
933
+ const combined = [stdout, stderr].filter(Boolean).join("\n");
934
+ if (combined) {
935
+ this.emit({
936
+ type: "terminal-output",
937
+ data: combined,
938
+ callId: block.tool_use_id
939
+ });
940
+ }
941
+ }
942
+ }
943
+ }
944
+ handleResultMessage(message) {
945
+ if (message.usage) {
946
+ this.emit({
947
+ type: "token-count",
948
+ ...message.usage,
949
+ duration_ms: message.duration_ms,
950
+ duration_api_ms: message.duration_api_ms,
951
+ total_cost_usd: message.total_cost_usd,
952
+ session_id: message.session_id
953
+ });
954
+ }
955
+ if (message.is_error) {
956
+ const detail = typeof message.result === "string" && message.result.trim().length > 0 ? message.result : message.subtype;
957
+ this.emitStatus("error", detail);
958
+ this.rejectActiveResponse(new Error(detail));
959
+ return;
960
+ }
961
+ this.emitStatus("idle");
962
+ this.resolveActiveResponse();
963
+ }
964
+ resolveActiveResponse() {
965
+ this.responseCompletionOutcome = { kind: "resolved" };
966
+ this.responseLastProgressAt = null;
967
+ if (!this.activeResponse) {
968
+ return;
969
+ }
970
+ const active = this.activeResponse;
971
+ this.activeResponse = null;
972
+ active.resolve(void 0);
973
+ }
974
+ rejectActiveResponse(error) {
975
+ this.responseCompletionOutcome = { kind: "rejected", error };
976
+ this.responseLastProgressAt = null;
977
+ if (!this.activeResponse) {
978
+ return;
979
+ }
980
+ const active = this.activeResponse;
981
+ this.activeResponse = null;
982
+ active.reject(error);
983
+ }
984
+ markResponseProgress() {
985
+ if (!this.activeResponse) {
986
+ return;
987
+ }
988
+ this.responseLastProgressAt = Date.now();
989
+ }
990
+ }
991
+
992
+ function mapToClaudeMode(mode) {
993
+ const codexToClaudeMap = {
994
+ "yolo": "bypassPermissions",
995
+ "safe-yolo": "default",
996
+ "read-only": "default"
997
+ };
998
+ return codexToClaudeMap[mode] ?? mode;
999
+ }
1000
+
1001
+ function defaultClaudeCommand() {
1002
+ return process.env.HAPPY_CLAUDE_COMMAND ?? process.env.HAPPY_CLAUDE_ACP_COMMAND ?? "claude";
1003
+ }
1004
+ function appendStringFlag(args, flag, value) {
1005
+ if (value && value.trim().length > 0) {
1006
+ args.push(flag, value);
1007
+ }
1008
+ }
1009
+ function appendListFlag(args, flag, values) {
1010
+ if (values && values.length > 0) {
1011
+ args.push(flag, values.join(","));
1012
+ }
1013
+ }
1014
+ function normalizeClaudePassthroughArgs(options) {
1015
+ const sourceArgs = options.args ?? options.baseArgs ?? [];
1016
+ return sourceArgs.filter((arg) => arg !== "--experimental-acp");
1017
+ }
1018
+ function resolveClaudeCliArgs(options) {
1019
+ const args = [
1020
+ "--output-format",
1021
+ "stream-json",
1022
+ "--verbose",
1023
+ "--input-format",
1024
+ "stream-json",
1025
+ ...normalizeClaudePassthroughArgs(options)
1026
+ ];
1027
+ if (options.permissionHandler) {
1028
+ args.push("--permission-prompt-tool", "stdio");
1029
+ }
1030
+ appendStringFlag(args, "--system-prompt", options.customSystemPrompt);
1031
+ appendStringFlag(args, "--append-system-prompt", options.appendSystemPrompt);
1032
+ appendStringFlag(args, "--model", options.model);
1033
+ appendStringFlag(args, "--fallback-model", options.fallbackModel);
1034
+ appendListFlag(args, "--allowedTools", options.allowedTools);
1035
+ appendListFlag(args, "--disallowedTools", options.disallowedTools);
1036
+ appendStringFlag(args, "--settings", options.settingsPath);
1037
+ if (options.permissionMode) {
1038
+ args.push("--permission-mode", mapToClaudeMode(options.permissionMode));
1039
+ }
1040
+ return args;
1041
+ }
1042
+ function createClaudeBackend(options) {
1043
+ const command = options.command ?? defaultClaudeCommand();
1044
+ const args = resolveClaudeCliArgs(options);
1045
+ return {
1046
+ backend: new ClaudeCodeBackend({
1047
+ cwd: options.cwd,
1048
+ env: {
1049
+ ...options.env,
1050
+ NODE_ENV: "production"
1051
+ },
1052
+ command,
1053
+ args: normalizeClaudePassthroughArgs(options),
1054
+ model: options.model,
1055
+ fallbackModel: options.fallbackModel,
1056
+ permissionMode: options.permissionMode ? mapToClaudeMode(options.permissionMode) : void 0,
1057
+ customSystemPrompt: options.customSystemPrompt,
1058
+ appendSystemPrompt: options.appendSystemPrompt,
1059
+ allowedTools: options.allowedTools,
1060
+ disallowedTools: options.disallowedTools,
1061
+ settingsPath: options.settingsPath,
1062
+ mcpServers: options.mcpServers,
1063
+ permissionHandler: options.permissionHandler
1064
+ }),
1065
+ command,
1066
+ args
1067
+ };
1068
+ }
1069
+ function registerClaudeAgent() {
1070
+ agentRegistry.register("claude", (opts) => createClaudeBackend(opts).backend);
1071
+ }
1072
+
1073
+ export { AbortError as A, PushableAsyncIterable as P, createClaudeBackend as c, mapToClaudeMode as m, query as q, registerClaudeAgent as r };