very-happy-cli 0.2.96 → 0.2.98

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 (32) hide show
  1. package/dist/{AcpBackend-B5Eh8G3W.mjs → AcpBackend-BXiGiFC7.mjs} +1 -1
  2. package/dist/{AcpBackend-BaCt4_zS.cjs → AcpBackend-DhR8ml8L.cjs} +1 -1
  3. package/dist/{AcpSessionManager-grr_aJEI.mjs → AcpSessionManager-CDnrxAfQ.mjs} +1 -1
  4. package/dist/{AcpSessionManager-CvgmPlXB.cjs → AcpSessionManager-Ckc0NFmf.cjs} +1 -1
  5. package/dist/{config-B69TZlJj.mjs → config-B3pA9YsN.mjs} +3 -3
  6. package/dist/{config-BjsUeQPA.cjs → config-GJQc_kpD.cjs} +3 -3
  7. package/dist/{index-DID1FV_n.cjs → index-BBm2b34F.cjs} +5 -5
  8. package/dist/{index-C-uJXSm3.mjs → index-Bh5Rcy0s.mjs} +6 -6
  9. package/dist/{index-uc-dtu-3.cjs → index-CO1gNtuP.cjs} +528 -25
  10. package/dist/{index-BMmbxCTq.mjs → index-CuUVSZnK.mjs} +527 -24
  11. package/dist/index.cjs +3 -3
  12. package/dist/index.mjs +3 -3
  13. package/dist/{installTerminalHooks-CepXxAM_.cjs → installTerminalHooks-Cp9JVxQ-.cjs} +3 -3
  14. package/dist/{installTerminalHooks-CBHjEQ-a.mjs → installTerminalHooks-Ru0dn_zF.mjs} +3 -3
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +77 -0
  17. package/dist/lib.d.mts +77 -0
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-CAtbtTXF.cjs → mcp-B5HMF24K.cjs} +3 -3
  20. package/dist/{mcp-BdSHqi2d.mjs → mcp-CQoVN0u2.mjs} +3 -3
  21. package/dist/{runGemini-qStPY5fH.cjs → runGemini-BBzPVzuc.cjs} +5 -5
  22. package/dist/{runGemini-cMZ3_CRf.mjs → runGemini-CwZXQsgu.mjs} +5 -5
  23. package/dist/{runOpenClaw-B8HR6GnX.cjs → runOpenClaw-B4nC6XGL.cjs} +4 -4
  24. package/dist/{runOpenClaw-BJ36wEbk.mjs → runOpenClaw-C-jz4rWr.mjs} +4 -4
  25. package/dist/{send-6eY55o3C.cjs → send-CWgaINHC.cjs} +3 -3
  26. package/dist/{send-TX13v8Xe.mjs → send-DN-nVBEI.mjs} +3 -3
  27. package/dist/{spawn-vOZA0kOi.cjs → spawn-C0NSP84Y.cjs} +3 -3
  28. package/dist/{spawn-CfCE6JAv.mjs → spawn-CqcfbOnk.mjs} +3 -3
  29. package/dist/{types-okYCRlgl.cjs → types-BP-4phS_.cjs} +358 -72
  30. package/dist/{types-CLRl0ET3.mjs → types-Cl4vWuDY.mjs} +356 -72
  31. package/package.json +7 -7
  32. package/scripts/shims/keychain-off/security +51 -0
@@ -3,7 +3,7 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var persistence = require('./types-okYCRlgl.cjs');
6
+ var persistence = require('./types-BP-4phS_.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -33,11 +33,11 @@ var open = require('open');
33
33
  var fastify = require('fastify');
34
34
  var z = require('zod');
35
35
  var fastifyTypeProviderZod = require('fastify-type-provider-zod');
36
+ var node_module = require('node:module');
36
37
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
37
38
  var node_http = require('node:http');
38
39
  var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
39
40
  var limits = require('./limits-KdWKmwtH.cjs');
40
- var node_module = require('node:module');
41
41
  var http = require('http');
42
42
  var util = require('util');
43
43
  var inquirer = require('inquirer');
@@ -197,6 +197,9 @@ async function spawnDaemonSession(directory, sessionId, opts) {
197
197
  async function notifyDaemonSessionEvent(sessionId, event, spawnedBy) {
198
198
  return daemonPost("/session-event", { sessionId, event, spawnedBy });
199
199
  }
200
+ async function notifyDaemonClaudeAuthFailed(sessionId) {
201
+ return daemonPost("/session-event", { sessionId, event: "auth_failed" });
202
+ }
200
203
  async function stopDaemonHttp() {
201
204
  await daemonPost("/stop");
202
205
  }
@@ -1766,6 +1769,20 @@ function parseSpecialCommand(message) {
1766
1769
  };
1767
1770
  }
1768
1771
 
1772
+ const AUTH_FAILURE_RESULT_TEXT = /Failed to authenticate|OAuth session expired/i;
1773
+ const QUERY_RECYCLE_NOTICE = {
1774
+ authentication_failed: "\u26A0\uFE0F Claude Code could not refresh its OAuth session. This agent process was ended so your next message starts a fresh one that re-reads the credentials on this machine; if it fails again, run `claude` on the machine to log in again."
1775
+ };
1776
+ function queryRecycleReason(result, lastAssistantError) {
1777
+ if (lastAssistantError === "authentication_failed") {
1778
+ return "authentication_failed";
1779
+ }
1780
+ if (result.is_error && typeof result.result === "string" && AUTH_FAILURE_RESULT_TEXT.test(result.result)) {
1781
+ return "authentication_failed";
1782
+ }
1783
+ return null;
1784
+ }
1785
+
1769
1786
  class PushableAsyncIterable {
1770
1787
  queue = [];
1771
1788
  waiters = [];
@@ -2026,11 +2043,15 @@ async function claudeRemote(opts) {
2026
2043
  }
2027
2044
  });
