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