happy-imou-cloud 2.0.13 → 2.0.14

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 (30) hide show
  1. package/dist/BaseReasoningProcessor-CB7luAdI.mjs +320 -0
  2. package/dist/BaseReasoningProcessor-Cwhs4PwS.cjs +323 -0
  3. package/dist/ProviderSelectionHandler-CmDe9yDh.cjs +265 -0
  4. package/dist/ProviderSelectionHandler-DnnCwXqU.mjs +261 -0
  5. package/dist/{api-D1meoL-9.mjs → api-Bad69WzY.mjs} +2 -2
  6. package/dist/{api-DH5-IqeM.cjs → api-CaqY_2x_.cjs} +2 -2
  7. package/dist/{command-CMvWClny.mjs → command-D9ZaQZQN.mjs} +4 -3
  8. package/dist/{command-Ch8Dgidj.cjs → command-DkVbAV9p.cjs} +4 -3
  9. package/dist/{index-Cxrx9m5D.mjs → index-naa51zV7.mjs} +1102 -50
  10. package/dist/{index-CryJfCh5.cjs → index-oxTpdQx2.cjs} +1106 -50
  11. package/dist/index.cjs +5 -4
  12. package/dist/index.mjs +5 -4
  13. package/dist/lib.cjs +1 -1
  14. package/dist/lib.mjs +1 -1
  15. package/dist/{persistence-9Iu0wGNM.mjs → persistence-4BmGePWc.mjs} +1 -1
  16. package/dist/{persistence-Bl3FYvwd.cjs → persistence-Byr0hWCR.cjs} +1 -1
  17. package/dist/{registerKillSessionHandler-BjkY-oUn.cjs → registerKillSessionHandler-CodtiIoq.cjs} +549 -4
  18. package/dist/{registerKillSessionHandler-BElGmD1E.mjs → registerKillSessionHandler-HO4ql8g-.mjs} +541 -5
  19. package/dist/{runClaude-CDZxAF3l.cjs → runClaude-C3UNcGqk.cjs} +583 -747
  20. package/dist/{runClaude-D7dF4RDM.mjs → runClaude-Ev-A-kLN.mjs} +575 -738
  21. package/dist/{runCodex-DnGz1XES.mjs → runCodex-BwFOTxMW.mjs} +9 -215
  22. package/dist/{runCodex-Cik8VzFs.cjs → runCodex-CNM6wz69.cjs} +20 -226
  23. package/dist/{runGemini-B8tXMHeL.mjs → runGemini-CXctVflO.mjs} +8 -7
  24. package/dist/{runGemini-BM2BQ4I7.cjs → runGemini-DqfqSBsP.cjs} +16 -15
  25. package/package.json +1 -1
  26. package/scripts/release-smoke.mjs +6 -5
  27. package/dist/ConversationHistory-V3VLmjJf.cjs +0 -868
  28. package/dist/ConversationHistory-_ciJNIgH.mjs +0 -856
  29. package/dist/createKeepAliveController-C5cQlDRr.mjs +0 -51
  30. package/dist/createKeepAliveController-DO8H6d5E.cjs +0 -54
@@ -1,6 +1,6 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, S as SigningBootstrapRequiredError, j as SIGNING_BOOTSTRAP_REQUIRED_MESSAGE, k as encodeBase64Url, f as delay, m as buildClientHeaders, n as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, o as getLatestDaemonLog } from './api-D1meoL-9.mjs';
3
- import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-9Iu0wGNM.mjs';
2
+ import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, S as SigningBootstrapRequiredError, j as SIGNING_BOOTSTRAP_REQUIRED_MESSAGE, k as encodeBase64Url, f as delay, m as buildClientHeaders, n as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, o as getLatestDaemonLog } from './api-Bad69WzY.mjs';
3
+ import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-4BmGePWc.mjs';
4
4
  import { z } from 'zod';
5
5
  import fs, { writeFile as writeFile$1, rename, unlink as unlink$1 } from 'fs/promises';
6
6
  import os, { homedir } from 'os';
@@ -20,7 +20,7 @@ import { spawn, execSync, exec } from 'child_process';
20
20
  import { dirname, resolve, join as join$1 } from 'path';
21
21
  import { fileURLToPath } from 'url';
22
22
  import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync, chmodSync, unlinkSync as unlinkSync$1, mkdirSync } from 'fs';
23
- import { execFileSync, spawn as spawn$2 } from 'node:child_process';
23
+ import { execFileSync, spawn as spawn$2, execSync as execSync$1 } from 'node:child_process';
24
24
  import psList from 'ps-list';
25
25
  import spawn$1 from 'cross-spawn';
26
26
  import fs$1, { existsSync, readFileSync, readdirSync, statSync, unlinkSync, rmSync, mkdirSync as mkdirSync$1, realpathSync } from 'node:fs';
@@ -31,6 +31,7 @@ import { createInterface } from 'node:readline';
31
31
  import { createServer } from 'http';
32
32
  import { promisify } from 'util';
33
33
  import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
34
+ import { fileURLToPath as fileURLToPath$1 } from 'node:url';
34
35
  import 'node:events';
35
36
 
36
37
  async function openBrowser(url) {
@@ -672,9 +673,9 @@ function setupCleanupHandlers() {
672
673
  });
673
674
  }
674
675
 
675
- const __dirname$1 = dirname(fileURLToPath(import.meta.url));
676
+ const __dirname$2 = dirname(fileURLToPath(import.meta.url));
676
677
  function projectPath() {
677
- const path = resolve(__dirname$1, "..");
678
+ const path = resolve(__dirname$2, "..");
678
679
  return path;
679
680
  }
680
681
 
@@ -4946,7 +4947,7 @@ class ClaudeTransport extends DefaultTransport {
4946
4947
  return 600;
4947
4948
  }
4948
4949
  }
4949
- const claudeTransport = new ClaudeTransport();
4950
+ new ClaudeTransport();
4950
4951
 