2028
2045
  }
2046
+ let lastAssistantError;
2029
2047
  updateThinking(true);
2030
2048
  try {
2031
2049
  persistence.logger.debug(`[claudeRemote] Starting to iterate over response`);
2032
2050
  for await (const message of response) {
2033
2051
  persistence.logger.debug(`[claudeRemote] Message ${message.type}`, persistence.contentLogMetadata(message));
2052
+ if (message.type === "assistant" && message.error) {
2053
+ lastAssistantError = message.error;
2054
+ }
2034
2055
  const outboundMessage = isCompactCommand && message.type === "assistant" ? { ...message, isCompactSummary: true } : message;
2035
2056
  opts.onMessage(outboundMessage);
2036
2057
  if (message.type === "system" && message.subtype === "init") {
@@ -2079,6 +2100,15 @@ async function claudeRemote(opts) {
2079
2100
  isCompactCommand = false;
2080
2101
  }
2081
2102
  opts.onReady(message);
2103
+ const recycleReason = queryRecycleReason(message, lastAssistantError);
2104
+ lastAssistantError = void 0;
2105
+ if (recycleReason) {
2106
+ persistence.logger.warn(`[claudeRemote] Ending SDK query after ${recycleReason}; the next message starts a fresh Claude Code process`);
2107
+ opts.onCompletionEvent?.(QUERY_RECYCLE_NOTICE[recycleReason]);
2108
+ opts.onAuthFailure?.(recycleReason);
2109
+ messages.end();
2110
+ continue;
2111
+ }
2082
2112
  opts.nextMessage().then((next) => {
2083
2113
  if (!next) {
2084
2114
  messages.end();
@@ -3282,8 +3312,9 @@ async function cleanupStdinAfterInk(opts) {
3282
3312
  }
3283
3313
 
3284
3314
  function applyClaudeResultLifecycle(result, callbacks) {
3285
- if (result && result.subtype !== "success") {
3286
- const error = result.errors?.filter(Boolean).join("\n").trim() || result.subtype;
3315
+ if (result && (result.subtype !== "success" || result.is_error === true)) {
3316
+ const frame = result;
3317
+ const error = frame.errors?.filter(Boolean).join("\n").trim() || (typeof frame.result === "string" ? frame.result.trim() : "") || frame.subtype;
3287
3318
  callbacks.closeFailed(error);
3288
3319
  callbacks.onFailed(error);
3289
3320
  return;
@@ -3755,6 +3786,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3755
3786
  persistence.logger.debug("[remote]: Completion event received:", persistence.contentLogMetadata(message));
3756
3787
  session.client.sendSessionEvent({ type: "message", message });
3757
3788
  },
3789
+ onAuthFailure: (reason) => {
3790
+ session.client.sendSessionEvent({ type: "message", message: `Claude Code auth: ${reason}`, kind: "claude-auth-failed" });
3791
+ void notifyDaemonClaudeAuthFailed(session.client.sessionId).catch((error) => persistence.logger.debug("[remote]: auth_failed report to daemon failed:", error));
3792
+ },
3758
3793
  onSessionReset: () => {
3759
3794
  persistence.logger.debug("[remote]: Session reset");
3760
3795
  session.clearSessionId();
@@ -5428,6 +5463,7 @@ function startDaemonControlServer({
5428
5463
  requestShutdown,
5429
5464
  onHappySessionWebhook,
5430
5465
  onSessionStateEvent,
5466
+ onClaudeAuthFailed,
5431
5467
  pushClipboard,
5432
5468
  onTerminalHook
5433
5469
  }) {
@@ -5483,7 +5519,7 @@ function startDaemonControlServer({
5483
5519
  schema: {
5484
5520
  body: z.z.object({
5485
5521
  sessionId: z.z.string(),
5486
- event: z.z.enum(["completed", "needs_input"]),
5522
+ event: z.z.enum(["completed", "needs_input", "auth_failed"]),
5487
5523
  spawnedBy: z.z.string().optional()
5488
5524
  }),
5489
5525
  response: {
@@ -5495,6 +5531,10 @@ function startDaemonControlServer({
5495
5531
  }, async (request) => {
5496
5532
  const { sessionId, event, spawnedBy } = request.body;
5497
5533
  persistence.logger.debug(`[CONTROL SERVER] Session event: ${sessionId} ${event} (spawnedBy=${spawnedBy ?? "unset"})`);
5534
+ if (event === "auth_failed") {
5535
+ onClaudeAuthFailed?.(sessionId);
5536
+ return { status: "ok" };
5537
+ }
5498
5538
  onSessionStateEvent?.(sessionId, event, spawnedBy);
5499
5539
  return { status: "ok" };
5500
5540
  });
@@ -6668,6 +6708,444 @@ async function handleResumeCommand(args) {
6668
6708
  }
6669
6709
  }
6670
6710
 
6711
+ const CLAUDE_KEYCHAIN_SERVICE_PREFIX = "Claude Code";
6712
+ function keychainIdentity(env = process.env, deps = {}) {
6713
+ const home = deps.home ?? os.homedir();
6714
+ const secureDir = env.CLAUDE_SECURESTORAGE_CONFIG_DIR?.trim();
6715
+ const configDirEnv = env.CLAUDE_CONFIG_DIR?.trim();
6716
+ const configDir = secureDir || configDirEnv || path.join(home, ".claude");
6717
+ const hasCustomDir = Boolean(secureDir || configDirEnv);
6718
+ const dirSuffix = hasCustomDir ? "-" + node_crypto.createHash("sha256").update(configDir.normalize("NFC")).digest("hex").slice(0, 8) : "";
6719
+ const oauthSuffix = env.CLAUDE_CODE_OAUTH_CLIENT_ID?.trim() ? "-custom-oauth" : "";
6720
+ const rawAccount = env.USER || safeUsername(deps.username);
6721
+ const account = /^[a-zA-Z0-9._-]+$/.test(rawAccount) ? rawAccount : "claude-code-user";
6722
+ return {
6723
+ service: `${CLAUDE_KEYCHAIN_SERVICE_PREFIX}${oauthSuffix}-credentials${dirSuffix}`,
6724
+ account,
6725
+ configDir,
6726
+ credentialsPath: path.join(configDir, ".credentials.json")
6727
+ };
6728
+ }
6729
+ function safeUsername(provider) {
6730
+ try {
6731
+ return provider ? provider() : os.userInfo().username;
6732
+ } catch {
6733
+ return "";
6734
+ }
6735
+ }
6736
+
6737
+ const CLAUDE_AUTH_PROBE_VERSION = 1;
6738
+ const LOCAL_CREDENTIAL_SOURCE = "Claude local credentials";
6739
+ function classifyAuthStatus(run, credentialSource) {
6740
+ const localSource = credentialSource === void 0 || credentialSource === LOCAL_CREDENTIAL_SOURCE;
6741
+ if (run.spawnError) {
6742
+ return { status: "error", diagnosis: "probe-crash", detail: `could not run claude auth status: ${run.spawnError}` };
6743
+ }
6744
+ if (run.timedOut) {
6745
+ return { status: "error", diagnosis: "probe-timeout", detail: "claude auth status did not answer within the timeout" };
6746
+ }
6747
+ const parsed = parseJsonObject(run.stdout);
6748
+ if (!parsed) {
6749
+ if (!localSource) return { status: "unknown", authMethod: credentialSource, detail: `auth status unparseable under ${credentialSource}` };
6750
+ return { status: "error", diagnosis: "probe-crash", detail: `claude auth status returned no JSON (exit ${run.exitCode ?? "null"})` };
6751
+ }
6752
+ const authMethod = typeof parsed.authMethod === "string" ? parsed.authMethod : void 0;
6753
+ const subscriptionType = typeof parsed.subscriptionType === "string" ? parsed.subscriptionType : void 0;
6754
+ if (parsed.loggedIn === true) {
6755
+ return { status: "ok", authMethod: localSource ? authMethod : credentialSource, subscriptionType };
6756
+ }
6757
+ if (!localSource) {
6758
+ return { status: "unknown", authMethod: credentialSource, detail: `Claude Code reports loggedIn=false under ${credentialSource}; not a local-credential failure` };
6759
+ }
6760
+ return { status: "not-logged-in", authMethod, subscriptionType, detail: "Claude Code in the daemon context reports it is not logged in" };
6761
+ }
6762
+ function parseJsonObject(text) {
6763
+ const trimmed = text.trim();
6764
+ if (!trimmed) return null;
6765
+ const start = trimmed.indexOf("{");
6766
+ if (start < 0) return null;
6767
+ try {
6768
+ const value = JSON.parse(trimmed.slice(start));
6769
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
6770
+ } catch {
6771
+ return null;
6772
+ }
6773
+ }
6774
+ function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CO1gNtuP.cjs', document.baseURI).href))).resolve(s)) {
6775
+ const platformArch = `${platform}-${arch}`;
6776
+ const candidates = [
6777
+ `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
6778
+ `@anthropic-ai/claude-agent-sdk-${platformArch}/claude.exe`
6779
+ ];
6780
+ for (const candidate of candidates) {
6781
+ try {
6782
+ return resolver(candidate);
6783
+ } catch {
6784
+ }
6785
+ }
6786
+ return null;
6787
+ }
6788
+ function interpretSecurityRead(result) {
6789
+ if (result.error === "ENOENT") return { kind: "unsupported" };
6790
+ if (result.error === "timeout") return { kind: "error", detail: "security timed out" };
6791
+ if (result.exitCode === 44) return { kind: "absent" };
6792
+ if (result.exitCode === 36) return { kind: "unreadable" };
6793
+ if (result.exitCode !== 0) return { kind: "error", detail: `security exited ${result.exitCode ?? "null"}` };
6794
+ const raw = result.stdout.trim();
6795
+ if (!raw) return { kind: "absent" };
6796
+ const parsed = parseJsonObject(raw);
6797
+ const oauth = parsed && typeof parsed.claudeAiOauth === "object" && parsed.claudeAiOauth ? parsed.claudeAiOauth : null;
6798
+ if (!oauth) return { kind: "present", accessToken: "", refreshToken: "", raw };
6799
+ return {
6800
+ kind: "present",
6801
+ accessToken: typeof oauth.accessToken === "string" ? oauth.accessToken : "",
6802
+ refreshToken: typeof oauth.refreshToken === "string" ? oauth.refreshToken : "",
6803
+ raw
6804
+ };
6805
+ }
6806
+ function interpretCredentialsFile(text) {
6807
+ if (text === null) return { exists: false, hasTokens: false, refreshToken: "" };
6808
+ const parsed = parseJsonObject(text);
6809
+ const oauth = parsed && typeof parsed.claudeAiOauth === "object" && parsed.claudeAiOauth ? parsed.claudeAiOauth : null;
6810
+ const access = oauth && typeof oauth.accessToken === "string" ? oauth.accessToken : "";
6811
+ const refresh = oauth && typeof oauth.refreshToken === "string" ? oauth.refreshToken : "";
6812
+ return { exists: true, hasTokens: access.length > 0 && refresh.length > 0, refreshToken: refresh };
6813
+ }
6814
+ function tokenTail(token) {
6815
+ return token ? node_crypto.createHash("sha256").update(token).digest("hex").slice(-6) : "";
6816
+ }
6817
+ function diagnoseStores(input) {
6818
+ const { status, keychain, file } = input;
6819
+ if (keychain.kind === "present") {
6820
+ const empty = keychain.accessToken.length === 0 && keychain.refreshToken.length === 0;
6821
+ if (empty && file.hasTokens && status === "not-logged-in") {
6822
+ return {
6823
+ diagnosis: "keychain-empty-item",
6824
+ repairable: "delete-empty-keychain-item",
6825
+ keychainRaw: keychain.raw,
6826
+ detail: "The login keychain holds a Claude Code credentials item with empty tokens; Claude Code prefers it over the valid ~/.claude/.credentials.json and reports not logged in."
6827
+ };
6828
+ }
6829
+ if (!empty && file.hasTokens && tokenTail(keychain.refreshToken) !== tokenTail(file.refreshToken)) {
6830
+ return {
6831
+ diagnosis: "store-divergence",
6832
+ detail: "Keychain and ~/.claude/.credentials.json hold different refresh tokens; one of them will stop working at its next refresh. Treat the daemon-context login as canonical, or pin credentialStore=file."
6833
+ };
6834
+ }
6835
+ return {};
6836
+ }
6837
+ if ((keychain.kind === "absent" || keychain.kind === "unreadable" || keychain.kind === "unsupported") && !file.hasTokens) {
6838
+ return { diagnosis: "no-credentials", detail: "No Claude Code credentials found for this daemon context; log in with `claude` on this machine." };
6839
+ }
6840
+ if (keychain.kind === "unreadable" && file.hasTokens && status === "not-logged-in") {
6841
+ return { detail: "The daemon context cannot read the keychain and the file credentials were not accepted; compare `claude auth status` on the machine." };
6842
+ }
6843
+ if (keychain.kind === "error") {
6844
+ return { detail: `keychain check failed: ${keychain.detail}` };
6845
+ }
6846
+ return {};
6847
+ }
6848
+ function securityReadArgs(identity) {
6849
+ return ["find-generic-password", "-s", identity.service, "-a", identity.account, "-w"];
6850
+ }
6851
+ function securityDeleteArgs(identity) {
6852
+ return ["delete-generic-password", "-s", identity.service, "-a", identity.account];
6853
+ }
6854
+ const HAPPY_DAEMON_LAUNCHD_LABEL = "com.mereith.happy-daemon";
6855
+ function classifyLineage(input) {
6856
+ if (input.platform !== "darwin") return "other";
6857
+ const label = input.label ?? HAPPY_DAEMON_LAUNCHD_LABEL;
6858
+ if (input.env.XPC_SERVICE_NAME !== label) return "other";
6859
+ if (input.launchdJobPid !== null && input.ancestorPids.includes(input.launchdJobPid)) return "launchd";
6860
+ return "inherited-env";
6861
+ }
6862
+ function parseLaunchctlPid(printOutput) {
6863
+ const match = /^\s*pid\s*=\s*(\d+)/m.exec(printOutput);
6864
+ return match ? Number(match[1]) : null;
6865
+ }
6866
+ function keychainOffShimDir(happyLibDir) {
6867
+ return path.join(happyLibDir, "scripts", "shims", "keychain-off");
6868
+ }
6869
+ function withKeychainOffPath(path$1, shimDir) {
6870
+ const parts = (path$1 ?? "").split(path.delimiter).filter((p) => p && p !== shimDir);
6871
+ return [shimDir, ...parts].join(path.delimiter);
6872
+ }
6873
+ function buildClaudeAuthState(input) {
6874
+ const { classification, diagnosis } = input;
6875
+ const detail = (diagnosis?.detail ?? classification.detail)?.slice(0, 200);
6876
+ const state = {
6877
+ probeVersion: CLAUDE_AUTH_PROBE_VERSION,
6878
+ daemonPid: input.daemonPid,
6879
+ status: classification.status,
6880
+ context: { platform: input.platform, lineage: input.lineage, credentialStore: input.credentialStore },
6881
+ checkedAt: input.now ?? Date.now()
6882
+ };
6883
+ if (classification.authMethod) state.authMethod = classification.authMethod;
6884
+ if (classification.subscriptionType) state.subscriptionType = classification.subscriptionType;
6885
+ const diag = diagnosis?.diagnosis ?? classification.diagnosis;
6886
+ if (diag) state.diagnosis = diag;
6887
+ if (detail) state.detail = detail;
6888
+ if (diagnosis?.repairable) state.repairable = diagnosis.repairable;
6889
+ return state;
6890
+ }
6891
+ function claudeAuthStateChanged(prev, next) {
6892
+ if (!prev) return true;
6893
+ const strip = ({ checkedAt: _c, ...rest }) => JSON.stringify(rest);
6894
+ return strip(prev) !== strip(next);
6895
+ }
6896
+ function keychainIdentityFor(env) {
6897
+ return keychainIdentity(env);
6898
+ }
6899
+
6900
+ const CLAUDE_AUTH_PROBE_INTERVAL_MS = 10 * 60 * 1e3;
6901
+ const CLAUDE_AUTH_REFRESH_INTERVAL_MS = 30 * 60 * 1e3;
6902
+ const PROBE_TIMEOUT_MS = 8e3;
6903
+ const SECURITY_TIMEOUT_MS = 3e3;
6904
+ const SIGNAL_DEBOUNCE_MS = 1e3;
6905
+ class ClaudeAuthService {
6906
+ constructor(opts) {
6907
+ this.opts = opts;
6908
+ this.env = opts.env ?? process.env;
6909
+ this.platform = opts.platform ?? process.platform;
6910
+ }
6911
+ timer = null;
6912
+ signalTimer = null;
6913
+ inFlight = null;
6914
+ last = null;
6915
+ dirty = false;
6916
+ lastPublishedAt = 0;
6917
+ lineage = null;
6918
+ lastDiagnosis;
6919
+ env;
6920
+ platform;
6921
+ start() {
6922
+ setTimeout(() => void this.probe("startup"), 2e3).unref();
6923
+ this.timer = setInterval(() => void this.probe("interval"), CLAUDE_AUTH_PROBE_INTERVAL_MS);
6924
+ this.timer.unref();
6925
+ }
6926
+ stop() {
6927
+ if (this.timer) clearInterval(this.timer);
6928
+ if (this.signalTimer) clearTimeout(this.signalTimer);
6929
+ this.timer = null;
6930
+ this.signalTimer = null;
6931
+ }
6932
+ current() {
6933
+ return this.last;
6934
+ }
6935
+ /** D3: a session reported `authentication_failed`; re-probe after a short debounce. */
6936
+ signalAuthFailed(sessionId) {
6937
+ persistence.logger.debug(`[CLAUDE AUTH] auth_failed signal from session ${sessionId}`);
6938
+ if (this.signalTimer) clearTimeout(this.signalTimer);
6939
+ this.signalTimer = setTimeout(() => {
6940
+ this.signalTimer = null;
6941
+ void this.probe("signal", true);
6942
+ }, SIGNAL_DEBOUNCE_MS);
6943
+ this.signalTimer.unref();
6944
+ }
6945
+ /** Env the SDK/one-shot Claude Code processes should get for the current store setting. */
6946
+ claudeProcessEnvOverrides() {
6947
+ if (this.opts.getCredentialStore() !== "file") return {};
6948
+ const shim = this.resolveShimDir();
6949
+ if (!shim) return {};
6950
+ return { PATH: withKeychainOffPath(this.env.PATH, shim) };
6951
+ }
6952
+ effectiveCredentialStore() {
6953
+ if (this.opts.getCredentialStore() !== "file") return "auto";
6954
+ return this.resolveShimDir() ? "file" : "auto";
6955
+ }
6956
+ async probe(reason, withDiagnosis = false) {
6957
+ if (this.inFlight) return this.inFlight;
6958
+ this.inFlight = this.runProbe(reason, withDiagnosis).finally(() => {
6959
+ this.inFlight = null;
6960
+ });
6961
+ return this.inFlight;
6962
+ }
6963
+ async setStore(store) {
6964
+ await this.opts.setCredentialStore(store);
6965
+ return this.probe("set-store", true);
6966
+ }
6967
+ /** D4: delete the empty-token keychain item after re-validating every precondition. */
6968
+ async repair(action) {
6969
+ if (action !== "delete-empty-keychain-item") return { error: "unknown-action", claudeAuth: this.last };
6970
+ if (this.platform !== "darwin" || this.effectiveCredentialStore() === "file") return { error: "precondition-failed", claudeAuth: this.last };
6971
+ const state = await this.probe("repair-precheck", true);
6972
+ const seen = this.lastDiagnosis;
6973
+ if (state.diagnosis !== "keychain-empty-item" || !seen?.keychainRaw) return { error: "precondition-failed", claudeAuth: state };
6974
+ const identity = keychainIdentityFor(this.env);
6975
+ const again = interpretSecurityRead(await this.security(securityReadArgs(identity)));
6976
+ if (again.kind !== "present" || again.raw !== seen.keychainRaw || again.accessToken || again.refreshToken) {
6977
+ return { error: "precondition-failed", claudeAuth: state };
6978
+ }
6979
+ try {
6980
+ const dir = path.join(this.opts.happyHomeDir, "backups");
6981
+ node_fs.mkdirSync(dir, { recursive: true, mode: 448 });
6982
+ node_fs.writeFileSync(path.join(dir, `claude-keychain-${Date.now()}.json`), again.raw + "\n", { mode: 384 });
6983
+ } catch (error) {
6984
+ return { error: `backup-failed: ${String(error)}`, claudeAuth: state };
6985
+ }
6986
+ const del = await this.security(securityDeleteArgs(identity));
6987
+ if (del.exitCode !== 0) return { error: `delete-failed: security exited ${del.exitCode ?? "null"}`, claudeAuth: state };
6988
+ persistence.logger.debug("[CLAUDE AUTH] deleted empty-token keychain item after backup");
6989
+ const after = await this.probe("repair-done", true);
6990
+ return { ok: true, claudeAuth: after };
6991
+ }
6992
+ // ── internals ────────────────────────────────────────────────────────
6993
+ resolveShimDir() {
6994
+ const dir = keychainOffShimDir(this.opts.happyLibDir);
6995
+ const bin = path.join(dir, "security");
6996
+ try {
6997
+ if (!node_fs.statSync(bin).isFile()) return null;
6998
+ node_fs.accessSync(bin, node_fs.constants.X_OK);
6999
+ return dir;
7000
+ } catch {
7001
+ return null;
7002
+ }
7003
+ }
7004
+ async runProbe(reason, withDiagnosis) {
7005
+ const store = this.effectiveCredentialStore();
7006
+ const storeRequested = this.opts.getCredentialStore();
7007
+ const classification = await this.runAuthStatus();
7008
+ let diagnosis;
7009
+ this.lastDiagnosis = void 0;
7010
+ if (this.platform === "darwin" && store !== "file" && (classification.status === "not-logged-in" || withDiagnosis && classification.status !== "unknown")) {
7011
+ diagnosis = await this.diagnose(classification.status);
7012
+ this.lastDiagnosis = diagnosis;
7013
+ } else if (classification.status === "not-logged-in" && store === "file") {
7014
+ const file = interpretCredentialsFile(this.readCredentialsFile());
7015
+ if (!file.hasTokens) diagnosis = { diagnosis: "no-credentials", detail: "credentialStore=file and ~/.claude/.credentials.json has no tokens; log in with `claude` from a terminal on this machine." };
7016
+ }
7017
+ if (storeRequested === "file" && store === "auto") {
7018
+ diagnosis = { ...diagnosis ?? {}, detail: `credentialStore=file requested but the keychain-off shim is missing under ${keychainOffShimDir(this.opts.happyLibDir)}; running in auto mode.` };
7019
+ }
7020
+ const state = buildClaudeAuthState({
7021
+ daemonPid: process.pid,
7022
+ platform: this.platform,
7023
+ lineage: await this.resolveLineage(),
7024
+ credentialStore: store,
7025
+ classification,
7026
+ diagnosis,
7027
+ now: this.opts.now?.() ?? Date.now()
7028
+ });
7029
+ const changed = claudeAuthStateChanged(this.last, state);
7030
+ const stale = state.checkedAt - this.lastPublishedAt >= CLAUDE_AUTH_REFRESH_INTERVAL_MS;
7031
+ if (changed) {
7032
+ persistence.logger.debug(`[CLAUDE AUTH] ${reason}: status=${state.status} diagnosis=${state.diagnosis ?? "-"} lineage=${state.context.lineage} store=${state.context.credentialStore}`);
7033
+ }
7034
+ this.last = state;
7035
+ if (changed || stale || this.dirty) {
7036
+ const ok = await this.opts.publish(state).catch((error) => {
7037
+ persistence.logger.debug("[CLAUDE AUTH] publish failed:", error);
7038
+ return false;
7039
+ });
7040
+ this.dirty = !ok;
7041
+ if (ok) this.lastPublishedAt = state.checkedAt;
7042
+ else persistence.logger.warn("[CLAUDE AUTH] daemonState publish did not land; will force resend on the next probe");
7043
+ }
7044
+ return state;
7045
+ }
7046
+ async runAuthStatus() {
7047
+ const binary = resolveSdkClaudeBinary(this.platform, process.arch);
7048
+ if (!binary) {
7049
+ return { status: "claude-missing", diagnosis: "sdk-binary-missing", detail: "The Claude Code binary bundled with the Agent SDK is missing; remote sessions cannot start." };
7050
+ }
7051
+ const cwd = path.join(this.opts.happyHomeDir, "tmp", "auth-probe");
7052
+ try {
7053
+ node_fs.mkdirSync(cwd, { recursive: true });
7054
+ } catch {
7055
+ }
7056
+ const env = { ...this.env, ...this.claudeProcessEnvOverrides() };
7057
+ const run = await new Promise((resolve) => {
7058
+ let stdout = "";
7059
+ let settled = false;
7060
+ const done = (r) => {
7061
+ if (!settled) {
7062
+ settled = true;
7063
+ resolve(r);
7064
+ }
7065
+ };
7066
+ let child;
7067
+ try {
7068
+ child = node_child_process.spawn(binary, ["auth", "status"], { cwd, env, stdio: ["ignore", "pipe", "ignore"] });
7069
+ } catch (error) {
7070
+ done({ stdout: "", exitCode: null, timedOut: false, spawnError: String(error) });
7071
+ return;
7072
+ }
7073
+ const timer = setTimeout(() => {
7074
+ try {
7075
+ child.kill("SIGKILL");
7076
+ } catch {
7077
+ }
7078
+ done({ stdout, exitCode: null, timedOut: true });
7079
+ }, PROBE_TIMEOUT_MS);
7080
+ child.stdout?.on("data", (chunk) => {
7081
+ if (stdout.length < 65536) stdout += chunk.toString("utf8");
7082
+ });
7083
+ child.on("error", (error) => {
7084
+ clearTimeout(timer);
7085
+ done({ stdout, exitCode: null, timedOut: false, spawnError: String(error) });
7086
+ });
7087
+ child.on("close", (code) => {
7088
+ clearTimeout(timer);
7089
+ done({ stdout, exitCode: code, timedOut: false });
7090
+ });
7091
+ });
7092
+ return classifyAuthStatus(run, this.opts.credentialSource);
7093
+ }
7094
+ async diagnose(status) {
7095
+ const identity = keychainIdentityFor(this.env);
7096
+ const keychain = interpretSecurityRead(await this.security(securityReadArgs(identity)));
7097
+ const file = interpretCredentialsFile(this.readCredentialsFile(identity.credentialsPath));
7098
+ return diagnoseStores({ status, keychain, file });
7099
+ }
7100
+ readCredentialsFile(path) {
7101
+ const target = path ?? keychainIdentityFor(this.env).credentialsPath;
7102
+ try {
7103
+ return node_fs.existsSync(target) ? node_fs.readFileSync(target, "utf8") : null;
7104
+ } catch {
7105
+ return null;
7106
+ }
7107
+ }
7108
+ security(args) {
7109
+ return new Promise((resolve) => {
7110
+ node_child_process.execFile("security", args, { env: this.env, timeout: SECURITY_TIMEOUT_MS, maxBuffer: 65536 }, (error, stdout) => {
7111
+ const err = error;
7112
+ if (err && err.code === "ENOENT") return resolve({ exitCode: null, stdout: "", error: "ENOENT" });
7113
+ if (err && err.killed) return resolve({ exitCode: null, stdout: "", error: "timeout" });
7114
+ const exitCode = err ? typeof err.code === "number" ? err.code : 1 : 0;
7115
+ resolve({ exitCode, stdout: String(stdout ?? "") });
7116
+ });
7117
+ });
7118
+ }
7119
+ async resolveLineage() {
7120
+ if (this.lineage) return this.lineage;
7121
+ if (this.platform !== "darwin") {
7122
+ this.lineage = "other";
7123
+ return this.lineage;
7124
+ }
7125
+ const uid = typeof process.getuid === "function" ? process.getuid() : null;
7126
+ const launchdJobPid = uid === null ? null : parseLaunchctlPid(await this.exec("launchctl", ["print", `gui/${uid}/${HAPPY_DAEMON_LAUNCHD_LABEL}`]));
7127
+ const ancestors = await this.ancestorPids();
7128
+ this.lineage = classifyLineage({ platform: this.platform, env: this.env, launchdJobPid, ancestorPids: ancestors });
7129
+ return this.lineage;
7130
+ }
7131
+ async ancestorPids() {
7132
+ const out = [];
7133
+ let pid = process.ppid;
7134
+ for (let i = 0; i < 10 && pid > 1; i++) {
7135
+ out.push(pid);
7136
+ const ppid = Number((await this.exec("ps", ["-o", "ppid=", "-p", String(pid)])).trim());
7137
+ if (!Number.isFinite(ppid) || ppid === pid) break;
7138
+ pid = ppid;
7139
+ }
7140
+ return out;
7141
+ }
7142
+ exec(cmd, args) {
7143
+ return new Promise((resolve) => {
7144
+ node_child_process.execFile(cmd, args, { env: this.env, timeout: SECURITY_TIMEOUT_MS, maxBuffer: 65536 }, (_error, stdout) => resolve(String(stdout ?? "")));
7145
+ });
7146
+ }
7147
+ }
7148
+
6671
7149
  const INTERNAL_CLAUDE_EVENT_TYPES = /* @__PURE__ */ new Set(["file-history-snapshot", "change", "queue-operation"]);
6672
7150
  function parseLines(lines) {
6673
7151
  const out = [];
@@ -7372,9 +7850,6 @@ async function claimSessionOrExit(happySessionId, options) {
7372
7850
  process.on("exit", () => releaseSessionLock(happySessionId));
7373
7851
  }
7374
7852
 
7375
- function shellescape(s) {
7376
- return "'" + s.replace(/'/g, "'\\''") + "'";
7377
- }
7378
7853
  const hostSuffix = process.env.HAPPY_VARIANT === "dev" ? "-dev" : "";
7379
7854
  const initialMachineMetadata = {
7380
7855
  host: os$1.hostname() + hostSuffix,
@@ -7387,6 +7862,8 @@ const initialMachineMetadata = {
7387
7862
  resumeSupport: { ...persistence.detectResumeSupport(), rpcAvailable: true }
7388
7863
  };
7389
7864
  async function startDaemon() {
7865
+ let claudeAuthServiceRef = null;
7866
+ let claudeCredentialStoreSetting = (await persistence.readSettings()).claudeCredentialStore === "file" ? "file" : "auto";
7390
7867
  let requestShutdown;
7391
7868
  let resolvesWhenShutdownRequested = new Promise((resolve) => {
7392
7869
  requestShutdown = (source, errorMessage) => {
@@ -7693,7 +8170,11 @@ async function startDaemon() {
7693
8170
  }
7694
8171
  let extraEnv = {
7695
8172
  ...authEnv,
7696
- ...options.environmentVariables ?? {}
8173
+ ...options.environmentVariables ?? {},
8174
+ // B-276 D8: credentialStore=file pins the spawned Claude Code (SDK
8175
+ // Query, title/board one-shots — all inside this wrapper) to
8176
+ // ~/.claude/.credentials.json via the keychain-off `security` shim.
8177
+ ...claudeAuthServiceRef?.claudeProcessEnvOverrides() ?? {}
7697
8178
  };
7698
8179
  if (options.parentSessionId) {
7699
8180
  extraEnv.HAPPY_FORKED_FROM_SESSION_ID = options.parentSessionId;
@@ -7753,8 +8234,8 @@ async function startDaemon() {
7753
8234
  const cliPath = path$1.join(persistence.projectPath(), "dist", "index.mjs");
7754
8235
  const agent = options.agent === "gemini" ? "gemini" : options.agent === "codex" ? "codex" : options.agent === "openclaw" ? "openclaw" : "claude";
7755
8236
  const resumeId = agent === "claude" ? options.resumeClaudeSessionId : agent === "codex" ? options.resumeCodexThreadId : void 0;
7756
- const resumeFragment = resumeId ? ` --resume ${shellescape(resumeId)}` : "";
7757
- const permissionModeFragment = spawnPermissionMode ? ` --permission-mode ${shellescape(spawnPermissionMode)}` : "";
8237
+ const resumeFragment = resumeId ? ` --resume ${persistence.shellescape(resumeId)}` : "";
8238
+ const permissionModeFragment = spawnPermissionMode ? ` --permission-mode ${persistence.shellescape(spawnPermissionMode)}` : "";
7758
8239
  const fullCommand = `node --no-warnings --no-deprecation ${cliPath} ${agent} --happy-starting-mode remote --started-by daemon${resumeFragment}${permissionModeFragment}`;
7759
8240
  const windowName = `happy-${Date.now()}-${agent}`;
7760
8241
  const tmuxEnv = {};
@@ -8319,6 +8800,7 @@ async function startDaemon() {
8319
8800
  requestShutdown: () => requestShutdown("happy-cli"),
8320
8801
  onHappySessionWebhook,
8321
8802
  onSessionStateEvent,
8803
+ onClaudeAuthFailed: (sessionId) => claudeAuthServiceRef?.signalAuthFailed(sessionId),
8322
8804
  pushClipboard: (text) => {
8323
8805
  if (!apiMachineRef) {
8324
8806
  return { delivered: false, truncated: false, totalBytes: 0, error: "daemon is still starting up" };
@@ -8389,6 +8871,25 @@ async function startDaemon() {
8389
8871
  listTrackedSessionIds: () => [...pidToTrackedSession.values()].map((session) => session.happySessionId).filter((sessionId) => typeof sessionId === "string"),
8390
8872
  requestShutdown: () => requestShutdown("happy-app")
8391
8873
  });
8874
+ const claudeAuthService = new ClaudeAuthService({
8875
+ happyHomeDir: persistence.configuration.happyHomeDir,
8876
+ happyLibDir: persistence.projectPath(),
8877
+ credentialSource: daemonClaudeCredentials.source,
8878
+ getCredentialStore: () => claudeCredentialStoreSetting,
8879
+ setCredentialStore: async (store) => {
8880
+ const settings = await persistence.readSettings();
8881
+ await persistence.writeSettings({ ...settings, claudeCredentialStore: store });
8882
+ claudeCredentialStoreSetting = store;
8883
+ },
8884
+ publish: (state) => apiMachine.setClaudeAuthState(state)
8885
+ });
8886
+ claudeAuthServiceRef = claudeAuthService;
8887
+ apiMachine.setClaudeAuthHandlers({
8888
+ probe: () => claudeAuthService.probe("rpc", true),
8889
+ repair: (action) => claudeAuthService.repair(action),
8890
+ setStore: (store) => claudeAuthService.setStore(store)
8891
+ });
8892
+ claudeAuthService.start();
8392
8893
  apiMachine.connect();
8393
8894
  let cliUpdateCheckRunning = false;
8394
8895
  const refreshCliUpdate = async () => {
@@ -8443,6 +8944,8 @@ async function startDaemon() {
8443
8944
  persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk, handing off to new daemon");
8444
8945
  clearInterval(restartOnStaleVersionAndHeartbeat);
8445
8946
  clearInterval(cliUpdateInterval);
8947
+ claudeAuthService.stop();
8948
+ claudeAuthService.stop();
8446
8949
  apiMachine.shutdown();
8447
8950
  await stopControlServer();
8448
8951
  await cleanupDaemonState();
@@ -9436,7 +9939,7 @@ const MAX_TITLE_CHARS = 60;
9436
9939
  const GENERATION_TIMEOUT_MS = 3e4;
9437
9940
  function resolveClaudeBinary() {
9438
9941
  try {
9439
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-uc-dtu-3.cjs', document.baseURI).href)));
9942
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CO1gNtuP.cjs', document.baseURI).href)));
9440
9943
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
9441
9944
  const { getClaudeCliPath } = require$1(utilsPath);
9442
9945
  const path$1 = getClaudeCliPath();
@@ -11631,9 +12134,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
11631
12134
  };
11632
12135
  }
11633
12136
 
11634
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-uc-dtu-3.cjs', document.baseURI).href)));
12137
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CO1gNtuP.cjs', document.baseURI).href)));
11635
12138
  const __dirname$1 = path.dirname(__filename$1);
11636
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-uc-dtu-3.cjs', document.baseURI).href)));
12139
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CO1gNtuP.cjs', document.baseURI).href)));
11637
12140
  const PRISMA_QUERY_ENGINE_FILES = {
11638
12141
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
11639
12142
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -14257,7 +14760,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14257
14760
  process.exit(0);
14258
14761
  } else if (subcommand === "install-terminal-hooks") {
14259
14762
  try {
14260
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-CepXxAM_.cjs'); });
14763
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-Cp9JVxQ-.cjs'); });
14261
14764
  const command = parseTerminalHooksArgs(args.slice(1));
14262
14765
  if (command.action === "help") {
14263
14766
  console.log(TERMINAL_HOOKS_HELP);
@@ -14274,7 +14777,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14274
14777
  }
14275
14778
  } else if (subcommand === "spawn") {
14276
14779
  try {
14277
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-vOZA0kOi.cjs'); });
14780
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-C0NSP84Y.cjs'); });
14278
14781
  await handleSpawnCommand(args.slice(1));
14279
14782
  } catch (error) {
14280
14783
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -14286,7 +14789,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14286
14789
  return;
14287
14790
  } else if (subcommand === "send") {
14288
14791
  try {
14289
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-6eY55o3C.cjs'); });
14792
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CWgaINHC.cjs'); });
14290
14793
  await handleSendCommand(args.slice(1));
14291
14794
  } catch (error) {
14292
14795
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -14392,9 +14895,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14392
14895
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
14393
14896
  const projectId = args[3];
14394
14897
  try {
14395
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BjsUeQPA.cjs'); });
14396
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-okYCRlgl.cjs'); }).then(function (n) { return n.persistence; });
14397
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-okYCRlgl.cjs'); }).then(function (n) { return n.api; });
14898
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-GJQc_kpD.cjs'); });
14899
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-BP-4phS_.cjs'); }).then(function (n) { return n.persistence; });
14900
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BP-4phS_.cjs'); }).then(function (n) { return n.api; });
14398
14901
  let userEmail = void 0;
14399
14902
  try {
14400
14903
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -14425,7 +14928,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14425
14928
  }
14426
14929
  if (geminiSubcommand === "project" && args[2] === "get") {
14427
14930
  try {
14428
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BjsUeQPA.cjs'); });
14931
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-GJQc_kpD.cjs'); });
14429
14932
  const config = readGeminiLocalConfig();
14430
14933
  if (config.googleCloudProject) {
14431
14934
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -14465,7 +14968,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14465
14968
  process.exit(0);
14466
14969
  }
14467
14970
  try {
14468
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-qStPY5fH.cjs'); });
14971
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BBzPVzuc.cjs'); });
14469
14972
  let startedBy = void 0;
14470
14973
  for (let i = 1; i < args.length; i++) {
14471
14974
  if (args[i] === "--started-by") {
@@ -14487,7 +14990,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14487
14990
  return;
14488
14991
  } else if (subcommand === "acp") {
14489
14992
  try {
14490
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DID1FV_n.cjs'); });
14993
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-BBm2b34F.cjs'); });
14491
14994
  let startedBy = void 0;
14492
14995
  let verbose = false;
14493
14996
  const acpArgs = [];
@@ -14527,7 +15030,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14527
15030
  return;
14528
15031
  } else if (subcommand === "openclaw") {
14529
15032
  try {
14530
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B8HR6GnX.cjs'); });
15033
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B4nC6XGL.cjs'); });
14531
15034
  let startedBy = void 0;
14532
15035
  let verbose = false;
14533
15036
  let gatewayUrl;
@@ -14578,7 +15081,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14578
15081
  return;
14579
15082
  } else if (subcommand === "mcp" && args.length === 1) {
14580
15083
  try {
14581
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CAtbtTXF.cjs'); });
15084
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-B5HMF24K.cjs'); });
14582
15085
  await handleMcpCommand();
14583
15086
  } catch (error) {
14584
15087
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}