whale-code 6.4.0

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 (319) hide show
  1. package/README.md +95 -0
  2. package/bin/swag-agent.js +9 -0
  3. package/bin/swagmanager-mcp.js +321 -0
  4. package/dist/cli/app.d.ts +26 -0
  5. package/dist/cli/app.js +64 -0
  6. package/dist/cli/chat/AgentSelector.d.ts +14 -0
  7. package/dist/cli/chat/AgentSelector.js +14 -0
  8. package/dist/cli/chat/ChatApp.d.ts +9 -0
  9. package/dist/cli/chat/ChatApp.js +267 -0
  10. package/dist/cli/chat/ChatInput.d.ts +39 -0
  11. package/dist/cli/chat/ChatInput.js +509 -0
  12. package/dist/cli/chat/MarkdownText.d.ts +10 -0
  13. package/dist/cli/chat/MarkdownText.js +20 -0
  14. package/dist/cli/chat/MessageList.d.ts +37 -0
  15. package/dist/cli/chat/MessageList.js +80 -0
  16. package/dist/cli/chat/ModelSelector.d.ts +20 -0
  17. package/dist/cli/chat/ModelSelector.js +73 -0
  18. package/dist/cli/chat/RewindViewer.d.ts +26 -0
  19. package/dist/cli/chat/RewindViewer.js +185 -0
  20. package/dist/cli/chat/StoreSelector.d.ts +14 -0
  21. package/dist/cli/chat/StoreSelector.js +24 -0
  22. package/dist/cli/chat/StreamingText.d.ts +12 -0
  23. package/dist/cli/chat/StreamingText.js +12 -0
  24. package/dist/cli/chat/SubagentPanel.d.ts +45 -0
  25. package/dist/cli/chat/SubagentPanel.js +110 -0
  26. package/dist/cli/chat/TeamPanel.d.ts +21 -0
  27. package/dist/cli/chat/TeamPanel.js +42 -0
  28. package/dist/cli/chat/ToolIndicator.d.ts +25 -0
  29. package/dist/cli/chat/ToolIndicator.js +436 -0
  30. package/dist/cli/chat/hooks/useAgentLoop.d.ts +39 -0
  31. package/dist/cli/chat/hooks/useAgentLoop.js +382 -0
  32. package/dist/cli/chat/hooks/useSlashCommands.d.ts +37 -0
  33. package/dist/cli/chat/hooks/useSlashCommands.js +387 -0
  34. package/dist/cli/commands/config-cmd.d.ts +10 -0
  35. package/dist/cli/commands/config-cmd.js +99 -0
  36. package/dist/cli/commands/doctor.d.ts +14 -0
  37. package/dist/cli/commands/doctor.js +172 -0
  38. package/dist/cli/commands/init.d.ts +16 -0
  39. package/dist/cli/commands/init.js +278 -0
  40. package/dist/cli/commands/mcp.d.ts +12 -0
  41. package/dist/cli/commands/mcp.js +162 -0
  42. package/dist/cli/login/LoginApp.d.ts +7 -0
  43. package/dist/cli/login/LoginApp.js +157 -0
  44. package/dist/cli/print-mode.d.ts +31 -0
  45. package/dist/cli/print-mode.js +202 -0
  46. package/dist/cli/serve-mode.d.ts +37 -0
  47. package/dist/cli/serve-mode.js +636 -0
  48. package/dist/cli/services/agent-definitions.d.ts +25 -0
  49. package/dist/cli/services/agent-definitions.js +91 -0
  50. package/dist/cli/services/agent-events.d.ts +178 -0
  51. package/dist/cli/services/agent-events.js +175 -0
  52. package/dist/cli/services/agent-loop.d.ts +90 -0
  53. package/dist/cli/services/agent-loop.js +762 -0
  54. package/dist/cli/services/agent-worker-base.d.ts +97 -0
  55. package/dist/cli/services/agent-worker-base.js +220 -0
  56. package/dist/cli/services/auth-service.d.ts +30 -0
  57. package/dist/cli/services/auth-service.js +160 -0
  58. package/dist/cli/services/background-processes.d.ts +126 -0
  59. package/dist/cli/services/background-processes.js +318 -0
  60. package/dist/cli/services/browser-auth.d.ts +24 -0
  61. package/dist/cli/services/browser-auth.js +180 -0
  62. package/dist/cli/services/claude-md-loader.d.ts +16 -0
  63. package/dist/cli/services/claude-md-loader.js +58 -0
  64. package/dist/cli/services/config-store.d.ts +47 -0
  65. package/dist/cli/services/config-store.js +79 -0
  66. package/dist/cli/services/debug-log.d.ts +10 -0
  67. package/dist/cli/services/debug-log.js +52 -0
  68. package/dist/cli/services/error-logger.d.ts +58 -0
  69. package/dist/cli/services/error-logger.js +269 -0
  70. package/dist/cli/services/file-history.d.ts +21 -0
  71. package/dist/cli/services/file-history.js +83 -0
  72. package/dist/cli/services/format-server-response.d.ts +16 -0
  73. package/dist/cli/services/format-server-response.js +440 -0
  74. package/dist/cli/services/git-context.d.ts +11 -0
  75. package/dist/cli/services/git-context.js +66 -0
  76. package/dist/cli/services/hooks.d.ts +85 -0
  77. package/dist/cli/services/hooks.js +258 -0
  78. package/dist/cli/services/interactive-tools.d.ts +125 -0
  79. package/dist/cli/services/interactive-tools.js +260 -0
  80. package/dist/cli/services/keybinding-manager.d.ts +52 -0
  81. package/dist/cli/services/keybinding-manager.js +115 -0
  82. package/dist/cli/services/local-tools.d.ts +22 -0
  83. package/dist/cli/services/local-tools.js +697 -0
  84. package/dist/cli/services/lsp-manager.d.ts +18 -0
  85. package/dist/cli/services/lsp-manager.js +717 -0
  86. package/dist/cli/services/mcp-client.d.ts +48 -0
  87. package/dist/cli/services/mcp-client.js +157 -0
  88. package/dist/cli/services/memory-manager.d.ts +16 -0
  89. package/dist/cli/services/memory-manager.js +57 -0
  90. package/dist/cli/services/model-manager.d.ts +18 -0
  91. package/dist/cli/services/model-manager.js +71 -0
  92. package/dist/cli/services/model-router.d.ts +26 -0
  93. package/dist/cli/services/model-router.js +149 -0
  94. package/dist/cli/services/permission-modes.d.ts +13 -0
  95. package/dist/cli/services/permission-modes.js +43 -0
  96. package/dist/cli/services/rewind.d.ts +84 -0
  97. package/dist/cli/services/rewind.js +194 -0
  98. package/dist/cli/services/ripgrep.d.ts +28 -0
  99. package/dist/cli/services/ripgrep.js +138 -0
  100. package/dist/cli/services/sandbox.d.ts +29 -0
  101. package/dist/cli/services/sandbox.js +97 -0
  102. package/dist/cli/services/server-tools.d.ts +61 -0
  103. package/dist/cli/services/server-tools.js +543 -0
  104. package/dist/cli/services/session-persistence.d.ts +23 -0
  105. package/dist/cli/services/session-persistence.js +99 -0
  106. package/dist/cli/services/subagent-worker.d.ts +19 -0
  107. package/dist/cli/services/subagent-worker.js +41 -0
  108. package/dist/cli/services/subagent.d.ts +47 -0
  109. package/dist/cli/services/subagent.js +647 -0
  110. package/dist/cli/services/system-prompt.d.ts +7 -0
  111. package/dist/cli/services/system-prompt.js +198 -0
  112. package/dist/cli/services/team-lead.d.ts +73 -0
  113. package/dist/cli/services/team-lead.js +512 -0
  114. package/dist/cli/services/team-state.d.ts +77 -0
  115. package/dist/cli/services/team-state.js +398 -0
  116. package/dist/cli/services/teammate.d.ts +31 -0
  117. package/dist/cli/services/teammate.js +689 -0
  118. package/dist/cli/services/telemetry.d.ts +61 -0
  119. package/dist/cli/services/telemetry.js +209 -0
  120. package/dist/cli/services/tools/agent-tools.d.ts +14 -0
  121. package/dist/cli/services/tools/agent-tools.js +347 -0
  122. package/dist/cli/services/tools/file-ops.d.ts +15 -0
  123. package/dist/cli/services/tools/file-ops.js +487 -0
  124. package/dist/cli/services/tools/search-tools.d.ts +8 -0
  125. package/dist/cli/services/tools/search-tools.js +186 -0
  126. package/dist/cli/services/tools/shell-exec.d.ts +10 -0
  127. package/dist/cli/services/tools/shell-exec.js +168 -0
  128. package/dist/cli/services/tools/task-manager.d.ts +28 -0
  129. package/dist/cli/services/tools/task-manager.js +209 -0
  130. package/dist/cli/services/tools/web-tools.d.ts +11 -0
  131. package/dist/cli/services/tools/web-tools.js +395 -0
  132. package/dist/cli/setup/SetupApp.d.ts +9 -0
  133. package/dist/cli/setup/SetupApp.js +191 -0
  134. package/dist/cli/shared/MatrixIntro.d.ts +4 -0
  135. package/dist/cli/shared/MatrixIntro.js +83 -0
  136. package/dist/cli/shared/Theme.d.ts +74 -0
  137. package/dist/cli/shared/Theme.js +127 -0
  138. package/dist/cli/shared/WhaleBanner.d.ts +10 -0
  139. package/dist/cli/shared/WhaleBanner.js +12 -0
  140. package/dist/cli/shared/markdown.d.ts +21 -0
  141. package/dist/cli/shared/markdown.js +756 -0
  142. package/dist/cli/status/StatusApp.d.ts +4 -0
  143. package/dist/cli/status/StatusApp.js +105 -0
  144. package/dist/cli/stores/StoreApp.d.ts +7 -0
  145. package/dist/cli/stores/StoreApp.js +81 -0
  146. package/dist/index.d.ts +15 -0
  147. package/dist/index.js +538 -0
  148. package/dist/local-agent/connection.d.ts +48 -0
  149. package/dist/local-agent/connection.js +332 -0
  150. package/dist/local-agent/discovery.d.ts +18 -0
  151. package/dist/local-agent/discovery.js +146 -0
  152. package/dist/local-agent/executor.d.ts +34 -0
  153. package/dist/local-agent/executor.js +241 -0
  154. package/dist/local-agent/index.d.ts +14 -0
  155. package/dist/local-agent/index.js +198 -0
  156. package/dist/node/adapters/base.d.ts +35 -0
  157. package/dist/node/adapters/base.js +10 -0
  158. package/dist/node/adapters/discord.d.ts +29 -0
  159. package/dist/node/adapters/discord.js +299 -0
  160. package/dist/node/adapters/email.d.ts +23 -0
  161. package/dist/node/adapters/email.js +218 -0
  162. package/dist/node/adapters/imessage.d.ts +17 -0
  163. package/dist/node/adapters/imessage.js +118 -0
  164. package/dist/node/adapters/slack.d.ts +26 -0
  165. package/dist/node/adapters/slack.js +259 -0
  166. package/dist/node/adapters/sms.d.ts +23 -0
  167. package/dist/node/adapters/sms.js +161 -0
  168. package/dist/node/adapters/telegram.d.ts +17 -0
  169. package/dist/node/adapters/telegram.js +101 -0
  170. package/dist/node/adapters/webchat.d.ts +27 -0
  171. package/dist/node/adapters/webchat.js +160 -0
  172. package/dist/node/adapters/whatsapp.d.ts +28 -0
  173. package/dist/node/adapters/whatsapp.js +230 -0
  174. package/dist/node/cli.d.ts +2 -0
  175. package/dist/node/cli.js +325 -0
  176. package/dist/node/config.d.ts +17 -0
  177. package/dist/node/config.js +31 -0
  178. package/dist/node/runtime.d.ts +50 -0
  179. package/dist/node/runtime.js +351 -0
  180. package/dist/server/handlers/__test-utils__/mock-supabase.d.ts +11 -0
  181. package/dist/server/handlers/__test-utils__/mock-supabase.js +393 -0
  182. package/dist/server/handlers/analytics.d.ts +17 -0
  183. package/dist/server/handlers/analytics.js +266 -0
  184. package/dist/server/handlers/api-keys.d.ts +6 -0
  185. package/dist/server/handlers/api-keys.js +221 -0
  186. package/dist/server/handlers/billing.d.ts +33 -0
  187. package/dist/server/handlers/billing.js +272 -0
  188. package/dist/server/handlers/browser.d.ts +10 -0
  189. package/dist/server/handlers/browser.js +517 -0
  190. package/dist/server/handlers/catalog.d.ts +99 -0
  191. package/dist/server/handlers/catalog.js +976 -0
  192. package/dist/server/handlers/comms.d.ts +254 -0
  193. package/dist/server/handlers/comms.js +588 -0
  194. package/dist/server/handlers/creations.d.ts +6 -0
  195. package/dist/server/handlers/creations.js +479 -0
  196. package/dist/server/handlers/crm.d.ts +89 -0
  197. package/dist/server/handlers/crm.js +538 -0
  198. package/dist/server/handlers/discovery.d.ts +6 -0
  199. package/dist/server/handlers/discovery.js +288 -0
  200. package/dist/server/handlers/embeddings.d.ts +92 -0
  201. package/dist/server/handlers/embeddings.js +197 -0
  202. package/dist/server/handlers/enrichment.d.ts +8 -0
  203. package/dist/server/handlers/enrichment.js +768 -0
  204. package/dist/server/handlers/image-gen.d.ts +6 -0
  205. package/dist/server/handlers/image-gen.js +409 -0
  206. package/dist/server/handlers/inventory.d.ts +319 -0
  207. package/dist/server/handlers/inventory.js +447 -0
  208. package/dist/server/handlers/kali.d.ts +10 -0
  209. package/dist/server/handlers/kali.js +210 -0
  210. package/dist/server/handlers/llm-providers.d.ts +6 -0
  211. package/dist/server/handlers/llm-providers.js +673 -0
  212. package/dist/server/handlers/local-agent.d.ts +6 -0
  213. package/dist/server/handlers/local-agent.js +118 -0
  214. package/dist/server/handlers/meta-ads.d.ts +111 -0
  215. package/dist/server/handlers/meta-ads.js +2279 -0
  216. package/dist/server/handlers/nodes.d.ts +33 -0
  217. package/dist/server/handlers/nodes.js +699 -0
  218. package/dist/server/handlers/operations.d.ts +138 -0
  219. package/dist/server/handlers/operations.js +131 -0
  220. package/dist/server/handlers/platform.d.ts +23 -0
  221. package/dist/server/handlers/platform.js +227 -0
  222. package/dist/server/handlers/supply-chain.d.ts +19 -0
  223. package/dist/server/handlers/supply-chain.js +327 -0
  224. package/dist/server/handlers/transcription.d.ts +17 -0
  225. package/dist/server/handlers/transcription.js +121 -0
  226. package/dist/server/handlers/video-gen.d.ts +6 -0
  227. package/dist/server/handlers/video-gen.js +466 -0
  228. package/dist/server/handlers/voice.d.ts +8 -0
  229. package/dist/server/handlers/voice.js +1146 -0
  230. package/dist/server/handlers/workflow-steps.d.ts +86 -0
  231. package/dist/server/handlers/workflow-steps.js +2349 -0
  232. package/dist/server/handlers/workflows.d.ts +7 -0
  233. package/dist/server/handlers/workflows.js +989 -0
  234. package/dist/server/index.d.ts +1 -0
  235. package/dist/server/index.js +2427 -0
  236. package/dist/server/lib/batch-client.d.ts +80 -0
  237. package/dist/server/lib/batch-client.js +467 -0
  238. package/dist/server/lib/code-worker-pool.d.ts +31 -0
  239. package/dist/server/lib/code-worker-pool.js +224 -0
  240. package/dist/server/lib/code-worker.d.ts +1 -0
  241. package/dist/server/lib/code-worker.js +188 -0
  242. package/dist/server/lib/compaction-service.d.ts +32 -0
  243. package/dist/server/lib/compaction-service.js +162 -0
  244. package/dist/server/lib/logger.d.ts +19 -0
  245. package/dist/server/lib/logger.js +46 -0
  246. package/dist/server/lib/otel.d.ts +38 -0
  247. package/dist/server/lib/otel.js +126 -0
  248. package/dist/server/lib/pg-rate-limiter.d.ts +21 -0
  249. package/dist/server/lib/pg-rate-limiter.js +86 -0
  250. package/dist/server/lib/prompt-sanitizer.d.ts +37 -0
  251. package/dist/server/lib/prompt-sanitizer.js +177 -0
  252. package/dist/server/lib/provider-capabilities.d.ts +85 -0
  253. package/dist/server/lib/provider-capabilities.js +190 -0
  254. package/dist/server/lib/provider-failover.d.ts +74 -0
  255. package/dist/server/lib/provider-failover.js +210 -0
  256. package/dist/server/lib/rate-limiter.d.ts +39 -0
  257. package/dist/server/lib/rate-limiter.js +147 -0
  258. package/dist/server/lib/server-agent-loop.d.ts +107 -0
  259. package/dist/server/lib/server-agent-loop.js +667 -0
  260. package/dist/server/lib/server-subagent.d.ts +78 -0
  261. package/dist/server/lib/server-subagent.js +203 -0
  262. package/dist/server/lib/session-checkpoint.d.ts +51 -0
  263. package/dist/server/lib/session-checkpoint.js +145 -0
  264. package/dist/server/lib/ssrf-guard.d.ts +13 -0
  265. package/dist/server/lib/ssrf-guard.js +240 -0
  266. package/dist/server/lib/supabase-client.d.ts +7 -0
  267. package/dist/server/lib/supabase-client.js +78 -0
  268. package/dist/server/lib/template-resolver.d.ts +31 -0
  269. package/dist/server/lib/template-resolver.js +215 -0
  270. package/dist/server/lib/utils.d.ts +16 -0
  271. package/dist/server/lib/utils.js +147 -0
  272. package/dist/server/local-agent-gateway.d.ts +82 -0
  273. package/dist/server/local-agent-gateway.js +426 -0
  274. package/dist/server/providers/anthropic.d.ts +20 -0
  275. package/dist/server/providers/anthropic.js +199 -0
  276. package/dist/server/providers/bedrock.d.ts +20 -0
  277. package/dist/server/providers/bedrock.js +194 -0
  278. package/dist/server/providers/gemini.d.ts +24 -0
  279. package/dist/server/providers/gemini.js +486 -0
  280. package/dist/server/providers/openai.d.ts +24 -0
  281. package/dist/server/providers/openai.js +522 -0
  282. package/dist/server/providers/registry.d.ts +32 -0
  283. package/dist/server/providers/registry.js +58 -0
  284. package/dist/server/providers/shared.d.ts +32 -0
  285. package/dist/server/providers/shared.js +124 -0
  286. package/dist/server/providers/types.d.ts +92 -0
  287. package/dist/server/providers/types.js +12 -0
  288. package/dist/server/proxy-handlers.d.ts +6 -0
  289. package/dist/server/proxy-handlers.js +89 -0
  290. package/dist/server/tool-router.d.ts +149 -0
  291. package/dist/server/tool-router.js +803 -0
  292. package/dist/server/validation.d.ts +24 -0
  293. package/dist/server/validation.js +301 -0
  294. package/dist/server/worker.d.ts +19 -0
  295. package/dist/server/worker.js +201 -0
  296. package/dist/setup.d.ts +8 -0
  297. package/dist/setup.js +181 -0
  298. package/dist/shared/agent-core.d.ts +157 -0
  299. package/dist/shared/agent-core.js +534 -0
  300. package/dist/shared/anthropic-types.d.ts +105 -0
  301. package/dist/shared/anthropic-types.js +7 -0
  302. package/dist/shared/api-client.d.ts +90 -0
  303. package/dist/shared/api-client.js +379 -0
  304. package/dist/shared/constants.d.ts +33 -0
  305. package/dist/shared/constants.js +80 -0
  306. package/dist/shared/sse-parser.d.ts +26 -0
  307. package/dist/shared/sse-parser.js +259 -0
  308. package/dist/shared/tool-dispatch.d.ts +52 -0
  309. package/dist/shared/tool-dispatch.js +191 -0
  310. package/dist/shared/types.d.ts +72 -0
  311. package/dist/shared/types.js +7 -0
  312. package/dist/updater.d.ts +25 -0
  313. package/dist/updater.js +140 -0
  314. package/dist/webchat/widget.d.ts +0 -0
  315. package/dist/webchat/widget.js +397 -0
  316. package/package.json +95 -0
  317. package/src/cli/services/builtin-skills/commit.md +19 -0
  318. package/src/cli/services/builtin-skills/review-pr.md +21 -0
  319. package/src/cli/services/builtin-skills/review.md +18 -0
