whale-code 6.5.9 → 6.5.11
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/cli/commands/doctor.js +1 -6
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/services/agent-loop-tools.js +1 -1
- package/dist/cli/services/agent-loop-tools.js.map +1 -1
- package/dist/cli/services/agent-loop.js +1 -1
- package/dist/cli/services/agent-loop.js.map +1 -1
- package/dist/cli/services/config-store.d.ts +8 -10
- package/dist/cli/services/config-store.js +10 -11
- package/dist/cli/services/config-store.js.map +1 -1
- package/dist/cli/setup/SetupApp.d.ts +2 -2
- package/dist/cli/setup/SetupApp.js +91 -254
- package/dist/cli/setup/SetupApp.js.map +1 -1
- package/dist/cli/status/StatusApp.js +3 -3
- package/dist/cli/status/StatusApp.js.map +1 -1
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/setup.js +5 -25
- package/dist/setup.js.map +1 -1
- package/package.json +1 -1
|
@@ -109,12 +109,7 @@ async function checkAuth() {
|
|
|
109
109
|
getValidToken
|
|
110
110
|
} = await import("../services/auth-service.js");
|
|
111
111
|
if (!isLoggedIn()) {
|
|
112
|
-
|
|
113
|
-
const {
|
|
114
|
-
loadConfig
|
|
115
|
-
} = await import("../services/config-store.js");
|
|
116
|
-
const config = loadConfig();
|
|
117
|
-
if (process.env.ANTHROPIC_API_KEY || config.anthropic_api_key) {
|
|
112
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
118
113
|
return {
|
|
119
114
|
status: "ok",
|
|
120
115
|
label: "Auth",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","names":["execSync","existsSync","readFileSync","join","homedir","CHECK","CROSS","WARN","DIM","RESET","icon","status","checkNodeVersion","version","process","major","parseInt","slice","split","label","detail","checkRipgrep","encoding","timeout","trim","rgPath","checkSupabase","SUPABASE_URL","resp","fetch","method","signal","AbortSignal","ok","err","message","checkAuth","isLoggedIn","getValidToken","loadConfig","config","env","ANTHROPIC_API_KEY","anthropic_api_key","token","checkServerTools","loadServerToolDefinitions","tools","length","checkMcpServers","servers","mcpServers","count","Object","keys","checkDiskSpace","dir","output","size","checkVersion","pkgPath","URL","import","meta","url","pathname","pkg","JSON","parse","runDoctor","console","log","checks","Promise","all","check","padEnd","errors","filter","c","warnings"],"sources":["../../../src/cli/commands/doctor.ts"],"sourcesContent":["/**\n * whale doctor — Run diagnostics\n *\n * Checks:\n * - Node.js version (>=20)\n * - ripgrep availability\n * - Supabase connection\n * - Auth status\n * - Server tools loadable\n * - MCP servers configured\n * - Disk space\n * - Package version vs latest\n */\n\nimport { execSync } from \"child_process\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { homedir } from \"os\";\n\nconst CHECK = \"\\x1b[32m✓\\x1b[0m\";\nconst CROSS = \"\\x1b[31m✗\\x1b[0m\";\nconst WARN = \"\\x1b[33m!\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\n\ninterface CheckResult {\n status: \"ok\" | \"warn\" | \"error\";\n label: string;\n detail: string;\n}\n\nfunction icon(status: \"ok\" | \"warn\" | \"error\"): string {\n if (status === \"ok\") return CHECK;\n if (status === \"warn\") return WARN;\n return CROSS;\n}\n\nasync function checkNodeVersion(): Promise<CheckResult> {\n const version = process.version;\n const major = parseInt(version.slice(1).split(\".\")[0], 10);\n if (major >= 20) {\n return { status: \"ok\", label: \"Node.js\", detail: version };\n }\n return { status: \"error\", label: \"Node.js\", detail: `${version} (need >=20)` };\n}\n\nasync function checkRipgrep(): Promise<CheckResult> {\n try {\n const version = execSync(\"rg --version 2>/dev/null\", { encoding: \"utf-8\", timeout: 3000 }).trim().split(\"\\n\")[0];\n return { status: \"ok\", label: \"ripgrep\", detail: version };\n } catch {\n // Check if @vscode/ripgrep is available\n try {\n const { rgPath } = await import(\"@vscode/ripgrep\") as any;\n return { status: \"ok\", label: \"ripgrep\", detail: `@vscode/ripgrep (${rgPath})` };\n } catch {\n return { status: \"warn\", label: \"ripgrep\", detail: \"not found (search will use fallback)\" };\n }\n }\n}\n\nasync function checkSupabase(): Promise<CheckResult> {\n try {\n const { SUPABASE_URL } = await import(\"../services/auth-service.js\");\n const resp = await fetch(`${SUPABASE_URL}/rest/v1/`, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(5000),\n });\n if (resp.ok || resp.status === 401) {\n return { status: \"ok\", label: \"Supabase\", detail: \"reachable\" };\n }\n return { status: \"warn\", label: \"Supabase\", detail: `status ${resp.status}` };\n } catch (err: any) {\n return { status: \"error\", label: \"Supabase\", detail: err.message?.slice(0, 60) || \"unreachable\" };\n }\n}\n\nasync function checkAuth(): Promise<CheckResult> {\n try {\n const { isLoggedIn, getValidToken } = await import(\"../services/auth-service.js\");\n if (!isLoggedIn()) {\n // Check for API key\n const { loadConfig } = await import(\"../services/config-store.js\");\n const config = loadConfig();\n if (process.env.ANTHROPIC_API_KEY || config.anthropic_api_key) {\n return { status: \"ok\", label: \"Auth\", detail: \"API key configured\" };\n }\n return { status: \"warn\", label: \"Auth\", detail: \"not logged in (run: whale login)\" };\n }\n const token = await getValidToken();\n return token\n ? { status: \"ok\", label: \"Auth\", detail: \"valid JWT\" }\n : { status: \"warn\", label: \"Auth\", detail: \"token expired\" };\n } catch {\n return { status: \"error\", label: \"Auth\", detail: \"check failed\" };\n }\n}\n\nasync function checkServerTools(): Promise<CheckResult> {\n try {\n const { loadServerToolDefinitions } = await import(\"../services/server-tools.js\");\n const tools = await loadServerToolDefinitions();\n return { status: \"ok\", label: \"Server tools\", detail: `${tools.length} tools loaded` };\n } catch (err: any) {\n return { status: \"warn\", label: \"Server tools\", detail: err.message?.slice(0, 60) || \"unavailable\" };\n }\n}\n\nasync function checkMcpServers(): Promise<CheckResult> {\n try {\n const { loadConfig } = await import(\"../services/config-store.js\");\n const config = loadConfig() as Record<string, unknown>;\n const servers = (config.mcpServers as Record<string, unknown>) || {};\n const count = Object.keys(servers).length;\n if (count === 0) {\n return { status: \"warn\", label: \"MCP servers\", detail: \"none configured\" };\n }\n return { status: \"ok\", label: \"MCP servers\", detail: `${count} configured` };\n } catch {\n return { status: \"warn\", label: \"MCP servers\", detail: \"config parse error\" };\n }\n}\n\nasync function checkDiskSpace(): Promise<CheckResult> {\n const dir = join(homedir(), \".whaletools\");\n if (!existsSync(dir)) {\n return { status: \"ok\", label: \"Data dir\", detail: \"~/.whaletools/ (not created yet)\" };\n }\n try {\n // Get total size\n const output = execSync(`du -sh \"${dir}\" 2>/dev/null`, { encoding: \"utf-8\", timeout: 5000 }).trim();\n const size = output.split(\"\\t\")[0];\n return { status: \"ok\", label: \"Data dir\", detail: `~/.whaletools/ (${size})` };\n } catch {\n return { status: \"ok\", label: \"Data dir\", detail: \"~/.whaletools/\" };\n }\n}\n\nasync function checkVersion(): Promise<CheckResult> {\n try {\n const pkgPath = join(new URL(\"../../..\", import.meta.url).pathname, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return { status: \"ok\", label: \"Version\", detail: `v${pkg.version}` };\n } catch {\n return { status: \"ok\", label: \"Version\", detail: \"unknown\" };\n }\n}\n\nexport async function runDoctor(): Promise<void> {\n console.log(\"\\n whale doctor\\n\");\n\n const checks = await Promise.all([\n checkNodeVersion(),\n checkRipgrep(),\n checkSupabase(),\n checkAuth(),\n checkServerTools(),\n checkMcpServers(),\n checkDiskSpace(),\n checkVersion(),\n ]);\n\n for (const check of checks) {\n console.log(` ${icon(check.status)} ${check.label.padEnd(16)} ${DIM}${check.detail}${RESET}`);\n }\n\n const errors = checks.filter(c => c.status === \"error\").length;\n const warnings = checks.filter(c => c.status === \"warn\").length;\n console.log();\n\n if (errors > 0) {\n console.log(` ${CROSS} ${errors} error${errors > 1 ? \"s\" : \"\"}, ${warnings} warning${warnings !== 1 ? \"s\" : \"\"}`);\n } else if (warnings > 0) {\n console.log(` ${WARN} All good, ${warnings} warning${warnings !== 1 ? \"s\" : \"\"}`);\n } else {\n console.log(` ${CHECK} All checks passed`);\n }\n console.log();\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"doctor.js","names":["execSync","existsSync","readFileSync","join","homedir","CHECK","CROSS","WARN","DIM","RESET","icon","status","checkNodeVersion","version","process","major","parseInt","slice","split","label","detail","checkRipgrep","encoding","timeout","trim","rgPath","checkSupabase","SUPABASE_URL","resp","fetch","method","signal","AbortSignal","ok","err","message","checkAuth","isLoggedIn","getValidToken","env","ANTHROPIC_API_KEY","token","checkServerTools","loadServerToolDefinitions","tools","length","checkMcpServers","loadConfig","config","servers","mcpServers","count","Object","keys","checkDiskSpace","dir","output","size","checkVersion","pkgPath","URL","import","meta","url","pathname","pkg","JSON","parse","runDoctor","console","log","checks","Promise","all","check","padEnd","errors","filter","c","warnings"],"sources":["../../../src/cli/commands/doctor.ts"],"sourcesContent":["/**\n * whale doctor — Run diagnostics\n *\n * Checks:\n * - Node.js version (>=20)\n * - ripgrep availability\n * - Supabase connection\n * - Auth status\n * - Server tools loadable\n * - MCP servers configured\n * - Disk space\n * - Package version vs latest\n */\n\nimport { execSync } from \"child_process\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { homedir } from \"os\";\n\nconst CHECK = \"\\x1b[32m✓\\x1b[0m\";\nconst CROSS = \"\\x1b[31m✗\\x1b[0m\";\nconst WARN = \"\\x1b[33m!\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\n\ninterface CheckResult {\n status: \"ok\" | \"warn\" | \"error\";\n label: string;\n detail: string;\n}\n\nfunction icon(status: \"ok\" | \"warn\" | \"error\"): string {\n if (status === \"ok\") return CHECK;\n if (status === \"warn\") return WARN;\n return CROSS;\n}\n\nasync function checkNodeVersion(): Promise<CheckResult> {\n const version = process.version;\n const major = parseInt(version.slice(1).split(\".\")[0], 10);\n if (major >= 20) {\n return { status: \"ok\", label: \"Node.js\", detail: version };\n }\n return { status: \"error\", label: \"Node.js\", detail: `${version} (need >=20)` };\n}\n\nasync function checkRipgrep(): Promise<CheckResult> {\n try {\n const version = execSync(\"rg --version 2>/dev/null\", { encoding: \"utf-8\", timeout: 3000 }).trim().split(\"\\n\")[0];\n return { status: \"ok\", label: \"ripgrep\", detail: version };\n } catch {\n // Check if @vscode/ripgrep is available\n try {\n const { rgPath } = await import(\"@vscode/ripgrep\") as any;\n return { status: \"ok\", label: \"ripgrep\", detail: `@vscode/ripgrep (${rgPath})` };\n } catch {\n return { status: \"warn\", label: \"ripgrep\", detail: \"not found (search will use fallback)\" };\n }\n }\n}\n\nasync function checkSupabase(): Promise<CheckResult> {\n try {\n const { SUPABASE_URL } = await import(\"../services/auth-service.js\");\n const resp = await fetch(`${SUPABASE_URL}/rest/v1/`, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(5000),\n });\n if (resp.ok || resp.status === 401) {\n return { status: \"ok\", label: \"Supabase\", detail: \"reachable\" };\n }\n return { status: \"warn\", label: \"Supabase\", detail: `status ${resp.status}` };\n } catch (err: any) {\n return { status: \"error\", label: \"Supabase\", detail: err.message?.slice(0, 60) || \"unreachable\" };\n }\n}\n\nasync function checkAuth(): Promise<CheckResult> {\n try {\n const { isLoggedIn, getValidToken } = await import(\"../services/auth-service.js\");\n if (!isLoggedIn()) {\n if (process.env.ANTHROPIC_API_KEY) {\n return { status: \"ok\", label: \"Auth\", detail: \"API key configured\" };\n }\n return { status: \"warn\", label: \"Auth\", detail: \"not logged in (run: whale login)\" };\n }\n const token = await getValidToken();\n return token\n ? { status: \"ok\", label: \"Auth\", detail: \"valid JWT\" }\n : { status: \"warn\", label: \"Auth\", detail: \"token expired\" };\n } catch {\n return { status: \"error\", label: \"Auth\", detail: \"check failed\" };\n }\n}\n\nasync function checkServerTools(): Promise<CheckResult> {\n try {\n const { loadServerToolDefinitions } = await import(\"../services/server-tools.js\");\n const tools = await loadServerToolDefinitions();\n return { status: \"ok\", label: \"Server tools\", detail: `${tools.length} tools loaded` };\n } catch (err: any) {\n return { status: \"warn\", label: \"Server tools\", detail: err.message?.slice(0, 60) || \"unavailable\" };\n }\n}\n\nasync function checkMcpServers(): Promise<CheckResult> {\n try {\n const { loadConfig } = await import(\"../services/config-store.js\");\n const config = loadConfig() as Record<string, unknown>;\n const servers = (config.mcpServers as Record<string, unknown>) || {};\n const count = Object.keys(servers).length;\n if (count === 0) {\n return { status: \"warn\", label: \"MCP servers\", detail: \"none configured\" };\n }\n return { status: \"ok\", label: \"MCP servers\", detail: `${count} configured` };\n } catch {\n return { status: \"warn\", label: \"MCP servers\", detail: \"config parse error\" };\n }\n}\n\nasync function checkDiskSpace(): Promise<CheckResult> {\n const dir = join(homedir(), \".whaletools\");\n if (!existsSync(dir)) {\n return { status: \"ok\", label: \"Data dir\", detail: \"~/.whaletools/ (not created yet)\" };\n }\n try {\n // Get total size\n const output = execSync(`du -sh \"${dir}\" 2>/dev/null`, { encoding: \"utf-8\", timeout: 5000 }).trim();\n const size = output.split(\"\\t\")[0];\n return { status: \"ok\", label: \"Data dir\", detail: `~/.whaletools/ (${size})` };\n } catch {\n return { status: \"ok\", label: \"Data dir\", detail: \"~/.whaletools/\" };\n }\n}\n\nasync function checkVersion(): Promise<CheckResult> {\n try {\n const pkgPath = join(new URL(\"../../..\", import.meta.url).pathname, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return { status: \"ok\", label: \"Version\", detail: `v${pkg.version}` };\n } catch {\n return { status: \"ok\", label: \"Version\", detail: \"unknown\" };\n }\n}\n\nexport async function runDoctor(): Promise<void> {\n console.log(\"\\n whale doctor\\n\");\n\n const checks = await Promise.all([\n checkNodeVersion(),\n checkRipgrep(),\n checkSupabase(),\n checkAuth(),\n checkServerTools(),\n checkMcpServers(),\n checkDiskSpace(),\n checkVersion(),\n ]);\n\n for (const check of checks) {\n console.log(` ${icon(check.status)} ${check.label.padEnd(16)} ${DIM}${check.detail}${RESET}`);\n }\n\n const errors = checks.filter(c => c.status === \"error\").length;\n const warnings = checks.filter(c => c.status === \"warn\").length;\n console.log();\n\n if (errors > 0) {\n console.log(` ${CROSS} ${errors} error${errors > 1 ? \"s\" : \"\"}, ${warnings} warning${warnings !== 1 ? \"s\" : \"\"}`);\n } else if (warnings > 0) {\n console.log(` ${WARN} All good, ${warnings} warning${warnings !== 1 ? \"s\" : \"\"}`);\n } else {\n console.log(` ${CHECK} All checks passed`);\n }\n console.log();\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -231,7 +231,7 @@ export function classifyToolError(output) {
|
|
|
231
231
|
export function canUseAgent() {
|
|
232
232
|
const config = loadConfig();
|
|
233
233
|
const hasToken = !!(config.access_token && config.refresh_token);
|
|
234
|
-
const hasApiKey = !!
|
|
234
|
+
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
|
235
235
|
if (hasToken || hasApiKey) return {
|
|
236
236
|
ready: true
|
|
237
237
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-loop-tools.js","names":["LOCAL_TOOL_DEFINITIONS","executeLocalTool","isLocalTool","INTERACTIVE_TOOL_DEFINITIONS","executeInteractiveTool","waitForPlanApproval","loadConfig","isServerTool","loadServerToolDefinitions","executeServerTool","mcpClientManager","getPermissionMode","isToolAllowedByPermission","runBeforeToolHook","runAfterToolHook","resetGitContext","resetClaudeMdCache","clearReadCache","resetAgentConfigCache","sessionInputTokens","sessionOutputTokens","getSessionTokens","input","output","addSessionTokens","resetSessionState","resetSessionLoopDetector","sessionLoopDetector","getSessionLoopDetector","setSessionLoopDetector","ld","CLI_NO_LIMIT","Number","MAX_SAFE_INTEGER","getTools","allowedTools","disallowedTools","localTools","map","t","name","description","input_schema","interactiveTools","push","serverTools","localNames","Set","uniqueServerTools","filter","has","mcpTools","allTools","length","allowed","disallowed","tools","serverToolCount","getServerToolCount","defs","INTERACTIVE_TOOL_NAMES","buildToolExecutor","hooks","abortSignal","emitter","success","effectiveInput","hookResult","hookErr","message","allow","modifiedInput","result","decision","action","feedback","isMcpTool","callTool","afterResult","modifiedOutput","undefined","truncateResult","maxLen","slice","classifyToolError","lower","toLowerCase","test","canUseAgent","config","hasToken","access_token","refresh_token","hasApiKey","process","env","ANTHROPIC_API_KEY","anthropic_api_key","ready","reason"],"sources":["../../../src/cli/services/agent-loop-tools.ts"],"sourcesContent":["/**\n * Agent Loop — tool definitions, session state, and tool executor builder.\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n LOCAL_TOOL_DEFINITIONS,\n executeLocalTool,\n isLocalTool,\n} from \"./local-tools.js\";\nimport {\n INTERACTIVE_TOOL_DEFINITIONS,\n executeInteractiveTool,\n waitForPlanApproval,\n type PlanApprovalDecision,\n} from \"./interactive-tools.js\";\nimport { loadConfig } from \"./config-store.js\";\nimport {\n isServerTool,\n loadServerToolDefinitions,\n executeServerTool,\n} from \"./server-tools.js\";\nimport { mcpClientManager } from \"./mcp-client.js\";\nimport { getPermissionMode, isToolAllowedByPermission } from \"./permission-modes.js\";\nimport { runBeforeToolHook, runAfterToolHook, type HookConfig } from \"./hooks.js\";\nimport type { AgentEventEmitter } from \"./agent-events.js\";\n\nimport { resetGitContext } from \"./git-context.js\";\nimport { resetClaudeMdCache } from \"./claude-md-loader.js\";\nimport { clearReadCache } from \"./tools/file-ops.js\";\nimport { resetAgentConfigCache } from \"./agent-config.js\";\n\n// ============================================================================\n// SESSION STATE\n// ============================================================================\n\nlet sessionInputTokens = 0;\nlet sessionOutputTokens = 0;\n\nexport function getSessionTokens(): { input: number; output: number } {\n return { input: sessionInputTokens, output: sessionOutputTokens };\n}\n\nexport function addSessionTokens(input: number, output: number): void {\n sessionInputTokens += input;\n sessionOutputTokens += output;\n}\n\n/**\n * Reset all CLI-only session state. Call when starting a new conversation.\n * Does NOT reset activeModel or permissionMode.\n */\nexport function resetSessionState(): void {\n sessionInputTokens = 0;\n sessionOutputTokens = 0;\n resetSessionLoopDetector();\n resetGitContext();\n resetClaudeMdCache();\n clearReadCache();\n resetAgentConfigCache();\n}\n\n// Loop detector — managed externally by the main loop\nimport { LoopDetector } from \"../../shared/agent-core.js\";\n\nlet sessionLoopDetector: LoopDetector | null = null;\n\nexport function getSessionLoopDetector(): LoopDetector | null {\n return sessionLoopDetector;\n}\n\nexport function setSessionLoopDetector(ld: LoopDetector): void {\n sessionLoopDetector = ld;\n}\n\nexport function resetSessionLoopDetector(): void {\n sessionLoopDetector = null;\n}\n\n// No artificial turn cap\nexport const CLI_NO_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// ============================================================================\n// TOOL DEFINITIONS\n// ============================================================================\n\nexport async function getTools(allowedTools?: string[], disallowedTools?: string[]): Promise<{ tools: Anthropic.Tool[]; serverToolCount: number }> {\n const localTools: Anthropic.Tool[] = LOCAL_TOOL_DEFINITIONS.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema as Anthropic.Tool[\"input_schema\"],\n }));\n\n const interactiveTools: Anthropic.Tool[] = INTERACTIVE_TOOL_DEFINITIONS.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema as Anthropic.Tool[\"input_schema\"],\n }));\n localTools.push(...interactiveTools);\n\n let serverTools: Anthropic.Tool[] = [];\n try {\n serverTools = await loadServerToolDefinitions();\n } catch {\n // Server tools silently unavailable\n }\n\n const localNames = new Set(localTools.map(t => t.name));\n const uniqueServerTools = serverTools.filter(t => !localNames.has(t.name));\n\n const mcpTools = mcpClientManager.getTools();\n\n let allTools = [...localTools, ...uniqueServerTools, ...mcpTools];\n\n if (allowedTools && allowedTools.length > 0) {\n const allowed = new Set(allowedTools);\n allTools = allTools.filter(t => allowed.has(t.name));\n }\n if (disallowedTools && disallowedTools.length > 0) {\n const disallowed = new Set(disallowedTools);\n allTools = allTools.filter(t => !disallowed.has(t.name));\n }\n\n return { tools: allTools, serverToolCount: uniqueServerTools.length };\n}\n\n/** Exposed for /status command */\nexport async function getServerToolCount(): Promise<number> {\n try {\n const defs = await loadServerToolDefinitions();\n return defs.length;\n } catch {\n return 0;\n }\n}\n\n// ============================================================================\n// TOOL EXECUTOR BUILDER\n// ============================================================================\n\nconst INTERACTIVE_TOOL_NAMES = new Set(INTERACTIVE_TOOL_DEFINITIONS.map(t => t.name));\n\nexport function buildToolExecutor(\n hooks: HookConfig[],\n abortSignal?: AbortSignal,\n emitter?: AgentEventEmitter,\n): (name: string, input: Record<string, unknown>) => Promise<{ success: boolean; output: string }> {\n return async (name: string, input: Record<string, unknown>) => {\n if (!name) return { success: false, output: \"Tool call missing name — skipping.\" };\n\n if (!isToolAllowedByPermission(name)) {\n return { success: false, output: `Tool \"${name}\" blocked by ${getPermissionMode()} mode. Switch modes with /mode.` };\n }\n\n let effectiveInput = input;\n if (hooks.length > 0) {\n let hookResult;\n try {\n hookResult = await runBeforeToolHook(hooks, name, input);\n } catch (hookErr: any) {\n return { success: false, output: `Hook error for ${name}: ${hookErr.message || hookErr}` };\n }\n if (!hookResult.allow) return { success: false, output: hookResult.message || \"Blocked by hook\" };\n if (hookResult.modifiedInput) effectiveInput = hookResult.modifiedInput;\n }\n\n let result: { success: boolean; output: string };\n if (INTERACTIVE_TOOL_NAMES.has(name)) {\n result = await executeInteractiveTool(name, effectiveInput);\n if (name === \"exit_plan_mode\" && result.success) {\n const decision: PlanApprovalDecision = await waitForPlanApproval(abortSignal);\n switch (decision.action) {\n case \"execute\": result = { success: true, output: `__PLAN_APPROVED_CLEAN__\\n${result.output}` }; break;\n case \"edit\": result = { success: true, output: \"Plan returned for revision. Make changes and use ExitPlanMode again when ready.\" }; break;\n case \"feedback\": result = { success: true, output: `User feedback on plan:\\n\\n${decision.feedback || \"(no feedback provided)\"}\\n\\nRevise the plan based on this feedback, then use ExitPlanMode again.` }; break;\n case \"cancel\": result = { success: true, output: \"Plan cancelled by user. Do not proceed with implementation.\" }; break;\n }\n }\n } else if (isLocalTool(name)) {\n result = await executeLocalTool(name, effectiveInput, abortSignal);\n } else if (isServerTool(name)) {\n result = await executeServerTool(name, effectiveInput, emitter);\n } else if (mcpClientManager.isMcpTool(name)) {\n result = await mcpClientManager.callTool(name, effectiveInput);\n } else {\n result = { success: false, output: `Unknown tool: ${name}` };\n }\n\n if (hooks.length > 0) {\n try {\n const afterResult = await runAfterToolHook(hooks, name, result.output, result.success);\n if (afterResult.modifiedOutput !== undefined) result = { ...result, output: afterResult.modifiedOutput };\n } catch {\n // After-hook failure is non-fatal — preserve original result\n }\n }\n\n return result;\n };\n}\n\n// ============================================================================\n// TELEMETRY HELPERS\n// ============================================================================\n\nexport function truncateResult(output: string, maxLen: number): string {\n if (output.length <= maxLen) return output;\n return output.slice(0, maxLen) + `... (${output.length} chars total)`;\n}\n\nexport function classifyToolError(output: string): string {\n const lower = output.toLowerCase();\n if (/timed?\\s*out|timeout/.test(lower)) return \"timeout\";\n if (/permission denied|eacces/.test(lower)) return \"permission\";\n if (/not found|no such file/.test(lower)) return \"not_found\";\n if (/command not found|exit code 127/.test(lower)) return \"command_not_found\";\n if (/import\\b.*\\berror|error\\b.*\\bimport/.test(lower)) return \"import_error\";\n if (/syntax|parse/.test(lower)) return \"syntax_error\";\n if (/externally-managed/.test(lower)) return \"env_managed\";\n return \"unknown\";\n}\n\n// ============================================================================\n// AUTH CHECK\n// ============================================================================\n\nexport function canUseAgent(): { ready: boolean; reason?: string } {\n const config = loadConfig();\n const hasToken = !!(config.access_token && config.refresh_token);\n const hasApiKey = !!(process.env.ANTHROPIC_API_KEY || config.anthropic_api_key);\n if (hasToken || hasApiKey) return { ready: true };\n return { ready: false, reason: \"Run `whale login` to authenticate.\" };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"agent-loop-tools.js","names":["LOCAL_TOOL_DEFINITIONS","executeLocalTool","isLocalTool","INTERACTIVE_TOOL_DEFINITIONS","executeInteractiveTool","waitForPlanApproval","loadConfig","isServerTool","loadServerToolDefinitions","executeServerTool","mcpClientManager","getPermissionMode","isToolAllowedByPermission","runBeforeToolHook","runAfterToolHook","resetGitContext","resetClaudeMdCache","clearReadCache","resetAgentConfigCache","sessionInputTokens","sessionOutputTokens","getSessionTokens","input","output","addSessionTokens","resetSessionState","resetSessionLoopDetector","sessionLoopDetector","getSessionLoopDetector","setSessionLoopDetector","ld","CLI_NO_LIMIT","Number","MAX_SAFE_INTEGER","getTools","allowedTools","disallowedTools","localTools","map","t","name","description","input_schema","interactiveTools","push","serverTools","localNames","Set","uniqueServerTools","filter","has","mcpTools","allTools","length","allowed","disallowed","tools","serverToolCount","getServerToolCount","defs","INTERACTIVE_TOOL_NAMES","buildToolExecutor","hooks","abortSignal","emitter","success","effectiveInput","hookResult","hookErr","message","allow","modifiedInput","result","decision","action","feedback","isMcpTool","callTool","afterResult","modifiedOutput","undefined","truncateResult","maxLen","slice","classifyToolError","lower","toLowerCase","test","canUseAgent","config","hasToken","access_token","refresh_token","hasApiKey","process","env","ANTHROPIC_API_KEY","ready","reason"],"sources":["../../../src/cli/services/agent-loop-tools.ts"],"sourcesContent":["/**\n * Agent Loop — tool definitions, session state, and tool executor builder.\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n LOCAL_TOOL_DEFINITIONS,\n executeLocalTool,\n isLocalTool,\n} from \"./local-tools.js\";\nimport {\n INTERACTIVE_TOOL_DEFINITIONS,\n executeInteractiveTool,\n waitForPlanApproval,\n type PlanApprovalDecision,\n} from \"./interactive-tools.js\";\nimport { loadConfig } from \"./config-store.js\";\nimport {\n isServerTool,\n loadServerToolDefinitions,\n executeServerTool,\n} from \"./server-tools.js\";\nimport { mcpClientManager } from \"./mcp-client.js\";\nimport { getPermissionMode, isToolAllowedByPermission } from \"./permission-modes.js\";\nimport { runBeforeToolHook, runAfterToolHook, type HookConfig } from \"./hooks.js\";\nimport type { AgentEventEmitter } from \"./agent-events.js\";\n\nimport { resetGitContext } from \"./git-context.js\";\nimport { resetClaudeMdCache } from \"./claude-md-loader.js\";\nimport { clearReadCache } from \"./tools/file-ops.js\";\nimport { resetAgentConfigCache } from \"./agent-config.js\";\n\n// ============================================================================\n// SESSION STATE\n// ============================================================================\n\nlet sessionInputTokens = 0;\nlet sessionOutputTokens = 0;\n\nexport function getSessionTokens(): { input: number; output: number } {\n return { input: sessionInputTokens, output: sessionOutputTokens };\n}\n\nexport function addSessionTokens(input: number, output: number): void {\n sessionInputTokens += input;\n sessionOutputTokens += output;\n}\n\n/**\n * Reset all CLI-only session state. Call when starting a new conversation.\n * Does NOT reset activeModel or permissionMode.\n */\nexport function resetSessionState(): void {\n sessionInputTokens = 0;\n sessionOutputTokens = 0;\n resetSessionLoopDetector();\n resetGitContext();\n resetClaudeMdCache();\n clearReadCache();\n resetAgentConfigCache();\n}\n\n// Loop detector — managed externally by the main loop\nimport { LoopDetector } from \"../../shared/agent-core.js\";\n\nlet sessionLoopDetector: LoopDetector | null = null;\n\nexport function getSessionLoopDetector(): LoopDetector | null {\n return sessionLoopDetector;\n}\n\nexport function setSessionLoopDetector(ld: LoopDetector): void {\n sessionLoopDetector = ld;\n}\n\nexport function resetSessionLoopDetector(): void {\n sessionLoopDetector = null;\n}\n\n// No artificial turn cap\nexport const CLI_NO_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// ============================================================================\n// TOOL DEFINITIONS\n// ============================================================================\n\nexport async function getTools(allowedTools?: string[], disallowedTools?: string[]): Promise<{ tools: Anthropic.Tool[]; serverToolCount: number }> {\n const localTools: Anthropic.Tool[] = LOCAL_TOOL_DEFINITIONS.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema as Anthropic.Tool[\"input_schema\"],\n }));\n\n const interactiveTools: Anthropic.Tool[] = INTERACTIVE_TOOL_DEFINITIONS.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema as Anthropic.Tool[\"input_schema\"],\n }));\n localTools.push(...interactiveTools);\n\n let serverTools: Anthropic.Tool[] = [];\n try {\n serverTools = await loadServerToolDefinitions();\n } catch {\n // Server tools silently unavailable\n }\n\n const localNames = new Set(localTools.map(t => t.name));\n const uniqueServerTools = serverTools.filter(t => !localNames.has(t.name));\n\n const mcpTools = mcpClientManager.getTools();\n\n let allTools = [...localTools, ...uniqueServerTools, ...mcpTools];\n\n if (allowedTools && allowedTools.length > 0) {\n const allowed = new Set(allowedTools);\n allTools = allTools.filter(t => allowed.has(t.name));\n }\n if (disallowedTools && disallowedTools.length > 0) {\n const disallowed = new Set(disallowedTools);\n allTools = allTools.filter(t => !disallowed.has(t.name));\n }\n\n return { tools: allTools, serverToolCount: uniqueServerTools.length };\n}\n\n/** Exposed for /status command */\nexport async function getServerToolCount(): Promise<number> {\n try {\n const defs = await loadServerToolDefinitions();\n return defs.length;\n } catch {\n return 0;\n }\n}\n\n// ============================================================================\n// TOOL EXECUTOR BUILDER\n// ============================================================================\n\nconst INTERACTIVE_TOOL_NAMES = new Set(INTERACTIVE_TOOL_DEFINITIONS.map(t => t.name));\n\nexport function buildToolExecutor(\n hooks: HookConfig[],\n abortSignal?: AbortSignal,\n emitter?: AgentEventEmitter,\n): (name: string, input: Record<string, unknown>) => Promise<{ success: boolean; output: string }> {\n return async (name: string, input: Record<string, unknown>) => {\n if (!name) return { success: false, output: \"Tool call missing name — skipping.\" };\n\n if (!isToolAllowedByPermission(name)) {\n return { success: false, output: `Tool \"${name}\" blocked by ${getPermissionMode()} mode. Switch modes with /mode.` };\n }\n\n let effectiveInput = input;\n if (hooks.length > 0) {\n let hookResult;\n try {\n hookResult = await runBeforeToolHook(hooks, name, input);\n } catch (hookErr: any) {\n return { success: false, output: `Hook error for ${name}: ${hookErr.message || hookErr}` };\n }\n if (!hookResult.allow) return { success: false, output: hookResult.message || \"Blocked by hook\" };\n if (hookResult.modifiedInput) effectiveInput = hookResult.modifiedInput;\n }\n\n let result: { success: boolean; output: string };\n if (INTERACTIVE_TOOL_NAMES.has(name)) {\n result = await executeInteractiveTool(name, effectiveInput);\n if (name === \"exit_plan_mode\" && result.success) {\n const decision: PlanApprovalDecision = await waitForPlanApproval(abortSignal);\n switch (decision.action) {\n case \"execute\": result = { success: true, output: `__PLAN_APPROVED_CLEAN__\\n${result.output}` }; break;\n case \"edit\": result = { success: true, output: \"Plan returned for revision. Make changes and use ExitPlanMode again when ready.\" }; break;\n case \"feedback\": result = { success: true, output: `User feedback on plan:\\n\\n${decision.feedback || \"(no feedback provided)\"}\\n\\nRevise the plan based on this feedback, then use ExitPlanMode again.` }; break;\n case \"cancel\": result = { success: true, output: \"Plan cancelled by user. Do not proceed with implementation.\" }; break;\n }\n }\n } else if (isLocalTool(name)) {\n result = await executeLocalTool(name, effectiveInput, abortSignal);\n } else if (isServerTool(name)) {\n result = await executeServerTool(name, effectiveInput, emitter);\n } else if (mcpClientManager.isMcpTool(name)) {\n result = await mcpClientManager.callTool(name, effectiveInput);\n } else {\n result = { success: false, output: `Unknown tool: ${name}` };\n }\n\n if (hooks.length > 0) {\n try {\n const afterResult = await runAfterToolHook(hooks, name, result.output, result.success);\n if (afterResult.modifiedOutput !== undefined) result = { ...result, output: afterResult.modifiedOutput };\n } catch {\n // After-hook failure is non-fatal — preserve original result\n }\n }\n\n return result;\n };\n}\n\n// ============================================================================\n// TELEMETRY HELPERS\n// ============================================================================\n\nexport function truncateResult(output: string, maxLen: number): string {\n if (output.length <= maxLen) return output;\n return output.slice(0, maxLen) + `... (${output.length} chars total)`;\n}\n\nexport function classifyToolError(output: string): string {\n const lower = output.toLowerCase();\n if (/timed?\\s*out|timeout/.test(lower)) return \"timeout\";\n if (/permission denied|eacces/.test(lower)) return \"permission\";\n if (/not found|no such file/.test(lower)) return \"not_found\";\n if (/command not found|exit code 127/.test(lower)) return \"command_not_found\";\n if (/import\\b.*\\berror|error\\b.*\\bimport/.test(lower)) return \"import_error\";\n if (/syntax|parse/.test(lower)) return \"syntax_error\";\n if (/externally-managed/.test(lower)) return \"env_managed\";\n return \"unknown\";\n}\n\n// ============================================================================\n// AUTH CHECK\n// ============================================================================\n\nexport function canUseAgent(): { ready: boolean; reason?: string } {\n const config = loadConfig();\n const hasToken = !!(config.access_token && config.refresh_token);\n const hasApiKey = !!process.env.ANTHROPIC_API_KEY;\n if (hasToken || hasApiKey) return { ready: true };\n return { ready: false, reason: \"Run `whale login` to authenticate.\" };\n}\n"],"mappings":"AAAA;AACA;AACA;;AAGA,SACEA,sBAAsB,EACtBC,gBAAgB,EAChBC,WAAW,QACN,kBAAkB;AACzB,SACEC,4BAA4B,EAC5BC,sBAAsB,EACtBC,mBAAmB,QAEd,wBAAwB;AAC/B,SAASC,UAAU,QAAQ,mBAAmB;AAC9C,SACEC,YAAY,EACZC,yBAAyB,EACzBC,iBAAiB,QACZ,mBAAmB;AAC1B,SAASC,gBAAgB,QAAQ,iBAAiB;AAClD,SAASC,iBAAiB,EAAEC,yBAAyB,QAAQ,uBAAuB;AACpF,SAASC,iBAAiB,EAAEC,gBAAgB,QAAyB,YAAY;AAGjF,SAASC,eAAe,QAAQ,kBAAkB;AAClD,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,cAAc,QAAQ,qBAAqB;AACpD,SAASC,qBAAqB,QAAQ,mBAAmB;;AAEzD;AACA;AACA;;AAEA,IAAIC,kBAAkB,GAAG,CAAC;AAC1B,IAAIC,mBAAmB,GAAG,CAAC;AAE3B,OAAO,SAASC,gBAAgBA,CAAA,EAAsC;EACpE,OAAO;IAAEC,KAAK,EAAEH,kBAAkB;IAAEI,MAAM,EAAEH;EAAoB,CAAC;AACnE;AAEA,OAAO,SAASI,gBAAgBA,CAACF,KAAa,EAAEC,MAAc,EAAQ;EACpEJ,kBAAkB,IAAIG,KAAK;EAC3BF,mBAAmB,IAAIG,MAAM;AAC/B;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAAA,EAAS;EACxCN,kBAAkB,GAAG,CAAC;EACtBC,mBAAmB,GAAG,CAAC;EACvBM,wBAAwB,CAAC,CAAC;EAC1BX,eAAe,CAAC,CAAC;EACjBC,kBAAkB,CAAC,CAAC;EACpBC,cAAc,CAAC,CAAC;EAChBC,qBAAqB,CAAC,CAAC;AACzB;;AAEA;;AAGA,IAAIS,mBAAwC,GAAG,IAAI;AAEnD,OAAO,SAASC,sBAAsBA,CAAA,EAAwB;EAC5D,OAAOD,mBAAmB;AAC5B;AAEA,OAAO,SAASE,sBAAsBA,CAACC,EAAgB,EAAQ;EAC7DH,mBAAmB,GAAGG,EAAE;AAC1B;AAEA,OAAO,SAASJ,wBAAwBA,CAAA,EAAS;EAC/CC,mBAAmB,GAAG,IAAI;AAC5B;;AAEA;AACA,OAAO,MAAMI,YAAY,GAAGC,MAAM,CAACC,gBAAgB;;AAEnD;AACA;AACA;;AAEA,OAAO,eAAeC,QAAQA,CAACC,YAAuB,EAAEC,eAA0B,EAAiE;EACjJ,MAAMC,UAA4B,GAAGrC,sBAAsB,CAACsC,GAAG,CAAEC,CAAC,KAAM;IACtEC,IAAI,EAAED,CAAC,CAACC,IAAI;IACZC,WAAW,EAAEF,CAAC,CAACE,WAAW;IAC1BC,YAAY,EAAEH,CAAC,CAACG;EAClB,CAAC,CAAC,CAAC;EAEH,MAAMC,gBAAkC,GAAGxC,4BAA4B,CAACmC,GAAG,CAAEC,CAAC,KAAM;IAClFC,IAAI,EAAED,CAAC,CAACC,IAAI;IACZC,WAAW,EAAEF,CAAC,CAACE,WAAW;IAC1BC,YAAY,EAAEH,CAAC,CAACG;EAClB,CAAC,CAAC,CAAC;EACHL,UAAU,CAACO,IAAI,CAAC,GAAGD,gBAAgB,CAAC;EAEpC,IAAIE,WAA6B,GAAG,EAAE;EACtC,IAAI;IACFA,WAAW,GAAG,MAAMrC,yBAAyB,CAAC,CAAC;EACjD,CAAC,CAAC,MAAM;IACN;EAAA;EAGF,MAAMsC,UAAU,GAAG,IAAIC,GAAG,CAACV,UAAU,CAACC,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,IAAI,CAAC,CAAC;EACvD,MAAMQ,iBAAiB,GAAGH,WAAW,CAACI,MAAM,CAACV,CAAC,IAAI,CAACO,UAAU,CAACI,GAAG,CAACX,CAAC,CAACC,IAAI,CAAC,CAAC;EAE1E,MAAMW,QAAQ,GAAGzC,gBAAgB,CAACwB,QAAQ,CAAC,CAAC;EAE5C,IAAIkB,QAAQ,GAAG,CAAC,GAAGf,UAAU,EAAE,GAAGW,iBAAiB,EAAE,GAAGG,QAAQ,CAAC;EAEjE,IAAIhB,YAAY,IAAIA,YAAY,CAACkB,MAAM,GAAG,CAAC,EAAE;IAC3C,MAAMC,OAAO,GAAG,IAAIP,GAAG,CAACZ,YAAY,CAAC;IACrCiB,QAAQ,GAAGA,QAAQ,CAACH,MAAM,CAACV,CAAC,IAAIe,OAAO,CAACJ,GAAG,CAACX,CAAC,CAACC,IAAI,CAAC,CAAC;EACtD;EACA,IAAIJ,eAAe,IAAIA,eAAe,CAACiB,MAAM,GAAG,CAAC,EAAE;IACjD,MAAME,UAAU,GAAG,IAAIR,GAAG,CAACX,eAAe,CAAC;IAC3CgB,QAAQ,GAAGA,QAAQ,CAACH,MAAM,CAACV,CAAC,IAAI,CAACgB,UAAU,CAACL,GAAG,CAACX,CAAC,CAACC,IAAI,CAAC,CAAC;EAC1D;EAEA,OAAO;IAAEgB,KAAK,EAAEJ,QAAQ;IAAEK,eAAe,EAAET,iBAAiB,CAACK;EAAO,CAAC;AACvE;;AAEA;AACA,OAAO,eAAeK,kBAAkBA,CAAA,EAAoB;EAC1D,IAAI;IACF,MAAMC,IAAI,GAAG,MAAMnD,yBAAyB,CAAC,CAAC;IAC9C,OAAOmD,IAAI,CAACN,MAAM;EACpB,CAAC,CAAC,MAAM;IACN,OAAO,CAAC;EACV;AACF;;AAEA;AACA;AACA;;AAEA,MAAMO,sBAAsB,GAAG,IAAIb,GAAG,CAAC5C,4BAA4B,CAACmC,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,IAAI,CAAC,CAAC;AAErF,OAAO,SAASqB,iBAAiBA,CAC/BC,KAAmB,EACnBC,WAAyB,EACzBC,OAA2B,EACsE;EACjG,OAAO,OAAOxB,IAAY,EAAElB,KAA8B,KAAK;IAC7D,IAAI,CAACkB,IAAI,EAAE,OAAO;MAAEyB,OAAO,EAAE,KAAK;MAAE1C,MAAM,EAAE;IAAqC,CAAC;IAElF,IAAI,CAACX,yBAAyB,CAAC4B,IAAI,CAAC,EAAE;MACpC,OAAO;QAAEyB,OAAO,EAAE,KAAK;QAAE1C,MAAM,EAAE,SAASiB,IAAI,gBAAgB7B,iBAAiB,CAAC,CAAC;MAAkC,CAAC;IACtH;IAEA,IAAIuD,cAAc,GAAG5C,KAAK;IAC1B,IAAIwC,KAAK,CAACT,MAAM,GAAG,CAAC,EAAE;MACpB,IAAIc,UAAU;MACd,IAAI;QACFA,UAAU,GAAG,MAAMtD,iBAAiB,CAACiD,KAAK,EAAEtB,IAAI,EAAElB,KAAK,CAAC;MAC1D,CAAC,CAAC,OAAO8C,OAAY,EAAE;QACrB,OAAO;UAAEH,OAAO,EAAE,KAAK;UAAE1C,MAAM,EAAE,kBAAkBiB,IAAI,KAAK4B,OAAO,CAACC,OAAO,IAAID,OAAO;QAAG,CAAC;MAC5F;MACA,IAAI,CAACD,UAAU,CAACG,KAAK,EAAE,OAAO;QAAEL,OAAO,EAAE,KAAK;QAAE1C,MAAM,EAAE4C,UAAU,CAACE,OAAO,IAAI;MAAkB,CAAC;MACjG,IAAIF,UAAU,CAACI,aAAa,EAAEL,cAAc,GAAGC,UAAU,CAACI,aAAa;IACzE;IAEA,IAAIC,MAA4C;IAChD,IAAIZ,sBAAsB,CAACV,GAAG,CAACV,IAAI,CAAC,EAAE;MACpCgC,MAAM,GAAG,MAAMpE,sBAAsB,CAACoC,IAAI,EAAE0B,cAAc,CAAC;MAC3D,IAAI1B,IAAI,KAAK,gBAAgB,IAAIgC,MAAM,CAACP,OAAO,EAAE;QAC/C,MAAMQ,QAA8B,GAAG,MAAMpE,mBAAmB,CAAC0D,WAAW,CAAC;QAC7E,QAAQU,QAAQ,CAACC,MAAM;UACrB,KAAK,SAAS;YAAEF,MAAM,GAAG;cAAEP,OAAO,EAAE,IAAI;cAAE1C,MAAM,EAAE,4BAA4BiD,MAAM,CAACjD,MAAM;YAAG,CAAC;YAAE;UACjG,KAAK,MAAM;YAAEiD,MAAM,GAAG;cAAEP,OAAO,EAAE,IAAI;cAAE1C,MAAM,EAAE;YAAkF,CAAC;YAAE;UACpI,KAAK,UAAU;YAAEiD,MAAM,GAAG;cAAEP,OAAO,EAAE,IAAI;cAAE1C,MAAM,EAAE,6BAA6BkD,QAAQ,CAACE,QAAQ,IAAI,wBAAwB;YAA2E,CAAC;YAAE;UAC3M,KAAK,QAAQ;YAAEH,MAAM,GAAG;cAAEP,OAAO,EAAE,IAAI;cAAE1C,MAAM,EAAE;YAA8D,CAAC;YAAE;QACpH;MACF;IACF,CAAC,MAAM,IAAIrB,WAAW,CAACsC,IAAI,CAAC,EAAE;MAC5BgC,MAAM,GAAG,MAAMvE,gBAAgB,CAACuC,IAAI,EAAE0B,cAAc,EAAEH,WAAW,CAAC;IACpE,CAAC,MAAM,IAAIxD,YAAY,CAACiC,IAAI,CAAC,EAAE;MAC7BgC,MAAM,GAAG,MAAM/D,iBAAiB,CAAC+B,IAAI,EAAE0B,cAAc,EAAEF,OAAO,CAAC;IACjE,CAAC,MAAM,IAAItD,gBAAgB,CAACkE,SAAS,CAACpC,IAAI,CAAC,EAAE;MAC3CgC,MAAM,GAAG,MAAM9D,gBAAgB,CAACmE,QAAQ,CAACrC,IAAI,EAAE0B,cAAc,CAAC;IAChE,CAAC,MAAM;MACLM,MAAM,GAAG;QAAEP,OAAO,EAAE,KAAK;QAAE1C,MAAM,EAAE,iBAAiBiB,IAAI;MAAG,CAAC;IAC9D;IAEA,IAAIsB,KAAK,CAACT,MAAM,GAAG,CAAC,EAAE;MACpB,IAAI;QACF,MAAMyB,WAAW,GAAG,MAAMhE,gBAAgB,CAACgD,KAAK,EAAEtB,IAAI,EAAEgC,MAAM,CAACjD,MAAM,EAAEiD,MAAM,CAACP,OAAO,CAAC;QACtF,IAAIa,WAAW,CAACC,cAAc,KAAKC,SAAS,EAAER,MAAM,GAAG;UAAE,GAAGA,MAAM;UAAEjD,MAAM,EAAEuD,WAAW,CAACC;QAAe,CAAC;MAC1G,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ;IAEA,OAAOP,MAAM;EACf,CAAC;AACH;;AAEA;AACA;AACA;;AAEA,OAAO,SAASS,cAAcA,CAAC1D,MAAc,EAAE2D,MAAc,EAAU;EACrE,IAAI3D,MAAM,CAAC8B,MAAM,IAAI6B,MAAM,EAAE,OAAO3D,MAAM;EAC1C,OAAOA,MAAM,CAAC4D,KAAK,CAAC,CAAC,EAAED,MAAM,CAAC,GAAG,QAAQ3D,MAAM,CAAC8B,MAAM,eAAe;AACvE;AAEA,OAAO,SAAS+B,iBAAiBA,CAAC7D,MAAc,EAAU;EACxD,MAAM8D,KAAK,GAAG9D,MAAM,CAAC+D,WAAW,CAAC,CAAC;EAClC,IAAI,sBAAsB,CAACC,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,SAAS;EACxD,IAAI,0BAA0B,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,YAAY;EAC/D,IAAI,wBAAwB,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,WAAW;EAC5D,IAAI,iCAAiC,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,mBAAmB;EAC7E,IAAI,qCAAqC,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,cAAc;EAC5E,IAAI,cAAc,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,cAAc;EACrD,IAAI,oBAAoB,CAACE,IAAI,CAACF,KAAK,CAAC,EAAE,OAAO,aAAa;EAC1D,OAAO,SAAS;AAClB;;AAEA;AACA;AACA;;AAEA,OAAO,SAASG,WAAWA,CAAA,EAAwC;EACjE,MAAMC,MAAM,GAAGnF,UAAU,CAAC,CAAC;EAC3B,MAAMoF,QAAQ,GAAG,CAAC,EAAED,MAAM,CAACE,YAAY,IAAIF,MAAM,CAACG,aAAa,CAAC;EAChE,MAAMC,SAAS,GAAG,CAAC,CAACC,OAAO,CAACC,GAAG,CAACC,iBAAiB;EACjD,IAAIN,QAAQ,IAAIG,SAAS,EAAE,OAAO;IAAEI,KAAK,EAAE;EAAK,CAAC;EACjD,OAAO;IAAEA,KAAK,EAAE,KAAK;IAAEC,MAAM,EAAE;EAAqC,CAAC;AACvE","ignoreList":[]}
|
|
@@ -1148,7 +1148,7 @@ export function classifyToolError(output) {
|
|
|
1148
1148
|
export function canUseAgent() {
|
|
1149
1149
|
const config = loadConfig();
|
|
1150
1150
|
const hasToken = !!(config.access_token && config.refresh_token);
|
|
1151
|
-
const hasApiKey = !!
|
|
1151
|
+
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
|
1152
1152
|
if (hasToken || hasApiKey) return {
|
|
1153
1153
|
ready: true
|
|
1154
1154
|
};
|