very-happy-cli 0.2.96 → 0.2.97
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.
- package/dist/{AcpBackend-B5Eh8G3W.mjs → AcpBackend-CTUM4dvG.mjs} +1 -1
- package/dist/{AcpBackend-BaCt4_zS.cjs → AcpBackend-DrwdVSeJ.cjs} +1 -1
- package/dist/{AcpSessionManager-CvgmPlXB.cjs → AcpSessionManager-BieE187D.cjs} +1 -1
- package/dist/{AcpSessionManager-grr_aJEI.mjs → AcpSessionManager-BoBuHee3.mjs} +1 -1
- package/dist/{config-BjsUeQPA.cjs → config-COq6X7U7.cjs} +3 -3
- package/dist/{config-B69TZlJj.mjs → config-DCH33LOM.mjs} +3 -3
- package/dist/{index-uc-dtu-3.cjs → index-BD2fHJ8o.cjs} +526 -20
- package/dist/{index-BMmbxCTq.mjs → index-Bcgquogx.mjs} +527 -21
- package/dist/{index-C-uJXSm3.mjs → index-DkhMvofH.mjs} +6 -6
- package/dist/{index-DID1FV_n.cjs → index-Dn0iOBFd.cjs} +5 -5
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/{installTerminalHooks-CBHjEQ-a.mjs → installTerminalHooks-DqNtW6a2.mjs} +3 -3
- package/dist/{installTerminalHooks-CepXxAM_.cjs → installTerminalHooks-H3kpFEZS.cjs} +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +67 -0
- package/dist/lib.d.mts +67 -0
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-BdSHqi2d.mjs → mcp-BKAuzaLX.mjs} +3 -3
- package/dist/{mcp-CAtbtTXF.cjs → mcp-BwNc5eRs.cjs} +3 -3
- package/dist/{runGemini-cMZ3_CRf.mjs → runGemini-Brp0UmLx.mjs} +5 -5
- package/dist/{runGemini-qStPY5fH.cjs → runGemini-w35qiFBB.cjs} +5 -5
- package/dist/{runOpenClaw-BJ36wEbk.mjs → runOpenClaw-BvPRFx-L.mjs} +4 -4
- package/dist/{runOpenClaw-B8HR6GnX.cjs → runOpenClaw-CkHtTCpI.cjs} +4 -4
- package/dist/{send-TX13v8Xe.mjs → send-c-wEmh5U.mjs} +3 -3
- package/dist/{send-6eY55o3C.cjs → send-tyKG13xt.cjs} +3 -3
- package/dist/{spawn-vOZA0kOi.cjs → spawn-xdCsG2RT.cjs} +3 -3
- package/dist/{spawn-CfCE6JAv.mjs → spawn-yS6yY8Xi.mjs} +3 -3
- package/dist/{types-okYCRlgl.cjs → types-DoGaKVfK.cjs} +77 -10
- package/dist/{types-CLRl0ET3.mjs → types-xZOYW0_G.mjs} +76 -10
- package/package.json +7 -7
- 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-
|
|
6
|
+
var persistence = require('./types-DoGaKVfK.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
|
|
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-BD2fHJ8o.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 = [];
|
|
@@ -7387,6 +7865,8 @@ const initialMachineMetadata = {
|
|
|
7387
7865
|
resumeSupport: { ...persistence.detectResumeSupport(), rpcAvailable: true }
|
|
7388
7866
|
};
|
|
7389
7867
|
async function startDaemon() {
|
|
7868
|
+
let claudeAuthServiceRef = null;
|
|
7869
|
+
let claudeCredentialStoreSetting = (await persistence.readSettings()).claudeCredentialStore === "file" ? "file" : "auto";
|
|
7390
7870
|
let requestShutdown;
|
|
7391
7871
|
let resolvesWhenShutdownRequested = new Promise((resolve) => {
|
|
7392
7872
|
requestShutdown = (source, errorMessage) => {
|
|
@@ -7693,7 +8173,11 @@ async function startDaemon() {
|
|
|
7693
8173
|
}
|
|
7694
8174
|
let extraEnv = {
|
|
7695
8175
|
...authEnv,
|
|
7696
|
-
...options.environmentVariables ?? {}
|
|
8176
|
+
...options.environmentVariables ?? {},
|
|
8177
|
+
// B-276 D8: credentialStore=file pins the spawned Claude Code (SDK
|
|
8178
|
+
// Query, title/board one-shots — all inside this wrapper) to
|
|
8179
|
+
// ~/.claude/.credentials.json via the keychain-off `security` shim.
|
|
8180
|
+
...claudeAuthServiceRef?.claudeProcessEnvOverrides() ?? {}
|
|
7697
8181
|
};
|
|
7698
8182
|
if (options.parentSessionId) {
|
|
7699
8183
|
extraEnv.HAPPY_FORKED_FROM_SESSION_ID = options.parentSessionId;
|
|
@@ -8319,6 +8803,7 @@ async function startDaemon() {
|
|
|
8319
8803
|
requestShutdown: () => requestShutdown("happy-cli"),
|
|
8320
8804
|
onHappySessionWebhook,
|
|
8321
8805
|
onSessionStateEvent,
|
|
8806
|
+
onClaudeAuthFailed: (sessionId) => claudeAuthServiceRef?.signalAuthFailed(sessionId),
|
|
8322
8807
|
pushClipboard: (text) => {
|
|
8323
8808
|
if (!apiMachineRef) {
|
|
8324
8809
|
return { delivered: false, truncated: false, totalBytes: 0, error: "daemon is still starting up" };
|
|
@@ -8389,6 +8874,25 @@ async function startDaemon() {
|
|
|
8389
8874
|
listTrackedSessionIds: () => [...pidToTrackedSession.values()].map((session) => session.happySessionId).filter((sessionId) => typeof sessionId === "string"),
|
|
8390
8875
|
requestShutdown: () => requestShutdown("happy-app")
|
|
8391
8876
|
});
|
|
8877
|
+
const claudeAuthService = new ClaudeAuthService({
|
|
8878
|
+
happyHomeDir: persistence.configuration.happyHomeDir,
|
|
8879
|
+
happyLibDir: persistence.projectPath(),
|
|
8880
|
+
credentialSource: daemonClaudeCredentials.source,
|
|
8881
|
+
getCredentialStore: () => claudeCredentialStoreSetting,
|
|
8882
|
+
setCredentialStore: async (store) => {
|
|
8883
|
+
const settings = await persistence.readSettings();
|
|
8884
|
+
await persistence.writeSettings({ ...settings, claudeCredentialStore: store });
|
|
8885
|
+
claudeCredentialStoreSetting = store;
|
|
8886
|
+
},
|
|
8887
|
+
publish: (state) => apiMachine.setClaudeAuthState(state)
|
|
8888
|
+
});
|
|
8889
|
+
claudeAuthServiceRef = claudeAuthService;
|
|
8890
|
+
apiMachine.setClaudeAuthHandlers({
|
|
8891
|
+
probe: () => claudeAuthService.probe("rpc", true),
|
|
8892
|
+
repair: (action) => claudeAuthService.repair(action),
|
|
8893
|
+
setStore: (store) => claudeAuthService.setStore(store)
|
|
8894
|
+
});
|
|
8895
|
+
claudeAuthService.start();
|
|
8392
8896
|
apiMachine.connect();
|
|
8393
8897
|
let cliUpdateCheckRunning = false;
|
|
8394
8898
|
const refreshCliUpdate = async () => {
|
|
@@ -8443,6 +8947,8 @@ async function startDaemon() {
|
|
|
8443
8947
|
persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk, handing off to new daemon");
|
|
8444
8948
|
clearInterval(restartOnStaleVersionAndHeartbeat);
|
|
8445
8949
|
clearInterval(cliUpdateInterval);
|
|
8950
|
+
claudeAuthService.stop();
|
|
8951
|
+
claudeAuthService.stop();
|
|
8446
8952
|
apiMachine.shutdown();
|
|
8447
8953
|
await stopControlServer();
|
|
8448
8954
|
await cleanupDaemonState();
|
|
@@ -9436,7 +9942,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
9436
9942
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
9437
9943
|
function resolveClaudeBinary() {
|
|
9438
9944
|
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-
|
|
9945
|
+
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-BD2fHJ8o.cjs', document.baseURI).href)));
|
|
9440
9946
|
const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
9441
9947
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
9442
9948
|
const path$1 = getClaudeCliPath();
|
|
@@ -11631,9 +12137,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
11631
12137
|
};
|
|
11632
12138
|
}
|
|
11633
12139
|
|
|
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-
|
|
12140
|
+
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-BD2fHJ8o.cjs', document.baseURI).href)));
|
|
11635
12141
|
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-
|
|
12142
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BD2fHJ8o.cjs', document.baseURI).href)));
|
|
11637
12143
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
11638
12144
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
11639
12145
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -14257,7 +14763,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14257
14763
|
process.exit(0);
|
|
14258
14764
|
} else if (subcommand === "install-terminal-hooks") {
|
|
14259
14765
|
try {
|
|
14260
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
14766
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-H3kpFEZS.cjs'); });
|
|
14261
14767
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
14262
14768
|
if (command.action === "help") {
|
|
14263
14769
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -14274,7 +14780,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14274
14780
|
}
|
|
14275
14781
|
} else if (subcommand === "spawn") {
|
|
14276
14782
|
try {
|
|
14277
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
14783
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-xdCsG2RT.cjs'); });
|
|
14278
14784
|
await handleSpawnCommand(args.slice(1));
|
|
14279
14785
|
} catch (error) {
|
|
14280
14786
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14286,7 +14792,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14286
14792
|
return;
|
|
14287
14793
|
} else if (subcommand === "send") {
|
|
14288
14794
|
try {
|
|
14289
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
14795
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-tyKG13xt.cjs'); });
|
|
14290
14796
|
await handleSendCommand(args.slice(1));
|
|
14291
14797
|
} catch (error) {
|
|
14292
14798
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14392,9 +14898,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14392
14898
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
14393
14899
|
const projectId = args[3];
|
|
14394
14900
|
try {
|
|
14395
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
14396
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-
|
|
14397
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
14901
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-COq6X7U7.cjs'); });
|
|
14902
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-DoGaKVfK.cjs'); }).then(function (n) { return n.persistence; });
|
|
14903
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DoGaKVfK.cjs'); }).then(function (n) { return n.api; });
|
|
14398
14904
|
let userEmail = void 0;
|
|
14399
14905
|
try {
|
|
14400
14906
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -14425,7 +14931,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14425
14931
|
}
|
|
14426
14932
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
14427
14933
|
try {
|
|
14428
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
14934
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-COq6X7U7.cjs'); });
|
|
14429
14935
|
const config = readGeminiLocalConfig();
|
|
14430
14936
|
if (config.googleCloudProject) {
|
|
14431
14937
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -14465,7 +14971,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14465
14971
|
process.exit(0);
|
|
14466
14972
|
}
|
|
14467
14973
|
try {
|
|
14468
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
14974
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-w35qiFBB.cjs'); });
|
|
14469
14975
|
let startedBy = void 0;
|
|
14470
14976
|
for (let i = 1; i < args.length; i++) {
|
|
14471
14977
|
if (args[i] === "--started-by") {
|
|
@@ -14487,7 +14993,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14487
14993
|
return;
|
|
14488
14994
|
} else if (subcommand === "acp") {
|
|
14489
14995
|
try {
|
|
14490
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
14996
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Dn0iOBFd.cjs'); });
|
|
14491
14997
|
let startedBy = void 0;
|
|
14492
14998
|
let verbose = false;
|
|
14493
14999
|
const acpArgs = [];
|
|
@@ -14527,7 +15033,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14527
15033
|
return;
|
|
14528
15034
|
} else if (subcommand === "openclaw") {
|
|
14529
15035
|
try {
|
|
14530
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
15036
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CkHtTCpI.cjs'); });
|
|
14531
15037
|
let startedBy = void 0;
|
|
14532
15038
|
let verbose = false;
|
|
14533
15039
|
let gatewayUrl;
|
|
@@ -14578,7 +15084,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14578
15084
|
return;
|
|
14579
15085
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
14580
15086
|
try {
|
|
14581
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
15087
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-BwNc5eRs.cjs'); });
|
|
14582
15088
|
await handleMcpCommand();
|
|
14583
15089
|
} catch (error) {
|
|
14584
15090
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|