@@ -0,0 +1,647 @@
1
+ /**
2
+ * Subagent System — Claude Code-style Task tool for spawning specialized agents
3
+ *
4
+ * Subagents run in isolated context, enabling:
5
+ * - Parallel exploration without polluting main context
6
+ * - Specialized prompts per agent type
7
+ * - Cost optimization (Haiku for simple tasks)
8
+ * - Resume capability for long-running tasks
9
+ */
10
+ import { readFileSync, existsSync, writeFileSync, mkdirSync, appendFileSync } from "fs";
11
+ import { join } from "path";
12
+ import { homedir, tmpdir } from "os";
13
+ import { LOCAL_TOOL_DEFINITIONS, } from "./local-tools.js";
14
+ import { LoopDetector, estimateCostUsd } from "../../shared/agent-core.js";
15
+ import { MODEL_MAP } from "../../shared/constants.js";
16
+ import { loadServerToolDefinitions, } from "./server-tools.js";
17
+ import { logSpan, generateSpanId, generateTraceId } from "./telemetry.js";
18
+ import { loadClaudeMd, getModel } from "./agent-loop.js";
19
+ import { getGlobalEmitter } from "./agent-events.js";
20
+ import { getAgentDefinition } from "./agent-definitions.js";
21
+ import { callAgentAPI, executeToolBlocks, extractTextBlocks, extractToolUseBlocks, getResponseText, yieldToEventLoop, yieldForRender, } from "./agent-worker-base.js";
22
+ // ============================================================================
23
+ // CONSTANTS
24
+ // ============================================================================
25
+ const AGENTS_DIR = join(homedir(), ".swagmanager", "agents");
26
+ // Claude Code pattern: subagents should be discrete tasks, not open-ended
27
+ // Low turn limit prevents infinite loops and forces focused execution
28
+ const MAX_TURNS = 8;
29
+ const SUBAGENT_MAX_OUTPUT_TOKENS = 32_000; // Claude Code parity — subagents get 32K output
30
+ // ============================================================================
31
+ // AGENT PROMPTS — specialized per type
32
+ // ============================================================================
33
+ // Build agent prompt with working directory context
34
+ function buildAgentPrompt(type, cwd) {
35
+ const cwdContext = `
36
+ ## Working Directory
37
+ You are working in: ${cwd}
38
+ All file paths should be relative to or absolute from this directory.
39
+ IMPORTANT: Focus ONLY on files within this directory. Do not get confused by other projects.
40
+ `;
41
+ // Check for custom agent definition first
42
+ const custom = getAgentDefinition(type);
43
+ if (custom)
44
+ return custom.prompt + cwdContext;
45
+ const prompts = {
46
+ explore: `You are an exploration agent. Your ONLY job is to quickly find specific information in the codebase, then STOP.
47
+
48
+ Tools available:
49
+ - glob: Find files by pattern (e.g., "**/*.ts")
50
+ - grep: Search file contents with regex
51
+ - read_file: Read file contents
52
+ - list_directory: List directory contents
53
+ ${cwdContext}
54
+ ## STOP CONDITIONS — You MUST stop when ANY of these are met:
55
+ 1. You found the specific information requested
56
+ 2. You've searched 3+ patterns without finding anything new
57
+ 3. You've read the key files that answer the question
58
+ 4. You've exhausted reasonable search patterns
59
+
60
+ ## Guidelines:
61
+ - Call multiple tools per turn — batch glob + grep + read_file in a single response
62
+ - Read only the necessary files to answer the question
63
+ - DO NOT continue exploring after you have the answer
64
+ - DO NOT read files that aren't directly relevant
65
+
66
+ ## Output Format:
67
+ Return a concise summary with:
68
+ - File paths and line numbers for relevant code
69
+ - Key code snippets (brief)
70
+ - Direct answer to the question asked
71
+
72
+ IMPORTANT: Complete in 2-4 turns. If you haven't found it by turn 4, summarize what you found and STOP.`,
73
+ plan: `You are a planning agent. Your ONLY job is to analyze the codebase and create an implementation plan, then STOP.
74
+
75
+ Tools available:
76
+ - glob: Find files by pattern
77
+ - grep: Search file contents
78
+ - read_file: Read file contents
79
+ - list_directory: List directory contents
80
+ ${cwdContext}
81
+ ## STOP CONDITIONS — You MUST stop when:
82
+ 1. You've identified the files that need changes
83
+ 2. You've understood the existing patterns/architecture
84
+ 3. You've created a concrete plan with specific steps
85
+
86
+ ## Guidelines:
87
+ - FIRST: Quick search to find relevant files
88
+ - Read only files needed to understand the architecture
89
+ - DO NOT read every file — focus on entry points and key modules
90
+ - Create the plan as soon as you understand the structure
91
+
92
+ ## Output Format — Return EXACTLY this structure:
93
+ ### Summary
94
+ [1-2 sentences on the approach]
95
+
96
+ ### Files to Modify
97
+ - path/to/file.ts: [what changes]
98
+
99
+ ### Implementation Steps
100
+ 1. [Specific step]
101
+ 2. [Specific step]
102
+
103
+ ### Risks
104
+ - [Any considerations]
105
+
106
+ IMPORTANT: Complete in 3-5 turns. If you haven't finished by turn 5, output your best plan and STOP.`,
107
+ "general-purpose": `You are an autonomous agent for discrete tasks. Complete the task, then STOP.
108
+
109
+ Tools available:
110
+ - File operations: read_file, write_file, edit_file, glob, grep
111
+ - Shell: run_command
112
+ - Search: search_files, search_content
113
+ - Web: web_fetch
114
+ ${cwdContext}
115
+ ## STOP CONDITIONS — You MUST stop when:
116
+ 1. The specific task is complete
117
+ 2. You've verified the changes work (if applicable)
118
+ 3. You encounter a blocker you cannot resolve
119
+
120
+ ## Guidelines:
121
+ - Understand what exists before making changes
122
+ - Make targeted changes — don't over-engineer
123
+ - Verify your changes if possible (run tests, check syntax)
124
+ - If blocked, explain the blocker and STOP
125
+
126
+ ## Output Format:
127
+ ### What I Did
128
+ [Brief summary of actions taken]
129
+
130
+ ### Files Modified
131
+ - path/to/file.ts: [change description]
132
+
133
+ ### Verification
134
+ [How you verified it works, or N/A]
135
+
136
+ ### Issues (if any)
137
+ [Any problems encountered]
138
+
139
+ IMPORTANT: This is a discrete task. Complete it in 4-6 turns maximum. Do not loop.`,
140
+ research: `You are a research agent. Find the specific information requested, then STOP.
141
+
142
+ Tools available:
143
+ - web_fetch: Fetch and parse web content
144
+ - web_search: Search the web
145
+ - read_file: Read local files
146
+ - grep: Search local file contents
147
+ ${cwdContext}
148
+ ## STOP CONDITIONS — You MUST stop when:
149
+ 1. You found the answer to the question
150
+ 2. You've checked 2-3 authoritative sources
151
+ 3. You've gathered enough information to answer
152
+
153
+ ## Guidelines:
154
+ - Search for official documentation first
155
+ - Check 2-3 sources, not 10
156
+ - DO NOT keep searching after you have the answer
157
+ - Summarize findings immediately when you have enough
158
+
159
+ ## Output Format:
160
+ ### Answer
161
+ [Direct answer to the question]
162
+
163
+ ### Key Points
164
+ - [Important detail 1]
165
+ - [Important detail 2]
166
+
167
+ ### Sources
168
+ - [URL 1]: [what it says]
169
+ - [URL 2]: [what it says]
170
+
171
+ ### Caveats
172
+ [Any version requirements or limitations]
173
+
174
+ IMPORTANT: Complete in 2-4 turns. Stop as soon as you have a good answer.`,
175
+ };
176
+ return prompts[type] || prompts["general-purpose"];
177
+ }
178
+ // ============================================================================
179
+ // AGENT STATE PERSISTENCE
180
+ // ============================================================================
181
+ function ensureAgentsDir() {
182
+ if (!existsSync(AGENTS_DIR))
183
+ mkdirSync(AGENTS_DIR, { recursive: true });
184
+ }
185
+ function saveAgentState(state) {
186
+ ensureAgentsDir();
187
+ const path = join(AGENTS_DIR, `${state.id}.json`);
188
+ writeFileSync(path, JSON.stringify(state, null, 2), "utf-8");
189
+ }
190
+ function loadAgentState(agentId) {
191
+ const path = join(AGENTS_DIR, `${agentId}.json`);
192
+ if (!existsSync(path))
193
+ return null;
194
+ try {
195
+ return JSON.parse(readFileSync(path, "utf-8"));
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ }
201
+ function generateAgentId() {
202
+ return `agent-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
203
+ }
204
+ // ============================================================================
205
+ // TOOL FILTERING — restrict tools per agent type
206
+ // ============================================================================
207
+ function getToolsForAgent(type) {
208
+ // Check for custom agent definition with explicit tools
209
+ const custom = getAgentDefinition(type);
210
+ if (custom?.tools && custom.tools.length > 0)
211
+ return custom.tools;
212
+ switch (type) {
213
+ case "explore":
214
+ return ["glob", "grep", "read_file", "list_directory", "search_files", "search_content"];
215
+ case "plan":
216
+ return ["glob", "grep", "read_file", "list_directory", "search_files", "search_content"];
217
+ case "research":
218
+ return ["web_fetch", "web_search", "read_file", "grep", "glob"];
219
+ case "general-purpose":
220
+ // All tools
221
+ return [
222
+ "read_file", "write_file", "edit_file", "list_directory",
223
+ "search_files", "search_content", "run_command",
224
+ "glob", "grep", "notebook_edit", "web_fetch", "tasks",
225
+ ];
226
+ default:
227
+ return ["read_file", "glob", "grep"];
228
+ }
229
+ }
230
+ async function getFilteredTools(type) {
231
+ const allowedNames = new Set(getToolsForAgent(type));
232
+ // Local tools
233
+ const localTools = LOCAL_TOOL_DEFINITIONS
234
+ .filter((t) => allowedNames.has(t.name))
235
+ .map((t) => ({
236
+ name: t.name,
237
+ description: t.description,
238
+ input_schema: t.input_schema,
239
+ }));
240
+ // Add web_search from server tools if allowed
241
+ if (allowedNames.has("web_search")) {
242
+ try {
243
+ const serverTools = await loadServerToolDefinitions();
244
+ const webSearch = serverTools.find((t) => t.name === "web_search");
245
+ if (webSearch)
246
+ localTools.push(webSearch);
247
+ }
248
+ catch { /* server tools unavailable */ }
249
+ }
250
+ return localTools;
251
+ }
252
+ // ============================================================================
253
+ // DISPLAY HELPERS — icons and colors for trace visualization
254
+ // ============================================================================
255
+ function getAgentIcon(type) {
256
+ const icons = {
257
+ explore: "🔍", // Magnifying glass for exploration
258
+ plan: "📋", // Clipboard for planning
259
+ "general-purpose": "🤖", // Robot for autonomous work
260
+ research: "📚", // Books for research
261
+ };
262
+ return icons[type] || "⚙️";
263
+ }
264
+ function getAgentColor(type) {
265
+ const colors = {
266
+ explore: "#3B82F6", // Blue for exploration
267
+ plan: "#8B5CF6", // Purple for planning
268
+ "general-purpose": "#10B981", // Green for general work
269
+ research: "#F59E0B", // Amber for research
270
+ };
271
+ return colors[type] || "#6B7280";
272
+ }
273
+ // ============================================================================
274
+ // SUBAGENT EXECUTION
275
+ // ============================================================================
276
+ // Progress emitter — uses event system instead of stderr to avoid UI conflicts
277
+ // The global emitter batches and routes these to ChatApp without causing re-renders
278
+ // NOTE: No module-level mutable state — agentId/turn passed through function params for parallel safety
279
+ function emitSubagentProgress(agentType, agentId, message, turn, toolName) {
280
+ const emitter = getGlobalEmitter();
281
+ emitter.emitSubagentProgress(agentId, agentType, message, turn, toolName);
282
+ }
283
+ export async function runSubagent(options) {
284
+ const { prompt, subagent_type, model, resume, max_turns, name, parentContext, parentTraceContext } = options;
285
+ const agentId = resume || generateAgentId();
286
+ // Inherit parent model when not specified (Anthropic pattern)
287
+ const modelId = model ? MODEL_MAP[model] : getModel();
288
+ const cwd = process.cwd();
289
+ const systemPrompt = buildAgentPrompt(subagent_type, cwd);
290
+ const startTime = Date.now();
291
+ const effectiveMaxTurns = max_turns ? Math.max(1, Math.min(50, max_turns)) : MAX_TURNS;
292
+ // Extract short description from prompt (first sentence or 60 chars)
293
+ const descMatch = prompt.match(/^[^.!?\n]+/);
294
+ const shortDescription = name || (descMatch
295
+ ? descMatch[0].slice(0, 60) + (descMatch[0].length > 60 ? "…" : "")
296
+ : prompt.slice(0, 60) + (prompt.length > 60 ? "…" : ""));
297
+ // Emit subagent start event
298
+ const emitter = getGlobalEmitter();
299
+ emitter.emitSubagentStart(agentId, subagent_type, model || "inherited", shortDescription);
300
+ // Load or create agent state
301
+ let state = resume ? loadAgentState(resume) : null;
302
+ if (!state) {
303
+ state = {
304
+ id: agentId,
305
+ type: subagent_type,
306
+ model: modelId,
307
+ messages: [],
308
+ toolsUsed: [],
309
+ createdAt: new Date().toISOString(),
310
+ updatedAt: new Date().toISOString(),
311
+ };
312
+ }
313
+ const loopDetector = new LoopDetector();
314
+ // Get filtered tools for this agent type
315
+ const tools = await getFilteredTools(subagent_type);
316
+ // Build full system prompt with optional parent context
317
+ let fullSystemPrompt = systemPrompt;
318
+ if (parentContext) {
319
+ fullSystemPrompt += `\n\n## Parent Conversation Context\n${parentContext}`;
320
+ }
321
+ // Add CLAUDE.md if available
322
+ const claudeMd = loadClaudeMd();
323
+ if (claudeMd) {
324
+ fullSystemPrompt += `\n\n## Project Instructions\n${claudeMd.content}`;
325
+ }
326
+ // Add user prompt to messages
327
+ state.messages.push({ role: "user", content: prompt });
328
+ let totalIn = 0;
329
+ let totalOut = 0;
330
+ let finalText = "";
331
+ // Create subagent span context — inherit parent's trace context for hierarchy
332
+ // IMPORTANT: Don't increment global turn number — subagent is part of parent turn
333
+ const subagentSpanId = generateSpanId();
334
+ const turnCtx = {
335
+ source: "claude_code",
336
+ serviceName: "whale-cli",
337
+ serviceVersion: "2.1.0",
338
+ model: modelId,
339
+ agentId,
340
+ agentName: name || `subagent-${subagent_type}`,
341
+ // Inherit parent's trace to keep hierarchy intact
342
+ traceId: parentTraceContext?.traceId || generateTraceId(),
343
+ spanId: subagentSpanId,
344
+ parentSpanId: parentTraceContext?.spanId, // Parent's spanId becomes our parentSpanId
345
+ conversationId: parentTraceContext?.conversationId,
346
+ turnNumber: parentTraceContext?.turnNumber, // Inherit parent turn, don't increment
347
+ userId: parentTraceContext?.userId,
348
+ userEmail: parentTraceContext?.userEmail,
349
+ traceFlags: 1,
350
+ };
351
+ try {
352
+ for (let turn = 0; turn < effectiveMaxTurns; turn++) {
353
+ // Emit progress and yield before API call to keep UI responsive
354
+ emitSubagentProgress(subagent_type, agentId, `turn ${turn + 1}: calling API...`, turn + 1);
355
+ await yieldForRender(); // Give Ink time to render the progress update
356
+ // Claude Code parity: thinking is DISABLED for all subagents.
357
+ // Subagents don't get extended thinking — all output tokens go to actual content.
358
+ // max_tokens = 32K matching Claude Code's hardcoded subagent default.
359
+ const apiStart = Date.now();
360
+ let response;
361
+ let lastError = null;
362
+ for (let attempt = 0; attempt < 3; attempt++) {
363
+ try {
364
+ response = await callAgentAPI({
365
+ modelId,
366
+ contextProfile: "subagent",
367
+ systemPrompt: fullSystemPrompt,
368
+ messages: state.messages,
369
+ tools,
370
+ thinkingEnabled: false,
371
+ maxOutputTokens: SUBAGENT_MAX_OUTPUT_TOKENS,
372
+ cacheLastTool: true,
373
+ });
374
+ lastError = null;
375
+ break;
376
+ }
377
+ catch (err) {
378
+ lastError = err;
379
+ if (attempt < 2 && (err.status === 429 || err.status === 500 || err.status === 529)) {
380
+ await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
381
+ continue;
382
+ }
383
+ throw err;
384
+ }
385
+ }
386
+ if (lastError)
387
+ throw lastError;
388
+ const apiDuration = Date.now() - apiStart;
389
+ // Yield after API call
390
+ await yieldToEventLoop();
391
+ totalIn += response.usage.input_tokens;
392
+ totalOut += response.usage.output_tokens;
393
+ // Log API call as child span
394
+ const apiCostUsd = estimateCostUsd(response.usage.input_tokens, response.usage.output_tokens, modelId);
395
+ logSpan({
396
+ action: "claude_api_request",
397
+ durationMs: apiDuration,
398
+ context: {
399
+ ...turnCtx,
400
+ spanId: generateSpanId(), // New span for this API call
401
+ parentSpanId: turnCtx.spanId, // Parent is the subagent
402
+ inputTokens: response.usage.input_tokens,
403
+ outputTokens: response.usage.output_tokens,
404
+ totalCost: apiCostUsd,
405
+ model: modelId,
406
+ },
407
+ details: {
408
+ "gen_ai.request.model": modelId,
409
+ "gen_ai.usage.input_tokens": response.usage.input_tokens,
410
+ "gen_ai.usage.output_tokens": response.usage.output_tokens,
411
+ "gen_ai.usage.cost": apiCostUsd,
412
+ agent_id: agentId,
413
+ agent_type: subagent_type,
414
+ turn: turn + 1,
415
+ stop_reason: response.stop_reason,
416
+ is_subagent_api: true,
417
+ },
418
+ });
419
+ // Yield to event loop to keep UI responsive
420
+ await yieldToEventLoop();
421
+ // Extract text and tool use using shared helpers
422
+ const textBlocks = extractTextBlocks(response.content);
423
+ const toolBlocks = extractToolUseBlocks(response.content);
424
+ if (textBlocks.length) {
425
+ finalText = getResponseText(response.content);
426
+ }
427
+ // No tool calls — we're done
428
+ if (toolBlocks.length === 0 || response.stop_reason === "end_turn") {
429
+ emitSubagentProgress(subagent_type, agentId, `done (${turn + 1} turn${turn > 0 ? "s" : ""})`, turn + 1);
430
+ break;
431
+ }
432
+ // Emit tool usage progress
433
+ const toolNames = toolBlocks.map(b => b.name).join(", ");
434
+ emitSubagentProgress(subagent_type, agentId, `using: ${toolNames}`, turn + 1);
435
+ // Execute tools using shared executeToolBlocks
436
+ const { toolResults, toolsUsed: turnToolsUsed } = await executeToolBlocks({
437
+ toolBlocks,
438
+ loopDetector,
439
+ callbacks: {
440
+ onToolStart: (toolName, input) => {
441
+ emitSubagentProgress(subagent_type, agentId, `running ${toolName}`, turn + 1, toolName);
442
+ emitter.emitSubagentToolStart(agentId, toolName, input);
443
+ },
444
+ onToolEnd: (toolName, success, durationMs) => {
445
+ emitter.emitSubagentToolEnd(agentId, toolName, success, durationMs);
446
+ // Log tool call as child span of the subagent
447
+ const tu = toolBlocks.find(b => b.name === toolName);
448
+ logSpan({
449
+ action: `tool.${toolName}`,
450
+ durationMs,
451
+ context: {
452
+ ...turnCtx,
453
+ spanId: generateSpanId(),
454
+ parentSpanId: turnCtx.spanId,
455
+ },
456
+ error: success ? undefined : "(see tool result)",
457
+ details: {
458
+ tool_type: "subagent_tool",
459
+ tool_input: tu?.input,
460
+ agent_id: agentId,
461
+ agent_type: subagent_type,
462
+ is_subagent_tool: true,
463
+ iteration: turn,
464
+ },
465
+ });
466
+ },
467
+ },
468
+ });
469
+ // Track tool usage
470
+ for (const tn of turnToolsUsed) {
471
+ if (!state.toolsUsed.includes(tn)) {
472
+ state.toolsUsed.push(tn);
473
+ }
474
+ }
475
+ // Append assistant response + tool results
476
+ state.messages.push({
477
+ role: "assistant",
478
+ content: response.content,
479
+ });
480
+ state.messages.push({
481
+ role: "user",
482
+ content: toolResults,
483
+ });
484
+ // Yield to event loop after tool execution
485
+ await yieldToEventLoop();
486
+ }
487
+ // Save state for potential resume
488
+ state.updatedAt = new Date().toISOString();
489
+ saveAgentState(state);
490
+ // Log the subagent's final response as a chat.assistant_response span
491
+ // This ensures the full output is visible in the telemetry waterfall
492
+ const subFinalCost = estimateCostUsd(totalIn, totalOut, modelId);
493
+ if (finalText) {
494
+ logSpan({
495
+ action: "chat.assistant_response",
496
+ durationMs: Date.now() - startTime,
497
+ context: {
498
+ ...turnCtx,
499
+ spanId: generateSpanId(),
500
+ parentSpanId: turnCtx.spanId,
501
+ inputTokens: totalIn,
502
+ outputTokens: totalOut,
503
+ totalCost: subFinalCost,
504
+ model: modelId,
505
+ },
506
+ details: {
507
+ response: finalText,
508
+ agent_id: agentId,
509
+ agent_name: name || `subagent-${subagent_type}`,
510
+ agent_type: subagent_type,
511
+ is_subagent: true,
512
+ "gen_ai.request.model": modelId,
513
+ "gen_ai.usage.input_tokens": totalIn,
514
+ "gen_ai.usage.output_tokens": totalOut,
515
+ "gen_ai.usage.cost": subFinalCost,
516
+ model: modelId,
517
+ input_tokens: totalIn,
518
+ output_tokens: totalOut,
519
+ turn_count: Math.floor(state.messages.length / 2),
520
+ tool_calls: state.toolsUsed.length,
521
+ tool_names: state.toolsUsed,
522
+ },
523
+ });
524
+ }
525
+ // Log telemetry with rich metadata for trace visualization
526
+ const subagentTotalCost = estimateCostUsd(totalIn, totalOut, modelId);
527
+ logSpan({
528
+ action: `subagent.${subagent_type}`,
529
+ durationMs: Date.now() - new Date(state.createdAt).getTime(),
530
+ context: {
531
+ ...turnCtx,
532
+ inputTokens: totalIn,
533
+ outputTokens: totalOut,
534
+ totalCost: subagentTotalCost,
535
+ },
536
+ details: {
537
+ // Core identification
538
+ agent_id: agentId,
539
+ agent_type: subagent_type,
540
+ model: modelId,
541
+ // Cost for SwiftUI display
542
+ "gen_ai.request.model": modelId,
543
+ "gen_ai.usage.input_tokens": totalIn,
544
+ "gen_ai.usage.output_tokens": totalOut,
545
+ "gen_ai.usage.cost": subagentTotalCost,
546
+ // Execution metrics
547
+ turns: state.messages.length / 2,
548
+ tools_used: state.toolsUsed,
549
+ tool_count: state.toolsUsed.length,
550
+ // Hierarchy info for visualization
551
+ is_subagent: true,
552
+ parent_trace_id: parentTraceContext?.traceId,
553
+ parent_span_id: parentTraceContext?.spanId,
554
+ // Rich display metadata
555
+ display_name: `${subagent_type.charAt(0).toUpperCase() + subagent_type.slice(1)} Agent`,
556
+ display_icon: getAgentIcon(subagent_type),
557
+ display_color: getAgentColor(subagent_type),
558
+ // Summary for trace feed (2000 chars for meaningful preview)
559
+ summary: finalText.slice(0, 2000) + (finalText.length > 2000 ? "..." : ""),
560
+ prompt_preview: prompt.slice(0, 200) + (prompt.length > 200 ? "..." : ""),
561
+ },
562
+ });
563
+ // Emit subagent done event
564
+ emitter.emitSubagentDone(agentId, subagent_type, true, finalText || "(No output from agent)", { input: totalIn, output: totalOut }, state.toolsUsed, Date.now() - startTime);
565
+ return {
566
+ success: true,
567
+ output: finalText || "(No output from agent)",
568
+ agentId,
569
+ tokensUsed: { input: totalIn, output: totalOut },
570
+ toolsUsed: state.toolsUsed,
571
+ };
572
+ }
573
+ catch (err) {
574
+ // Emit subagent error event
575
+ emitter.emitSubagentDone(agentId, subagent_type, false, `Agent error: ${err.message || err}`, { input: totalIn, output: totalOut }, state.toolsUsed, Date.now() - startTime);
576
+ return {
577
+ success: false,
578
+ output: `Agent error: ${err.message || err}`,
579
+ agentId,
580
+ tokensUsed: { input: totalIn, output: totalOut },
581
+ toolsUsed: state.toolsUsed,
582
+ };
583
+ }
584
+ }
585
+ // ============================================================================
586
+ // BACKGROUND AGENT EXECUTION
587
+ // ============================================================================
588
+ export async function runSubagentBackground(options) {
589
+ const agentId = options.resume || generateAgentId();
590
+ const outputFile = join(tmpdir(), `whale-agent-${agentId}.output`);
591
+ // Write initial status
592
+ writeFileSync(outputFile, `Agent ${agentId} started (${options.subagent_type})\n`, "utf-8");
593
+ // Import background process tracker (dynamic to avoid circular deps)
594
+ const bgModule = await import("./background-processes.js");
595
+ bgModule.registerBackgroundAgent(agentId, options.subagent_type, outputFile);
596
+ // Start agent in detached async — don't await
597
+ runSubagent({ ...options, resume: undefined }).then(result => {
598
+ appendFileSync(outputFile, `\n---DONE---\n${JSON.stringify({ success: result.success, agentId: result.agentId, output: result.output })}\n`, "utf-8");
599
+ import("./background-processes.js").then(m => m.markAgentDone(agentId, result.success));
600
+ }).catch(err => {
601
+ appendFileSync(outputFile, `\n---ERROR---\n${err.message}\n`, "utf-8");
602
+ import("./background-processes.js").then(m => m.markAgentDone(agentId, false));
603
+ });
604
+ return { agentId, outputFile };
605
+ }
606
+ // ============================================================================
607
+ // TOOL DEFINITION — for integration with main agent loop
608
+ // ============================================================================
609
+ // Following Claude Code pattern: discrete, focused tasks with clear completion criteria
610
+ export const TASK_TOOL_DEFINITION = {
611
+ name: "task",
612
+ description: `Launch a subagent in isolated context. Subagents have full tool access and batch multiple tool calls per turn (glob + grep + read_file in parallel). Launch multiple task calls in one response for parallel execution.
613
+
614
+ Use for any work requiring 3+ tool calls or touching multiple parts of the codebase.
615
+
616
+ Agent types:
617
+ - explore: Find specific files/code (2-4 turns, uses batch glob+grep)
618
+ - plan: Create implementation plan (3-5 turns)
619
+ - general-purpose: Complete a specific task (4-8 turns, full tool access)
620
+ - research: Look up specific info (2-4 turns)
621
+
622
+ Each agent completes autonomously and returns results.`,
623
+ input_schema: {
624
+ type: "object",
625
+ properties: {
626
+ prompt: {
627
+ type: "string",
628
+ description: "Specific task with clear completion criteria. Include: what to find/do, where to look, what to return.",
629
+ },
630
+ subagent_type: {
631
+ type: "string",
632
+ enum: ["explore", "plan", "general-purpose", "research"],
633
+ description: "Agent type: explore=find, plan=design, general-purpose=do, research=lookup.",
634
+ },
635
+ model: {
636
+ type: "string",
637
+ enum: ["sonnet", "opus", "haiku"],
638
+ description: "Optional model override. If not specified, inherits from parent. Prefer haiku for quick, straightforward tasks to minimize cost and latency.",
639
+ },
640
+ resume: {
641
+ type: "string",
642
+ description: "Agent ID to resume (rarely needed).",
643
+ },
644
+ },
645
+ required: ["prompt", "subagent_type"],
646
+ },
647
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * System Prompt Builder — assembles the full system prompt for the agent loop
3
+ *
4
+ * Extracted from agent-loop.ts for single-responsibility.
5
+ * All consumers should import from agent-loop.ts (re-export facade).
6
+ */
7
+ export declare function buildSystemPrompt(hasServerTools: boolean, effort?: "low" | "medium" | "high"): Promise<string>;