4951
4952
  class CursorTransport extends DefaultTransport {
4952
4953
  constructor() {
@@ -4984,7 +4985,7 @@ function appendToolOutput(existing, next) {
4984
4985
  }
4985
4986
  return `${existing}${next}`;
4986
4987
  }
4987
- function isRecord(value) {
4988
+ function isRecord$1(value) {
4988
4989
  return typeof value === "object" && value !== null && !Array.isArray(value);
4989
4990
  }
4990
4991
  function hasMeaningfulContent(value) {
@@ -4997,7 +4998,7 @@ function hasMeaningfulContent(value) {
4997
4998
  if (Array.isArray(value)) {
4998
4999
  return value.length > 0;
4999
5000
  }
5000
- if (isRecord(value)) {
5001
+ if (isRecord$1(value)) {
5001
5002
  return Object.keys(value).length > 0;
5002
5003
  }
5003
5004
  return true;
@@ -5020,7 +5021,7 @@ function looksLikeToolMetadata(record) {
5020
5021
  const nestedKeys = ["input", "toolCall", "arguments", "content"];
5021
5022
  for (const key of nestedKeys) {
5022
5023
  const nested = record[key];
5023
- if (isRecord(nested) && looksLikeToolMetadata(nested)) {
5024
+ if (isRecord$1(nested) && looksLikeToolMetadata(nested)) {
5024
5025
  return true;
5025
5026
  }
5026
5027
  }
@@ -5034,7 +5035,7 @@ function extractToolOutputChunk(content) {
5034
5035
  const parts = content.map((item) => extractToolOutputChunk(item)).filter((item) => Boolean(item));
5035
5036
  return parts.length > 0 ? parts.join("") : null;
5036
5037
  }
5037
- if (!isRecord(content)) {
5038
+ if (!isRecord$1(content)) {
5038
5039
  return null;
5039
5040
  }
5040
5041
  const outputKeys = ["stdout", "stderr", "output", "text", "message", "data", "error", "reason"];
@@ -5062,7 +5063,7 @@ function mergeStreamedOutputWithResult(content, streamedOutput) {
5062
5063
  if (!hasMeaningfulContent(content)) {
5063
5064
  return streamedOutput;
5064
5065
  }
5065
- if (isRecord(content)) {
5066
+ if (isRecord$1(content)) {
5066
5067
  const hasStructuredOutput = ["stdout", "stderr", "output", "text", "message", "data"].some((key) => key in content);
5067
5068
  if (!hasStructuredOutput) {
5068
5069
  return {
@@ -7354,6 +7355,1051 @@ function registerCodexAgent() {
7354
7355
  agentRegistry.register("codex", (opts) => createCodexBackend(opts).backend);
7355
7356
  }
7356
7357
 
7358
+ class Stream {
7359
+ constructor(returned) {
7360
+ this.returned = returned;
7361
+ }
7362
+ queue = [];
7363
+ readResolve;
7364
+ readReject;
7365
+ isDone = false;
7366
+ hasError;
7367
+ started = false;
7368
+ /**
7369
+ * Implements async iterable protocol
7370
+ */
7371
+ [Symbol.asyncIterator]() {
7372
+ if (this.started) {
7373
+ throw new Error("Stream can only be iterated once");
7374
+ }
7375
+ this.started = true;
7376
+ return this;
7377
+ }
7378
+ /**
7379
+ * Gets the next value from the stream
7380
+ */
7381
+ async next() {
7382
+ if (this.queue.length > 0) {
7383
+ return Promise.resolve({
7384
+ done: false,
7385
+ value: this.queue.shift()
7386
+ });
7387
+ }
7388
+ if (this.isDone) {
7389
+ return Promise.resolve({ done: true, value: void 0 });
7390
+ }
7391
+ if (this.hasError) {
7392
+ return Promise.reject(this.hasError);
7393
+ }
7394
+ return new Promise((resolve, reject) => {
7395
+ this.readResolve = resolve;
7396
+ this.readReject = reject;
7397
+ });
7398
+ }
7399
+ /**
7400
+ * Adds a value to the stream
7401
+ */
7402
+ enqueue(value) {
7403
+ if (this.readResolve) {
7404
+ const resolve = this.readResolve;
7405
+ this.readResolve = void 0;
7406
+ this.readReject = void 0;
7407
+ resolve({ done: false, value });
7408
+ } else {
7409
+ this.queue.push(value);
7410
+ }
7411
+ }
7412
+ /**
7413
+ * Marks the stream as complete
7414
+ */
7415
+ done() {
7416
+ this.isDone = true;
7417
+ if (this.readResolve) {
7418
+ const resolve = this.readResolve;
7419
+ this.readResolve = void 0;
7420
+ this.readReject = void 0;
7421
+ resolve({ done: true, value: void 0 });
7422
+ }
7423
+ }
7424
+ /**
7425
+ * Propagates an error through the stream
7426
+ */
7427
+ error(error) {
7428
+ this.hasError = error;
7429
+ if (this.readReject) {
7430
+ const reject = this.readReject;
7431
+ this.readResolve = void 0;
7432
+ this.readReject = void 0;
7433
+ reject(error);
7434
+ }
7435
+ }
7436
+ /**
7437
+ * Implements async iterator cleanup
7438
+ */
7439
+ async return() {
7440
+ this.isDone = true;
7441
+ if (this.returned) {
7442
+ this.returned();
7443
+ }
7444
+ return Promise.resolve({ done: true, value: void 0 });
7445
+ }
7446
+ }
7447
+
7448
+ class AbortError extends Error {
7449
+ constructor(message) {
7450
+ super(message);
7451
+ this.name = "AbortError";
7452
+ }
7453
+ }
7454
+
7455
+ const __filename$1 = fileURLToPath$1(import.meta.url);
7456
+ const __dirname$1 = join(__filename$1, "..");
7457
+ function getGlobalClaudeVersion() {
7458
+ try {
7459
+ const cleanEnv = getCleanEnv();
7460
+ const output = execSync$1("claude --version", {
7461
+ encoding: "utf8",
7462
+ stdio: ["pipe", "pipe", "pipe"],
7463
+ cwd: homedir$1(),
7464
+ env: cleanEnv
7465
+ }).trim();
7466
+ const match = output.match(/(\d+\.\d+\.\d+)/);
7467
+ logger.debug(`[Claude SDK] Global claude --version output: ${output}`);
7468
+ return match ? match[1] : null;
7469
+ } catch {
7470
+ return null;
7471
+ }
7472
+ }
7473
+ function getCleanEnv() {
7474
+ const env = { ...process.env };
7475
+ const cwd = process.cwd();
7476
+ const pathSep = process.platform === "win32" ? ";" : ":";
7477
+ const pathKey = process.platform === "win32" ? "Path" : "PATH";
7478
+ const actualPathKey = Object.keys(env).find((k) => k.toLowerCase() === "path") || pathKey;
7479
+ if (env[actualPathKey]) {
7480
+ const cleanPath = env[actualPathKey].split(pathSep).filter((p) => {
7481
+ const normalizedP = p.replace(/\\/g, "/").toLowerCase();
7482
+ const normalizedCwd = cwd.replace(/\\/g, "/").toLowerCase();
7483
+ return !normalizedP.startsWith(normalizedCwd);
7484
+ }).join(pathSep);
7485
+ env[actualPathKey] = cleanPath;
7486
+ logger.debug(`[Claude SDK] Cleaned PATH, removed local paths from: ${cwd}`);
7487
+ }
7488
+ if (isBun()) {
7489
+ Object.keys(env).forEach((key) => {
7490
+ if (key.startsWith("BUN_")) {
7491
+ delete env[key];
7492
+ }
7493
+ });
7494
+ logger.debug("[Claude SDK] Removed Bun-specific environment variables for Node.js compatibility");
7495
+ }
7496
+ return env;
7497
+ }
7498
+ function findGlobalClaudePath() {
7499
+ const homeDir = homedir$1();
7500
+ const cleanEnv = getCleanEnv();
7501
+ try {
7502
+ execSync$1("claude --version", {
7503
+ encoding: "utf8",
7504
+ stdio: ["pipe", "pipe", "pipe"],
7505
+ cwd: homeDir,
7506
+ env: cleanEnv
7507
+ });
7508
+ logger.debug("[Claude SDK] Global claude command available (checked with clean PATH)");
7509
+ return "claude";
7510
+ } catch {
7511
+ }
7512
+ if (process.platform !== "win32") {
7513
+ try {
7514
+ const result = execSync$1("which claude", {
7515
+ encoding: "utf8",
7516
+ stdio: ["pipe", "pipe", "pipe"],
7517
+ cwd: homeDir,
7518
+ env: cleanEnv
7519
+ }).trim();
7520
+ if (result && existsSync(result)) {
7521
+ logger.debug(`[Claude SDK] Found global claude path via which: ${result}`);
7522
+ return result;
7523
+ }
7524
+ } catch {
7525
+ }
7526
+ }
7527
+ return null;
7528
+ }
7529
+ function getDefaultClaudeCodePath() {
7530
+ const nodeModulesPath = join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
7531
+ if (process.env.HAPPY_CLAUDE_PATH) {
7532
+ logger.debug(`[Claude SDK] Using HAPPY_CLAUDE_PATH: ${process.env.HAPPY_CLAUDE_PATH}`);
7533
+ return process.env.HAPPY_CLAUDE_PATH;
7534
+ }
7535
+ if (process.env.HAPPY_USE_BUNDLED_CLAUDE === "1") {
7536
+ logger.debug(`[Claude SDK] Forced bundled version: ${nodeModulesPath}`);
7537
+ return nodeModulesPath;
7538
+ }
7539
+ const globalPath = findGlobalClaudePath();
7540
+ if (!globalPath) {
7541
+ logger.debug(`[Claude SDK] No global claude found, using bundled: ${nodeModulesPath}`);
7542
+ return nodeModulesPath;
7543
+ }
7544
+ const globalVersion = getGlobalClaudeVersion();
7545
+ logger.debug(`[Claude SDK] Global version: ${globalVersion || "unknown"}`);
7546
+ if (!globalVersion) {
7547
+ logger.debug(`[Claude SDK] Cannot compare versions, using global: ${globalPath}`);
7548
+ return globalPath;
7549
+ }
7550
+ return globalPath;
7551
+ }
7552
+ function logDebug(message) {
7553
+ if (process.env.DEBUG) {
7554
+ logger.debug(message);
7555
+ console.log(message);
7556
+ }
7557
+ }
7558
+ async function streamToStdin(stream, stdin, abort) {
7559
+ for await (const message of stream) {
7560
+ if (abort?.aborted) break;
7561
+ stdin.write(JSON.stringify(message) + "\n");
7562
+ }
7563
+ stdin.end();
7564
+ }
7565
+
7566
+ class Query {
7567
+ constructor(childStdin, childStdout, processExitPromise, canCallTool) {
7568
+ this.childStdin = childStdin;
7569
+ this.childStdout = childStdout;
7570
+ this.processExitPromise = processExitPromise;
7571
+ this.canCallTool = canCallTool;
7572
+ this.readMessages();
7573
+ this.sdkMessages = this.readSdkMessages();
7574
+ }
7575
+ pendingControlResponses = /* @__PURE__ */ new Map();
7576
+ cancelControllers = /* @__PURE__ */ new Map();
7577
+ sdkMessages;
7578
+ inputStream = new Stream();
7579
+ canCallTool;
7580
+ /**
7581
+ * Set an error on the stream
7582
+ */
7583
+ setError(error) {
7584
+ this.inputStream.error(error);
7585
+ }
7586
+ /**
7587
+ * AsyncIterableIterator implementation
7588
+ */
7589
+ next(...args) {
7590
+ return this.sdkMessages.next(...args);
7591
+ }
7592
+ return(value) {
7593
+ if (this.sdkMessages.return) {
7594
+ return this.sdkMessages.return(value);
7595
+ }
7596
+ return Promise.resolve({ done: true, value: void 0 });
7597
+ }
7598
+ throw(e) {
7599
+ if (this.sdkMessages.throw) {
7600
+ return this.sdkMessages.throw(e);
7601
+ }
7602
+ return Promise.reject(e);
7603
+ }
7604
+ [Symbol.asyncIterator]() {
7605
+ return this.sdkMessages;
7606
+ }
7607
+ /**
7608
+ * Read messages from Claude process stdout
7609
+ */
7610
+ async readMessages() {
7611
+ const rl = createInterface({ input: this.childStdout });
7612
+ try {
7613
+ for await (const line of rl) {
7614
+ if (line.trim()) {
7615
+ try {
7616
+ const message = JSON.parse(line);
7617
+ if (message.type === "control_response") {
7618
+ const controlResponse = message;
7619
+ const handler = this.pendingControlResponses.get(controlResponse.response.request_id);
7620
+ if (handler) {
7621
+ handler(controlResponse.response);
7622
+ }
7623
+ continue;
7624
+ } else if (message.type === "control_request") {
7625
+ await this.handleControlRequest(message);
7626
+ continue;
7627
+ } else if (message.type === "control_cancel_request") {
7628
+ this.handleControlCancelRequest(message);
7629
+ continue;
7630
+ }
7631
+ this.inputStream.enqueue(message);
7632
+ } catch (e) {
7633
+ logger.debug(line);
7634
+ }
7635
+ }
7636
+ }
7637
+ await this.processExitPromise;
7638
+ } catch (error) {
7639
+ this.inputStream.error(error);
7640
+ } finally {
7641
+ this.inputStream.done();
7642
+ this.cleanupControllers();
7643
+ rl.close();
7644
+ }
7645
+ }
7646
+ /**
7647
+ * Async generator for SDK messages
7648
+ */
7649
+ async *readSdkMessages() {
7650
+ for await (const message of this.inputStream) {
7651
+ yield message;
7652
+ }
7653
+ }
7654
+ /**
7655
+ * Send interrupt request to Claude
7656
+ */
7657
+ async interrupt() {
7658
+ if (!this.childStdin) {
7659
+ throw new Error("Interrupt requires --input-format stream-json");
7660
+ }
7661
+ await this.request({
7662
+ subtype: "interrupt"
7663
+ }, this.childStdin);
7664
+ }
7665
+ /**
7666
+ * Send control request to Claude process
7667
+ */
7668
+ request(request, childStdin) {
7669
+ const requestId = Math.random().toString(36).substring(2, 15);
7670
+ const sdkRequest = {
7671
+ request_id: requestId,
7672
+ type: "control_request",
7673
+ request
7674
+ };
7675
+ return new Promise((resolve, reject) => {
7676
+ this.pendingControlResponses.set(requestId, (response) => {
7677
+ if (response.subtype === "success") {
7678
+ resolve(response);
7679
+ } else {
7680
+ reject(new Error(response.error));
7681
+ }
7682
+ });
7683
+ childStdin.write(JSON.stringify(sdkRequest) + "\n");
7684
+ });
7685
+ }
7686
+ /**
7687
+ * Handle incoming control requests for tool permissions
7688
+ * Replicates the exact logic from the SDK's handleControlRequest method
7689
+ */
7690
+ async handleControlRequest(request) {
7691
+ if (!this.childStdin) {
7692
+ logDebug("Cannot handle control request - no stdin available");
7693
+ return;
7694
+ }
7695
+ const controller = new AbortController();
7696
+ this.cancelControllers.set(request.request_id, controller);
7697
+ try {
7698
+ const response = await this.processControlRequest(request, controller.signal);
7699
+ const controlResponse = {
7700
+ type: "control_response",
7701
+ response: {
7702
+ subtype: "success",
7703
+ request_id: request.request_id,
7704
+ response
7705
+ }
7706
+ };
7707
+ this.childStdin.write(JSON.stringify(controlResponse) + "\n");
7708
+ } catch (error) {
7709
+ const controlErrorResponse = {
7710
+ type: "control_response",
7711
+ response: {
7712
+ subtype: "error",
7713
+ request_id: request.request_id,
7714
+ error: error instanceof Error ? error.message : String(error)
7715
+ }
7716
+ };
7717
+ this.childStdin.write(JSON.stringify(controlErrorResponse) + "\n");
7718
+ } finally {
7719
+ this.cancelControllers.delete(request.request_id);
7720
+ }
7721
+ }
7722
+ /**
7723
+ * Handle control cancel requests
7724
+ * Replicates the exact logic from the SDK's handleControlCancelRequest method
7725
+ */
7726
+ handleControlCancelRequest(request) {
7727
+ const controller = this.cancelControllers.get(request.request_id);
7728
+ if (controller) {
7729
+ controller.abort();
7730
+ this.cancelControllers.delete(request.request_id);
7731
+ }
7732
+ }
7733
+ /**
7734
+ * Process control requests based on subtype
7735
+ * Replicates the exact logic from the SDK's processControlRequest method
7736
+ */
7737
+ async processControlRequest(request, signal) {
7738
+ if (request.request.subtype === "can_use_tool") {
7739
+ if (!this.canCallTool) {
7740
+ throw new Error("canCallTool callback is not provided.");
7741
+ }
7742
+ return this.canCallTool(request.request.tool_name, request.request.input, {
7743
+ signal,
7744
+ requestId: request.request_id
7745
+ });
7746
+ }
7747
+ throw new Error("Unsupported control request subtype: " + request.request.subtype);
7748
+ }
7749
+ /**
7750
+ * Cleanup method to abort all pending control requests
7751
+ */
7752
+ cleanupControllers() {
7753
+ for (const [requestId, controller] of this.cancelControllers.entries()) {
7754
+ controller.abort();
7755
+ this.cancelControllers.delete(requestId);
7756
+ }
7757
+ }
7758
+ }
7759
+ function query(config) {
7760
+ const {
7761
+ prompt,
7762
+ options: {
7763
+ allowedTools = [],
7764
+ appendSystemPrompt,
7765
+ customSystemPrompt,
7766
+ cwd,
7767
+ disallowedTools = [],
7768
+ env,
7769
+ executable = "node",
7770
+ executableArgs = [],
7771
+ maxTurns,
7772
+ mcpServers,
7773
+ pathToClaudeCodeExecutable = getDefaultClaudeCodePath(),
7774
+ permissionMode,
7775
+ continue: continueConversation,
7776
+ resume,
7777
+ model,
7778
+ fallbackModel,
7779
+ strictMcpConfig,
7780
+ canCallTool,
7781
+ settingsPath,
7782
+ extraArgs = []
7783
+ } = {}
7784
+ } = config;
7785
+ if (!process.env.CLAUDE_CODE_ENTRYPOINT) {
7786
+ process.env.CLAUDE_CODE_ENTRYPOINT = "sdk-ts";
7787
+ }
7788
+ const args = [...extraArgs, "--output-format", "stream-json", "--verbose"];
7789
+ if (customSystemPrompt) args.push("--system-prompt", customSystemPrompt);
7790
+ if (appendSystemPrompt) args.push("--append-system-prompt", appendSystemPrompt);
7791
+ if (maxTurns) args.push("--max-turns", maxTurns.toString());
7792
+ if (model) args.push("--model", model);
7793
+ if (canCallTool) {
7794
+ if (typeof prompt === "string") {
7795
+ throw new Error("canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable.");
7796
+ }
7797
+ args.push("--permission-prompt-tool", "stdio");
7798
+ }
7799
+ if (continueConversation) args.push("--continue");
7800
+ if (resume) args.push("--resume", resume);
7801
+ if (allowedTools.length > 0) args.push("--allowedTools", allowedTools.join(","));
7802
+ if (disallowedTools.length > 0) args.push("--disallowedTools", disallowedTools.join(","));
7803
+ if (mcpServers && Object.keys(mcpServers).length > 0) {
7804
+ args.push("--mcp-config", JSON.stringify({ mcpServers }));
7805
+ }
7806
+ if (strictMcpConfig) args.push("--strict-mcp-config");
7807
+ if (permissionMode) args.push("--permission-mode", permissionMode);
7808
+ if (settingsPath) args.push("--settings", settingsPath);
7809
+ if (fallbackModel) {
7810
+ if (model && fallbackModel === model) {
7811
+ throw new Error("Fallback model cannot be the same as the main model. Please specify a different model for fallbackModel option.");
7812
+ }
7813
+ args.push("--fallback-model", fallbackModel);
7814
+ }
7815
+ if (typeof prompt === "string") {
7816
+ args.push("--print", prompt.trim());
7817
+ } else {
7818
+ args.push("--input-format", "stream-json");
7819
+ }
7820
+ const isJsFile = pathToClaudeCodeExecutable.endsWith(".js") || pathToClaudeCodeExecutable.endsWith(".cjs");
7821
+ const isCommandOnly = pathToClaudeCodeExecutable === "claude";
7822
+ if (!isCommandOnly && !existsSync(pathToClaudeCodeExecutable)) {
7823
+ throw new ReferenceError(`Claude Code executable not found at ${pathToClaudeCodeExecutable}. Is options.pathToClaudeCodeExecutable set?`);
7824
+ }
7825
+ const spawnCommand = isJsFile ? executable : pathToClaudeCodeExecutable;
7826
+ const spawnArgs = isJsFile ? [...executableArgs, pathToClaudeCodeExecutable, ...args] : args;
7827
+ const spawnEnv = {
7828
+ ...isCommandOnly ? getCleanEnv() : process.env,
7829
+ ...env
7830
+ };
7831
+ logDebug(`Spawning Claude Code process: ${spawnCommand} ${spawnArgs.join(" ")} (using ${isCommandOnly ? "clean" : "normal"} env)`);
7832
+ const child = spawn$2(spawnCommand, spawnArgs, {
7833
+ cwd,
7834
+ stdio: ["pipe", "pipe", "pipe"],
7835
+ signal: config.options?.abort,
7836
+ env: spawnEnv,
7837
+ // Use shell on Windows for global binaries and command-only mode
7838
+ shell: !isJsFile && process.platform === "win32"
7839
+ });
7840
+ let childStdin = null;
7841
+ if (typeof prompt === "string") {
7842
+ child.stdin.end();
7843
+ } else {
7844
+ streamToStdin(prompt, child.stdin, config.options?.abort);
7845
+ childStdin = child.stdin;
7846
+ }
7847
+ if (process.env.DEBUG) {
7848
+ child.stderr.on("data", (data) => {
7849
+ console.error("Claude Code stderr:", data.toString());
7850
+ });
7851
+ }
7852
+ const cleanup = () => {
7853
+ if (!child.killed) {
7854
+ child.kill("SIGTERM");
7855
+ }
7856
+ };
7857
+ config.options?.abort?.addEventListener("abort", cleanup);
7858
+ process.on("exit", cleanup);
7859
+ const processExitPromise = new Promise((resolve) => {
7860
+ child.on("close", (code) => {
7861
+ if (config.options?.abort?.aborted) {
7862
+ query2.setError(new AbortError("Claude Code process aborted by user"));
7863
+ }
7864
+ if (code !== 0) {
7865
+ query2.setError(new Error(`Claude Code process exited with code ${code}`));
7866
+ } else {
7867
+ resolve();
7868
+ }
7869
+ });
7870
+ });
7871
+ const query2 = new Query(childStdin, child.stdout, processExitPromise, canCallTool);
7872
+ child.on("error", (error) => {
7873
+ if (config.options?.abort?.aborted) {
7874
+ query2.setError(new AbortError("Claude Code process aborted by user"));
7875
+ } else {
7876
+ query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));
7877
+ }
7878
+ });
7879
+ processExitPromise.finally(() => {
7880
+ cleanup();
7881
+ config.options?.abort?.removeEventListener("abort", cleanup);
7882
+ if (process.env.CLAUDE_SDK_MCP_SERVERS) {
7883
+ delete process.env.CLAUDE_SDK_MCP_SERVERS;
7884
+ }
7885
+ });
7886
+ return query2;
7887
+ }
7888
+
7889
+ class Future {
7890
+ _resolve;
7891
+ _reject;
7892
+ _promise;
7893
+ constructor() {
7894
+ this._promise = new Promise((resolve, reject) => {
7895
+ this._resolve = resolve;
7896
+ this._reject = reject;
7897
+ });
7898
+ }
7899
+ resolve(value) {
7900
+ this._resolve(value);
7901
+ }
7902
+ reject(reason) {
7903
+ this._reject(reason);
7904
+ }
7905
+ get promise() {
7906
+ return this._promise;
7907
+ }
7908
+ }
7909
+
7910
+ class PushableAsyncIterable {
7911
+ queue = [];
7912
+ waiters = [];
7913
+ isDone = false;
7914
+ error = null;
7915
+ started = false;
7916
+ constructor() {
7917
+ }
7918
+ /**
7919
+ * Push a value to the iterable
7920
+ */
7921
+ push(value) {
7922
+ if (this.isDone) {
7923
+ throw new Error("Cannot push to completed iterable");
7924
+ }
7925
+ if (this.error) {
7926
+ throw this.error;
7927
+ }
7928
+ const waiter = this.waiters.shift();
7929
+ if (waiter) {
7930
+ waiter.resolve({ done: false, value });
7931
+ } else {
7932
+ this.queue.push(value);
7933
+ }
7934
+ }
7935
+ /**
7936
+ * Mark the iterable as complete
7937
+ */
7938
+ end() {
7939
+ if (this.isDone) {
7940
+ return;
7941
+ }
7942
+ this.isDone = true;
7943
+ this.cleanup();
7944
+ }
7945
+ /**
7946
+ * Set an error on the iterable
7947
+ */
7948
+ setError(err) {
7949
+ if (this.isDone) {
7950
+ return;
7951
+ }
7952
+ this.error = err;
7953
+ this.isDone = true;
7954
+ this.cleanup();
7955
+ }
7956
+ /**
7957
+ * Cleanup waiting consumers
7958
+ */
7959
+ cleanup() {
7960
+ while (this.waiters.length > 0) {
7961
+ const waiter = this.waiters.shift();
7962
+ if (this.error) {
7963
+ waiter.reject(this.error);
7964
+ } else {
7965
+ waiter.resolve({ done: true, value: void 0 });
7966
+ }
7967
+ }
7968
+ }
7969
+ /**
7970
+ * AsyncIterableIterator implementation
7971
+ */
7972
+ async next() {
7973
+ if (this.queue.length > 0) {
7974
+ return { done: false, value: this.queue.shift() };
7975
+ }
7976
+ if (this.isDone) {
7977
+ if (this.error) {
7978
+ throw this.error;
7979
+ }
7980
+ return { done: true, value: void 0 };
7981
+ }
7982
+ return new Promise((resolve, reject) => {
7983
+ this.waiters.push({ resolve, reject });
7984
+ });
7985
+ }
7986
+ /**
7987
+ * AsyncIterableIterator return implementation
7988
+ */
7989
+ async return(_value) {
7990
+ this.end();
7991
+ return { done: true, value: void 0 };
7992
+ }
7993
+ /**
7994
+ * AsyncIterableIterator throw implementation
7995
+ */
7996
+ async throw(e) {
7997
+ this.setError(e instanceof Error ? e : new Error(String(e)));
7998
+ throw this.error;
7999
+ }
8000
+ /**
8001
+ * Make this iterable
8002
+ */
8003
+ [Symbol.asyncIterator]() {
8004
+ if (this.started) {
8005
+ throw new Error("PushableAsyncIterable can only be iterated once");
8006
+ }
8007
+ this.started = true;
8008
+ return this;
8009
+ }
8010
+ /**
8011
+ * Check if the iterable is done
8012
+ */
8013
+ get done() {
8014
+ return this.isDone;
8015
+ }
8016
+ /**
8017
+ * Check if the iterable has an error
8018
+ */
8019
+ get hasError() {
8020
+ return this.error !== null;
8021
+ }
8022
+ /**
8023
+ * Get the current queue size
8024
+ */
8025
+ get queueSize() {
8026
+ return this.queue.length;
8027
+ }
8028
+ /**
8029
+ * Get the number of waiting consumers
8030
+ */
8031
+ get waiterCount() {
8032
+ return this.waiters.length;
8033
+ }
8034
+ }
8035
+
8036
+ function normalizeClaudeBackendError(error) {
8037
+ const record = typeof error === "object" && error !== null ? error : null;
8038
+ const text = formatDisplayMessage(error).trim();
8039
+ const stderrText = record ? formatDisplayMessage(record.stderr).trim() : "";
8040
+ const detailText = record ? formatDisplayMessage(record.detail).trim() : "";
8041
+ const searchable = [text, stderrText, detailText].filter(Boolean).join("\n").trim();
8042
+ return searchable || "Claude runtime backend exited unexpectedly";
8043
+ }
8044
+ function isRecord(value) {
8045
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8046
+ }
8047
+ function createTimeoutError(timeoutMs) {
8048
+ return new Error(`Claude response did not complete within ${timeoutMs}ms`);
8049
+ }
8050
+ function normalizePermissionResult(input, decision) {
8051
+ if (decision === "approved" || decision === "approved_for_session") {
8052
+ return {
8053
+ behavior: "allow",
8054
+ updatedInput: isRecord(input) ? input : {}
8055
+ };
8056
+ }
8057
+ return {
8058
+ behavior: "deny",
8059
+ message: decision === "denied" ? "The user denied this tool request." : "The tool request was aborted."
8060
+ };
8061
+ }
8062
+ function getClaudeExecutablePath(command) {
8063
+ if (command === "claude") {
8064
+ return resolve$1(join(projectPath(), "scripts", "claude_remote_launcher.cjs"));
8065
+ }
8066
+ return command;
8067
+ }
8068
+ class ClaudeCodeBackend {
8069
+ constructor(options) {
8070
+ this.options = options;
8071
+ }
8072
+ listeners = /* @__PURE__ */ new Set();
8073
+ toolNamesByCallId = /* @__PURE__ */ new Map();
8074
+ runtimeSessionId = randomUUID();
8075
+ messageStream = null;
8076
+ queryInstance = null;
8077
+ runtimeAbortController = null;
8078
+ consumeTask = null;
8079
+ activeResponse = null;
8080
+ responseCompletionOutcome = null;
8081
+ disposed = false;
8082
+ lastStatus = null;
8083
+ onMessage(handler) {
8084
+ this.listeners.add(handler);
8085
+ }
8086
+ offMessage(handler) {
8087
+ this.listeners.delete(handler);
8088
+ }
8089
+ async startSession(initialPrompt) {
8090
+ if (initialPrompt) {
8091
+ await this.sendPrompt(this.runtimeSessionId, initialPrompt);
8092
+ }
8093
+ return { sessionId: this.runtimeSessionId };
8094
+ }
8095
+ async sendPrompt(_sessionId, prompt) {
8096
+ if (this.disposed) {
8097
+ throw new Error("Claude runtime backend has already been disposed");
8098
+ }
8099
+ if (this.activeResponse) {
8100
+ throw new Error("Claude runtime backend is already processing a prompt");
8101
+ }
8102
+ await this.ensureQueryStarted();
8103
+ this.responseCompletionOutcome = null;
8104
+ this.activeResponse = new Future();
8105
+ void this.activeResponse.promise.catch(() => {
8106
+ });
8107
+ this.emitStatus("running");
8108
+ this.messageStream.push({
8109
+ type: "user",
8110
+ message: {
8111
+ role: "user",
8112
+ content: prompt
8113
+ }
8114
+ });
8115
+ }
8116
+ async cancel(_sessionId) {
8117
+ if (!this.queryInstance) {
8118
+ return;
8119
+ }
8120
+ try {
8121
+ await this.queryInstance.interrupt();
8122
+ } catch (error) {
8123
+ logger.debug("[ClaudeRuntimeBackend] Error interrupting Claude query:", error);
8124
+ }
8125
+ }
8126
+ async waitForResponseComplete(timeoutMs = 12e4) {
8127
+ if (this.responseCompletionOutcome) {
8128
+ const outcome = this.responseCompletionOutcome;
8129
+ if (outcome.kind === "rejected") {
8130
+ throw outcome.error;
8131
+ }
8132
+ return;
8133
+ }
8134
+ if (!this.activeResponse) {
8135
+ return;
8136
+ }
8137
+ let timeoutHandle;
8138
+ try {
8139
+ await Promise.race([
8140
+ this.activeResponse.promise,
8141
+ new Promise((_, reject) => {
8142
+ timeoutHandle = setTimeout(() => reject(createTimeoutError(timeoutMs)), timeoutMs);
8143
+ })
8144
+ ]);
8145
+ } finally {
8146
+ if (timeoutHandle) {
8147
+ clearTimeout(timeoutHandle);
8148
+ }
8149
+ }
8150
+ }
8151
+ async dispose() {
8152
+ if (this.disposed) {
8153
+ return;
8154
+ }
8155
+ this.disposed = true;
8156
+ const activeQuery = this.queryInstance;
8157
+ this.rejectActiveResponse(new Error("Claude runtime backend disposed"));
8158
+ this.messageStream?.end();
8159
+ this.runtimeAbortController?.abort();
8160
+ if (activeQuery && typeof activeQuery.return === "function") {
8161
+ try {
8162
+ await activeQuery.return();
8163
+ } catch (error) {
8164
+ logger.debug("[ClaudeRuntimeBackend] Error closing Claude query iterator:", error);
8165
+ }
8166
+ }
8167
+ try {
8168
+ await this.consumeTask;
8169
+ } catch (error) {
8170
+ logger.debug("[ClaudeRuntimeBackend] Error while disposing backend:", error);
8171
+ } finally {
8172
+ this.queryInstance = null;
8173
+ this.messageStream = null;
8174
+ this.runtimeAbortController = null;
8175
+ this.consumeTask = null;
8176
+ this.toolNamesByCallId.clear();
8177
+ this.emitStatus("stopped");
8178
+ }
8179
+ }
8180
+ emit(message) {
8181
+ for (const listener of this.listeners) {
8182
+ listener(message);
8183
+ }
8184
+ }
8185
+ emitStatus(status, detail) {
8186
+ if (this.lastStatus?.status === status && this.lastStatus.detail === detail) {
8187
+ return;
8188
+ }
8189
+ const message = {
8190
+ type: "status",
8191
+ status,
8192
+ ...detail ? { detail } : {}
8193
+ };
8194
+ this.lastStatus = message;
8195
+ this.emit(message);
8196
+ }
8197
+ async ensureQueryStarted() {
8198
+ if (this.queryInstance) {
8199
+ return;
8200
+ }
8201
+ this.emitStatus("starting");
8202
+ this.runtimeAbortController = new AbortController();
8203
+ this.messageStream = new PushableAsyncIterable();
8204
+ this.queryInstance = query({
8205
+ prompt: this.messageStream,
8206
+ options: {
8207
+ cwd: this.options.cwd,
8208
+ env: this.options.env,
8209
+ allowedTools: this.options.allowedTools,
8210
+ appendSystemPrompt: this.options.appendSystemPrompt,
8211
+ customSystemPrompt: this.options.customSystemPrompt,
8212
+ disallowedTools: this.options.disallowedTools,
8213
+ extraArgs: this.options.args,
8214
+ fallbackModel: this.options.fallbackModel,
8215
+ mcpServers: this.options.mcpServers,
8216
+ model: this.options.model,
8217
+ pathToClaudeCodeExecutable: getClaudeExecutablePath(this.options.command),
8218
+ permissionMode: this.options.permissionMode,
8219
+ settingsPath: this.options.settingsPath,
8220
+ canCallTool: this.options.permissionHandler ? async (toolName, input, requestOptions) => {
8221
+ const requestId = requestOptions.requestId ?? randomUUID();
8222
+ this.emit({
8223
+ type: "permission-request",
8224
+ id: requestId,
8225
+ reason: `Claude wants to use ${toolName}`,
8226
+ payload: {
8227
+ toolName,
8228
+ input
8229
+ }
8230
+ });
8231
+ const decision = await this.options.permissionHandler.handleToolCall(requestId, toolName, input);
8232
+ this.emit({
8233
+ type: "permission-response",
8234
+ id: requestId,
8235
+ approved: decision.decision === "approved" || decision.decision === "approved_for_session"
8236
+ });
8237
+ return normalizePermissionResult(input, decision.decision);
8238
+ } : void 0,
8239
+ abort: this.runtimeAbortController.signal
8240
+ }
8241
+ });
8242
+ this.consumeTask = this.consumeMessages(this.queryInstance);
8243
+ }
8244
+ async consumeMessages(activeQuery) {
8245
+ try {
8246
+ for await (const message of activeQuery) {
8247
+ this.handleMessage(message);
8248
+ }
8249
+ } catch (error) {
8250
+ const aborted = this.runtimeAbortController?.signal.aborted === true;
8251
+ if (!aborted) {
8252
+ const detail = normalizeClaudeBackendError(error);
8253
+ this.emitStatus("error", detail);
8254
+ this.rejectActiveResponse(new Error(detail));
8255
+ }
8256
+ } finally {
8257
+ if (!this.disposed && this.activeResponse) {
8258
+ const detail = "Claude runtime backend stopped before completing the response";
8259
+ this.emitStatus("error", detail);
8260
+ this.rejectActiveResponse(new Error(detail));
8261
+ }
8262
+ if (!this.disposed) {
8263
+ this.queryInstance = null;
8264
+ this.messageStream = null;
8265
+ this.runtimeAbortController = null;
8266
+ this.consumeTask = null;
8267
+ this.emitStatus("stopped");
8268
+ }
8269
+ }
8270
+ }
8271
+ handleMessage(message) {
8272
+ switch (message.type) {
8273
+ case "system":
8274
+ this.handleSystemMessage(message);
8275
+ return;
8276
+ case "assistant":
8277
+ this.handleAssistantMessage(message);
8278
+ return;
8279
+ case "user":
8280
+ this.handleUserMessage(message);
8281
+ return;
8282
+ case "result":
8283
+ this.handleResultMessage(message);
8284
+ return;
8285
+ default:
8286
+ return;
8287
+ }
8288
+ }
8289
+ handleSystemMessage(message) {
8290
+ if (message.subtype === "init") {
8291
+ this.emitStatus("running");
8292
+ this.emit({
8293
+ type: "event",
8294
+ name: "session-init",
8295
+ payload: {
8296
+ sessionId: message.session_id,
8297
+ cwd: message.cwd,
8298
+ model: message.model,
8299
+ tools: message.tools
8300
+ }
8301
+ });
8302
+ }
8303
+ }
8304
+ handleAssistantMessage(message) {
8305
+ for (const block of message.message.content ?? []) {
8306
+ if (block.type === "text" && typeof block.text === "string" && block.text.length > 0) {
8307
+ this.emit({
8308
+ type: "model-output",
8309
+ textDelta: block.text
8310
+ });
8311
+ continue;
8312
+ }
8313
+ if (block.type === "thinking") {
8314
+ const thinkingText = isRecord(block) && typeof block.thinking === "string" ? block.thinking : "";
8315
+ if (thinkingText) {
8316
+ this.emit({
8317
+ type: "event",
8318
+ name: "thinking",
8319
+ payload: { text: thinkingText }
8320
+ });
8321
+ }
8322
+ continue;
8323
+ }
8324
+ if (block.type === "tool_use" && block.id && block.name) {
8325
+ this.toolNamesByCallId.set(block.id, block.name);
8326
+ this.emit({
8327
+ type: "tool-call",
8328
+ toolName: block.name,
8329
+ args: isRecord(block.input) ? block.input : {},
8330
+ callId: block.id
8331
+ });
8332
+ }
8333
+ }
8334
+ }
8335
+ handleUserMessage(message) {
8336
+ const content = Array.isArray(message.message.content) ? message.message.content : [];
8337
+ for (const block of content) {
8338
+ if (block.type !== "tool_result" || !block.tool_use_id) {
8339
+ continue;
8340
+ }
8341
+ const toolName = this.toolNamesByCallId.get(block.tool_use_id) ?? "unknown";
8342
+ this.emit({
8343
+ type: "tool-result",
8344
+ toolName,
8345
+ result: block.content,
8346
+ callId: block.tool_use_id
8347
+ });
8348
+ if (toolName === "Bash" && isRecord(message.tool_use_result)) {
8349
+ const toolResult = message.tool_use_result;
8350
+ const stdout = formatDisplayMessage(toolResult.stdout).trim();
8351
+ const stderr = formatDisplayMessage(toolResult.stderr).trim();
8352
+ const combined = [stdout, stderr].filter(Boolean).join("\n");
8353
+ if (combined) {
8354
+ this.emit({
8355
+ type: "terminal-output",
8356
+ data: combined,
8357
+ callId: block.tool_use_id
8358
+ });
8359
+ }
8360
+ }
8361
+ }
8362
+ }
8363
+ handleResultMessage(message) {
8364
+ if (message.usage) {
8365
+ this.emit({
8366
+ type: "token-count",
8367
+ ...message.usage,
8368
+ duration_ms: message.duration_ms,
8369
+ duration_api_ms: message.duration_api_ms,
8370
+ total_cost_usd: message.total_cost_usd,
8371
+ session_id: message.session_id
8372
+ });
8373
+ }
8374
+ if (message.is_error) {
8375
+ const detail = typeof message.result === "string" && message.result.trim().length > 0 ? message.result : message.subtype;
8376
+ this.emitStatus("error", detail);
8377
+ this.rejectActiveResponse(new Error(detail));
8378
+ return;
8379
+ }
8380
+ this.emitStatus("idle");
8381
+ this.resolveActiveResponse();
8382
+ }
8383
+ resolveActiveResponse() {
8384
+ this.responseCompletionOutcome = { kind: "resolved" };
8385
+ if (!this.activeResponse) {
8386
+ return;
8387
+ }
8388
+ const active = this.activeResponse;
8389
+ this.activeResponse = null;
8390
+ active.resolve(void 0);
8391
+ }
8392
+ rejectActiveResponse(error) {
8393
+ this.responseCompletionOutcome = { kind: "rejected", error };
8394
+ if (!this.activeResponse) {
8395
+ return;
8396
+ }
8397
+ const active = this.activeResponse;
8398
+ this.activeResponse = null;
8399
+ active.reject(error);
8400
+ }
8401
+ }
8402
+
7357
8403
  function mapToClaudeMode(mode) {
7358
8404
  const codexToClaudeMap = {
7359
8405
  "yolo": "bypassPermissions",
@@ -7363,14 +8409,8 @@ function mapToClaudeMode(mode) {
7363
8409
  return codexToClaudeMap[mode] ?? mode;
7364
8410
  }
7365
8411
 
7366
- function ensureExperimentalAcp(args) {
7367
- if (args.includes("--experimental-acp")) {
7368
- return args;
7369
- }
7370
- return ["--experimental-acp", ...args];
7371
- }
7372
- function defaultClaudeArgs() {
7373
- return ensureExperimentalAcp([]);
8412
+ function defaultClaudeCommand() {
8413
+ return process.env.HAPPY_CLAUDE_COMMAND ?? process.env.HAPPY_CLAUDE_ACP_COMMAND ?? "claude";
7374
8414
  }
7375
8415
  function appendStringFlag(args, flag, value) {
7376
8416
  if (value && value.trim().length > 0) {
@@ -7382,11 +8422,22 @@ function appendListFlag(args, flag, values) {
7382
8422
  args.push(flag, values.join(","));
7383
8423
  }
7384
8424
  }
7385
- function resolveClaudeAcpArgs(options) {
7386
- if (options.args) {
7387
- return ensureExperimentalAcp([...options.args]);
8425
+ function normalizeClaudePassthroughArgs(options) {
8426
+ const sourceArgs = options.args ?? options.baseArgs ?? [];
8427
+ return sourceArgs.filter((arg) => arg !== "--experimental-acp");
8428
+ }
8429
+ function resolveClaudeCliArgs(options) {
8430
+ const args = [
8431
+ "--output-format",
8432
+ "stream-json",
8433
+ "--verbose",
8434
+ "--input-format",
8435
+ "stream-json",
8436
+ ...normalizeClaudePassthroughArgs(options)
8437
+ ];
8438
+ if (options.permissionHandler) {
8439
+ args.push("--permission-prompt-tool", "stdio");
7388
8440
  }
7389
- const args = ensureExperimentalAcp([...options.baseArgs ?? []]);
7390
8441
  appendStringFlag(args, "--system-prompt", options.customSystemPrompt);
7391
8442
  appendStringFlag(args, "--append-system-prompt", options.appendSystemPrompt);
7392
8443
  appendStringFlag(args, "--model", options.model);
@@ -7400,27 +8451,28 @@ function resolveClaudeAcpArgs(options) {
7400
8451
  return args;
7401
8452
  }
7402
8453
  function createClaudeBackend(options) {
7403
- const command = options.command ?? process.env.HAPPY_CLAUDE_ACP_COMMAND ?? "claude";
7404
- const args = resolveClaudeAcpArgs({
7405
- ...options,
7406
- baseArgs: options.baseArgs ?? defaultClaudeArgs()
7407
- });
7408
- const backendOptions = {
7409
- agentName: "claude",
7410
- cwd: options.cwd,
7411
- command,
7412
- args,
7413
- env: {
7414
- ...options.env,
7415
- NODE_ENV: "production"
7416
- },
7417
- mcpServers: options.mcpServers,
7418
- permissionHandler: options.permissionHandler,
7419
- selectionHandler: options.selectionHandler,
7420
- transportHandler: claudeTransport
7421
- };
8454
+ const command = options.command ?? defaultClaudeCommand();
8455
+ const args = resolveClaudeCliArgs(options);
7422
8456
  return {
7423
- backend: new AcpBackend(backendOptions),
8457
+ backend: new ClaudeCodeBackend({
8458
+ cwd: options.cwd,
8459
+ env: {
8460
+ ...options.env,
8461
+ NODE_ENV: "production"
8462
+ },
8463
+ command,
8464
+ args: normalizeClaudePassthroughArgs(options),
8465
+ model: options.model,
8466
+ fallbackModel: options.fallbackModel,
8467
+ permissionMode: options.permissionMode ? mapToClaudeMode(options.permissionMode) : void 0,
8468
+ customSystemPrompt: options.customSystemPrompt,
8469
+ appendSystemPrompt: options.appendSystemPrompt,
8470
+ allowedTools: options.allowedTools,
8471
+ disallowedTools: options.disallowedTools,
8472
+ settingsPath: options.settingsPath,
8473
+ mcpServers: options.mcpServers,
8474
+ permissionHandler: options.permissionHandler
8475
+ }),
7424
8476
  command,
7425
8477
  args
7426
8478
  };
@@ -7651,11 +8703,11 @@ var launch = /*#__PURE__*/Object.freeze({
7651
8703
 
7652
8704
  const unifiedProviderExecutors = {
7653
8705
  claude: async (opts) => {
7654
- const { runClaude } = await import('./runClaude-D7dF4RDM.mjs');
8706
+ const { runClaude } = await import('./runClaude-Ev-A-kLN.mjs');
7655
8707
  await runClaude(opts.credentials, opts.claudeOptions ?? {});
7656
8708
  },
7657
8709
  codex: async (opts) => {
7658
- const { runCodex } = await import('./runCodex-DnGz1XES.mjs');
8710
+ const { runCodex } = await import('./runCodex-BwFOTxMW.mjs');
7659
8711
  await runCodex({
7660
8712
  credentials: opts.credentials,
7661
8713
  startedBy: opts.startedBy,
@@ -7664,7 +8716,7 @@ const unifiedProviderExecutors = {
7664
8716
  });
7665
8717
  },
7666
8718
  gemini: async (opts) => {
7667
- const { runGemini } = await import('./runGemini-B8tXMHeL.mjs');
8719
+ const { runGemini } = await import('./runGemini-CXctVflO.mjs');
7668
8720
  await runGemini({
7669
8721
  credentials: opts.credentials,
7670
8722
  startedBy: opts.startedBy
@@ -7740,7 +8792,7 @@ function shouldRunMainClaudeFlow(opts) {
7740
8792
  return;
7741
8793
  } else if (subcommand === "runtime") {
7742
8794
  if (args[1] === "providers") {
7743
- const { renderRuntimeProviders } = await import('./command-CMvWClny.mjs');
8795
+ const { renderRuntimeProviders } = await import('./command-D9ZaQZQN.mjs');
7744
8796
  console.log(renderRuntimeProviders());
7745
8797
  return;
7746
8798
  }
@@ -7918,8 +8970,8 @@ function shouldRunMainClaudeFlow(opts) {
7918
8970
  const projectId = args[3];
7919
8971
  try {
7920
8972
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
7921
- const { readCredentials: readCredentials2 } = await import('./persistence-9Iu0wGNM.mjs');
7922
- const { ApiClient: ApiClient2 } = await import('./api-D1meoL-9.mjs').then(function (n) { return n.q; });
8973
+ const { readCredentials: readCredentials2 } = await import('./persistence-4BmGePWc.mjs');
8974
+ const { ApiClient: ApiClient2 } = await import('./api-Bad69WzY.mjs').then(function (n) { return n.q; });
7923
8975
  let userEmail = void 0;
7924
8976
  try {
7925
8977
  const credentials = await readCredentials2();
@@ -8335,4 +9387,4 @@ ${chalk.bold("Examples:")}
8335
9387
  }
8336
9388
  }
8337
9389
 
8338
- export { ExitCodeError as E, GEMINI_MODEL_ENV as G, RuntimeShell as R, createGeminiBackend as a, stopCaffeinate as b, createDefaultRuntimeShell as c, createCodexBackend as d, publishSessionRegistration as e, formatDisplayMessage as f, getInitialGeminiModel as g, resolveCanonicalToolNameV2 as h, initialMachineMetadata as i, getProjectPath as j, claudeLocal as k, isBun as l, trimIdent as m, claudeCheckSession as n, mapToClaudeMode as o, projectPath as p, getEnvironmentInfo as q, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, truncateDisplayMessage as t, startCaffeinate as u, validateCodexAcpSpawn as v };
9390
+ export { AbortError as A, ExitCodeError as E, Future as F, GEMINI_MODEL_ENV as G, PushableAsyncIterable as P, RuntimeShell as R, createGeminiBackend as a, stopCaffeinate as b, createDefaultRuntimeShell as c, createCodexBackend as d, projectPath as e, formatDisplayMessage as f, getInitialGeminiModel as g, resolveCanonicalToolNameV2 as h, initialMachineMetadata as i, getProjectPath as j, claudeLocal as k, trimIdent as l, createClaudeBackend as m, claudeCheckSession as n, mapToClaudeMode as o, publishSessionRegistration as p, query as q, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, truncateDisplayMessage as t, getEnvironmentInfo as u, validateCodexAcpSpawn as v, startCaffeinate as w };