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,259 @@
1
+ /**
2
+ * Unified SSE Parser — ONE implementation replacing 4 duplicates.
3
+ *
4
+ * Used by:
5
+ * - agent-loop.ts (processStreamWithCallbacks for real-time UI)
6
+ * - subagent.ts (collectStreamResult for batch collection)
7
+ * - teammate.ts (collectStreamResult for batch collection)
8
+ * - server-agent-loop.ts (processStreamWithCallbacks for SSE relay)
9
+ */
10
+ // ============================================================================
11
+ // RAW SSE PARSER — yields typed events from HTTP response body
12
+ // ============================================================================
13
+ /**
14
+ * Parse SSE stream from proxy HTTP response into typed events.
15
+ * Handles `data: {...}\n\n` format with [DONE] sentinel.
16
+ */
17
+ export async function* parseSSEStream(body, signal) {
18
+ const reader = body.getReader();
19
+ const decoder = new TextDecoder();
20
+ let buffer = "";
21
+ try {
22
+ while (true) {
23
+ if (signal?.aborted)
24
+ break;
25
+ const { done, value } = await reader.read();
26
+ if (done)
27
+ break;
28
+ buffer += decoder.decode(value, { stream: true });
29
+ const lines = buffer.split("\n");
30
+ buffer = lines.pop() || "";
31
+ for (const line of lines) {
32
+ const trimmed = line.trim();
33
+ if (!trimmed || !trimmed.startsWith("data: "))
34
+ continue;
35
+ const payload = trimmed.slice(6);
36
+ if (payload === "[DONE]")
37
+ return;
38
+ try {
39
+ yield JSON.parse(payload);
40
+ }
41
+ catch { /* skip malformed JSON */ }
42
+ }
43
+ }
44
+ }
45
+ finally {
46
+ reader.releaseLock();
47
+ }
48
+ }
49
+ // ============================================================================
50
+ // STREAM COLLECTOR — batch-collects all events (subagent/teammate)
51
+ // ============================================================================
52
+ /**
53
+ * Collect all events into a StreamResult. No callbacks — used by
54
+ * subagent and teammate where real-time text isn't needed.
55
+ */
56
+ export async function collectStreamResult(events) {
57
+ return processStreamWithCallbacks(events, {});
58
+ }
59
+ // ============================================================================
60
+ // STREAM PROCESSOR — full event processing with callbacks (agent-loop)
61
+ // ============================================================================
62
+ /**
63
+ * Process streaming events with optional real-time callbacks.
64
+ * Used by agent-loop (needs onText for UI) and as internal impl for collect.
65
+ */
66
+ export async function processStreamWithCallbacks(events, callbacks, signal) {
67
+ let text = "";
68
+ const toolUseBlocks = [];
69
+ const thinkingBlocks = [];
70
+ const citations = [];
71
+ let currentToolUse = null;
72
+ let currentThinking = null;
73
+ let currentCitation = null;
74
+ let inputTokens = 0;
75
+ let outputTokens = 0;
76
+ let cacheCreationTokens = 0;
77
+ let cacheReadTokens = 0;
78
+ let apiThinkingTokens = 0; // Actual count from API (Gemini/OpenAI), 0 = use char estimate
79
+ let compactionContent = null;
80
+ let isCompactionBlock = false;
81
+ let contextManagementApplied = false;
82
+ let stopReason = "end_turn";
83
+ for await (const event of events) {
84
+ if (signal?.aborted)
85
+ break;
86
+ switch (event.type) {
87
+ case "content_block_start": {
88
+ const e = event;
89
+ const block = e.content_block;
90
+ if (block.type === "tool_use") {
91
+ currentToolUse = {
92
+ id: block.id,
93
+ name: block.name,
94
+ input: "",
95
+ thoughtSignature: block.thought_signature,
96
+ };
97
+ callbacks.onToolStart?.(block.name);
98
+ }
99
+ else if (block.type === "thinking") {
100
+ currentThinking = { text: "", signature: "" };
101
+ }
102
+ else if (block.type === "compaction") {
103
+ isCompactionBlock = true;
104
+ compactionContent = "";
105
+ }
106
+ else if (block.type === "cite") {
107
+ // Citation block — initialize from content_block_start payload
108
+ currentCitation = {
109
+ cited_text: block.cited_text ?? "",
110
+ document_index: block.document_index ?? 0,
111
+ document_title: block.document_title,
112
+ start_char_index: block.start_char_index ?? 0,
113
+ end_char_index: block.end_char_index ?? 0,
114
+ };
115
+ }
116
+ break;
117
+ }
118
+ case "content_block_delta": {
119
+ const e = event;
120
+ const delta = e.delta;
121
+ if (delta.type === "text_delta") {
122
+ text += delta.text;
123
+ callbacks.onText?.(delta.text);
124
+ }
125
+ else if (delta.type === "input_json_delta" && currentToolUse) {
126
+ currentToolUse.input += delta.partial_json;
127
+ }
128
+ else if (delta.type === "thinking_delta" && currentThinking) {
129
+ currentThinking.text += delta.thinking || "";
130
+ callbacks.onThinking?.(delta.thinking || "");
131
+ }
132
+ else if (delta.type === "signature_delta" && currentThinking) {
133
+ currentThinking.signature += delta.signature || "";
134
+ }
135
+ else if (delta.type === "compaction_delta" && isCompactionBlock) {
136
+ if (delta.content != null) {
137
+ compactionContent = (compactionContent || "") + delta.content;
138
+ }
139
+ }
140
+ else if (delta.type === "cite_delta" && currentCitation) {
141
+ // Accumulate incremental citation data from deltas
142
+ if (delta.cited_text != null)
143
+ currentCitation.cited_text += delta.cited_text;
144
+ if (delta.document_index != null)
145
+ currentCitation.document_index = delta.document_index;
146
+ if (delta.document_title != null)
147
+ currentCitation.document_title = delta.document_title;
148
+ if (delta.start_char_index != null)
149
+ currentCitation.start_char_index = delta.start_char_index;
150
+ if (delta.end_char_index != null)
151
+ currentCitation.end_char_index = delta.end_char_index;
152
+ }
153
+ break;
154
+ }
155
+ case "content_block_stop": {
156
+ if (currentToolUse) {
157
+ try {
158
+ const parsed = JSON.parse(currentToolUse.input || "{}");
159
+ toolUseBlocks.push({
160
+ id: currentToolUse.id,
161
+ name: currentToolUse.name,
162
+ input: parsed,
163
+ ...(currentToolUse.thoughtSignature ? { thoughtSignature: currentToolUse.thoughtSignature } : {}),
164
+ });
165
+ // Second callback with parsed input for UI context
166
+ callbacks.onToolStart?.(currentToolUse.name, parsed);
167
+ }
168
+ catch { /* skip bad JSON */ }
169
+ currentToolUse = null;
170
+ }
171
+ if (currentThinking) {
172
+ thinkingBlocks.push({
173
+ type: "thinking",
174
+ thinking: currentThinking.text,
175
+ signature: currentThinking.signature,
176
+ });
177
+ currentThinking = null;
178
+ }
179
+ if (currentCitation) {
180
+ const citation = {
181
+ type: "cite",
182
+ cited_text: currentCitation.cited_text,
183
+ document_index: currentCitation.document_index,
184
+ start_char_index: currentCitation.start_char_index,
185
+ end_char_index: currentCitation.end_char_index,
186
+ ...(currentCitation.document_title ? { document_title: currentCitation.document_title } : {}),
187
+ };
188
+ citations.push(citation);
189
+ callbacks.onCitation?.(citation);
190
+ currentCitation = null;
191
+ }
192
+ if (isCompactionBlock) {
193
+ isCompactionBlock = false;
194
+ contextManagementApplied = true;
195
+ }
196
+ break;
197
+ }
198
+ case "message_start": {
199
+ const e = event;
200
+ if (e.message?.usage) {
201
+ inputTokens += e.message.usage.input_tokens;
202
+ cacheCreationTokens += e.message.usage.cache_creation_input_tokens || 0;
203
+ cacheReadTokens += e.message.usage.cache_read_input_tokens || 0;
204
+ }
205
+ break;
206
+ }
207
+ case "message_delta": {
208
+ const e = event;
209
+ if (e.usage) {
210
+ outputTokens += e.usage.output_tokens;
211
+ // Non-Anthropic providers (Gemini, OpenAI) emit input_tokens and cache info in message_delta
212
+ if (e.usage.input_tokens) {
213
+ inputTokens += e.usage.input_tokens;
214
+ }
215
+ if (e.usage.cache_read_input_tokens) {
216
+ cacheReadTokens += e.usage.cache_read_input_tokens;
217
+ }
218
+ if (e.usage.thinking_tokens) {
219
+ apiThinkingTokens += e.usage.thinking_tokens;
220
+ }
221
+ }
222
+ if (e.delta?.stop_reason) {
223
+ stopReason = e.delta.stop_reason;
224
+ }
225
+ if (e.delta?.context_management?.applied_edits?.length) {
226
+ contextManagementApplied = true;
227
+ }
228
+ break;
229
+ }
230
+ case "error": {
231
+ const errMsg = typeof event.error === "string"
232
+ ? event.error
233
+ : JSON.stringify(event.error);
234
+ throw new Error(errMsg);
235
+ }
236
+ }
237
+ }
238
+ // Use actual thinking token count from API when available (Gemini/OpenAI),
239
+ // otherwise estimate from character count (~4 chars per token)
240
+ const thinkingTokens = apiThinkingTokens > 0
241
+ ? apiThinkingTokens
242
+ : thinkingBlocks.reduce((sum, b) => sum + Math.ceil(b.thinking.length / 4), 0);
243
+ return {
244
+ text,
245
+ toolUseBlocks,
246
+ thinkingBlocks,
247
+ thinkingTokens,
248
+ citations,
249
+ usage: {
250
+ inputTokens,
251
+ outputTokens,
252
+ cacheCreationTokens,
253
+ cacheReadTokens,
254
+ },
255
+ compactionContent,
256
+ contextManagementApplied,
257
+ stopReason,
258
+ };
259
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Unified Tool Dispatch — ONE implementation replacing 4 duplicates.
3
+ *
4
+ * Handles: loop detection, parallel execution, result truncation, bail-out.
5
+ * Used by agent-loop, subagent, teammate, and server-agent-loop.
6
+ */
7
+ import { LoopDetector } from "./agent-core.js";
8
+ import type { ToolUseBlock, ToolResultMessage } from "./types.js";
9
+ export interface ToolDispatchOptions {
10
+ /** Loop detector instance (shared across turns) */
11
+ loopDetector: LoopDetector;
12
+ /** Max concurrent tool executions (7 for main, 1 for sequential) */
13
+ maxConcurrent?: number;
14
+ /** @deprecated — Anthropic context_management handles limits. Only SAFETY_MAX_CHARS applies. */
15
+ maxResultChars?: number;
16
+ /** Per-tool execution timeout in ms (default 120000 = 2 minutes) */
17
+ toolTimeoutMs?: number;
18
+ /** Called when a tool starts executing */
19
+ onStart?: (name: string, input: Record<string, unknown>) => void;
20
+ /** Called when a tool finishes */
21
+ onResult?: (name: string, success: boolean, result: string, durationMs: number) => void;
22
+ /** Abort signal */
23
+ signal?: AbortSignal;
24
+ /** Transcribe audio data — called when __AUDIO__ marker detected in tool result */
25
+ transcribeAudio?: (base64: string, mediaType: string) => Promise<string>;
26
+ }
27
+ export type ToolExecutor = (name: string, input: Record<string, unknown>) => Promise<{
28
+ success: boolean;
29
+ output: string;
30
+ }>;
31
+ /**
32
+ * Execute tool calls with loop detection, parallel batching, and truncation.
33
+ * Returns tool result messages in original order.
34
+ */
35
+ export declare function dispatchTools(toolCalls: ToolUseBlock[], executor: ToolExecutor, opts: ToolDispatchOptions): Promise<{
36
+ results: ToolResultMessage[];
37
+ bailOut: boolean;
38
+ bailMessage?: string;
39
+ }>;
40
+ /**
41
+ * Build assistant content array from stream result for the next conversation turn.
42
+ */
43
+ export declare function buildAssistantContent(opts: {
44
+ text: string;
45
+ toolUseBlocks: ToolUseBlock[];
46
+ thinkingBlocks?: Array<{
47
+ type: "thinking";
48
+ thinking: string;
49
+ signature: string;
50
+ }>;
51
+ compactionContent?: string | null;
52
+ }): Array<Record<string, unknown>>;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Unified Tool Dispatch — ONE implementation replacing 4 duplicates.
3
+ *
4
+ * Handles: loop detection, parallel execution, result truncation, bail-out.
5
+ * Used by agent-loop, subagent, teammate, and server-agent-loop.
6
+ */
7
+ // ============================================================================
8
+ // TYPES
9
+ // ============================================================================
10
+ /** Hard cap on tool result size — matches Claude Code's 30K char limit.
11
+ * Prevents single tool outputs from blowing up context. Anthropic's
12
+ * context_management (clear_tool_uses + compact) handles multi-turn growth;
13
+ * this cap prevents any ONE result from being catastrophic. */
14
+ const SAFETY_MAX_CHARS = 30_000;
15
+ /** Tools that spawn workers/subprocesses and need much longer than 2 min */
16
+ const LONG_RUNNING_TOOL_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
17
+ const LONG_RUNNING_TOOLS = new Set(["team_create", "task", "kali", "delegate_task"]);
18
+ // ============================================================================
19
+ // DISPATCH
20
+ // ============================================================================
21
+ /**
22
+ * Execute tool calls with loop detection, parallel batching, and truncation.
23
+ * Returns tool result messages in original order.
24
+ */
25
+ export async function dispatchTools(toolCalls, executor, opts) {
26
+ const { loopDetector, maxConcurrent = 7, toolTimeoutMs = 120_000, onStart, onResult, signal, transcribeAudio, } = opts;
27
+ const resultMap = new Map();
28
+ async function executeSingle(tu) {
29
+ if (signal?.aborted) {
30
+ resultMap.set(tu.id, {
31
+ type: "tool_result",
32
+ tool_use_id: tu.id,
33
+ content: JSON.stringify({ error: "Aborted" }),
34
+ });
35
+ return;
36
+ }
37
+ // Loop detection check
38
+ const loopCheck = loopDetector.recordCall(tu.name, tu.input);
39
+ if (loopCheck.blocked) {
40
+ onResult?.(tu.name, false, loopCheck.reason, 0);
41
+ resultMap.set(tu.id, {
42
+ type: "tool_result",
43
+ tool_use_id: tu.id,
44
+ content: JSON.stringify({ error: loopCheck.reason }),
45
+ });
46
+ return;
47
+ }
48
+ onStart?.(tu.name, tu.input);
49
+ const toolStart = Date.now();
50
+ let result;
51
+ try {
52
+ const toolPromise = executor(tu.name, tu.input);
53
+ const effectiveTimeout = LONG_RUNNING_TOOLS.has(tu.name)
54
+ ? Math.max(toolTimeoutMs, LONG_RUNNING_TOOL_TIMEOUT_MS)
55
+ : toolTimeoutMs;
56
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Tool "${tu.name}" timed out after ${effectiveTimeout}ms`)), effectiveTimeout));
57
+ result = await Promise.race([toolPromise, timeoutPromise]);
58
+ }
59
+ catch (err) {
60
+ result = {
61
+ success: false,
62
+ output: `Tool execution error: ${err.message || String(err)}`,
63
+ };
64
+ }
65
+ const durationMs = Date.now() - toolStart;
66
+ loopDetector.recordResult(tu.name, result.success, tu.input);
67
+ onResult?.(tu.name, result.success, result.output, durationMs);
68
+ // Check for media markers — convert to appropriate content blocks
69
+ const mediaMatch = result.success && typeof result.output === "string"
70
+ ? result.output.match(/^__(IMAGE|AUDIO)__(.+?)__(.+)$/)
71
+ : null;
72
+ let resultBlock;
73
+ if (mediaMatch && mediaMatch[1] === "IMAGE") {
74
+ // Image → multimodal image content block
75
+ resultBlock = {
76
+ type: "tool_result",
77
+ tool_use_id: tu.id,
78
+ content: [
79
+ {
80
+ type: "image",
81
+ source: {
82
+ type: "base64",
83
+ media_type: mediaMatch[2],
84
+ data: mediaMatch[3],
85
+ },
86
+ },
87
+ ],
88
+ };
89
+ }
90
+ else if (mediaMatch && mediaMatch[1] === "AUDIO") {
91
+ // Audio → transcribe via Whisper, return transcript as text
92
+ let transcript;
93
+ if (transcribeAudio) {
94
+ try {
95
+ transcript = await transcribeAudio(mediaMatch[3], mediaMatch[2]);
96
+ }
97
+ catch (err) {
98
+ transcript = `Audio transcription failed: ${err.message}. The audio file was read successfully but could not be transcribed.`;
99
+ }
100
+ }
101
+ else {
102
+ transcript = "Audio file detected but transcription is not available. Configure an OpenAI API key for audio transcription via Whisper.";
103
+ }
104
+ resultBlock = {
105
+ type: "tool_result",
106
+ tool_use_id: tu.id,
107
+ content: transcript,
108
+ };
109
+ }
110
+ else {
111
+ const rawContent = result.success
112
+ ? result.output
113
+ : JSON.stringify({ error: result.output });
114
+ let contentStr = typeof rawContent === "string"
115
+ ? rawContent
116
+ : JSON.stringify(rawContent);
117
+ // Safety-only cap — prevents OOM from pathological tool outputs.
118
+ // Normal results flow through unmodified; Anthropic's context_management
119
+ // API clears old tool uses when context grows (clear_tool_uses_20250919).
120
+ if (contentStr.length > SAFETY_MAX_CHARS) {
121
+ contentStr =
122
+ contentStr.slice(0, SAFETY_MAX_CHARS) +
123
+ `\n\n... (safety truncated — ${contentStr.length.toLocaleString()} chars total)`;
124
+ }
125
+ resultBlock = {
126
+ type: "tool_result",
127
+ tool_use_id: tu.id,
128
+ content: contentStr,
129
+ };
130
+ }
131
+ resultMap.set(tu.id, resultBlock);
132
+ }
133
+ // Execute in parallel batches
134
+ for (let i = 0; i < toolCalls.length; i += maxConcurrent) {
135
+ if (signal?.aborted)
136
+ break;
137
+ const batch = toolCalls.slice(i, i + maxConcurrent);
138
+ await Promise.all(batch.map((tu) => executeSingle(tu)));
139
+ }
140
+ // Collect results in original order
141
+ const results = [];
142
+ for (const tu of toolCalls) {
143
+ const r = resultMap.get(tu.id);
144
+ if (r)
145
+ results.push(r);
146
+ }
147
+ // Bail-out detection
148
+ const bailCheck = loopDetector.endTurn();
149
+ if (bailCheck.shouldBail && results.length > 0) {
150
+ const lastResult = results[results.length - 1];
151
+ if (typeof lastResult.content === "string") {
152
+ lastResult.content = `[SYSTEM WARNING] ${bailCheck.message}\n\n${lastResult.content}`;
153
+ }
154
+ }
155
+ return {
156
+ results,
157
+ bailOut: bailCheck.shouldBail,
158
+ bailMessage: bailCheck.message,
159
+ };
160
+ }
161
+ // ============================================================================
162
+ // ASSISTANT CONTENT BUILDER — builds message content for next turn
163
+ // ============================================================================
164
+ /**
165
+ * Build assistant content array from stream result for the next conversation turn.
166
+ */
167
+ export function buildAssistantContent(opts) {
168
+ const content = [];
169
+ // Compaction block must come first
170
+ if (opts.compactionContent !== null && opts.compactionContent !== undefined) {
171
+ content.push({ type: "compaction", content: opts.compactionContent });
172
+ }
173
+ // Thinking blocks before text/tool_use
174
+ if (opts.thinkingBlocks) {
175
+ for (const tb of opts.thinkingBlocks) {
176
+ content.push(tb);
177
+ }
178
+ }
179
+ if (opts.text) {
180
+ content.push({ type: "text", text: opts.text });
181
+ }
182
+ content.push(...opts.toolUseBlocks.map((t) => ({
183
+ type: "tool_use",
184
+ id: t.id,
185
+ name: t.name,
186
+ input: t.input,
187
+ // Preserve Gemini thought signatures through function call round-trips
188
+ ...(t.thoughtSignature ? { thought_signature: t.thoughtSignature } : {}),
189
+ })));
190
+ return content;
191
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Shared Types — unified interfaces used by both CLI and server.
3
+ *
4
+ * Replaces 3 separate ToolResult definitions and provides typed SSE events.
5
+ * Pure TypeScript, no runtime dependencies.
6
+ */
7
+ /** Canonical tool result format — CLI tools return { success, output } */
8
+ export interface ToolResult {
9
+ success: boolean;
10
+ output: string;
11
+ }
12
+ export interface ToolUseBlock {
13
+ id: string;
14
+ name: string;
15
+ input: Record<string, unknown>;
16
+ /** Gemini thought signature — must be preserved through function call round-trips */
17
+ thoughtSignature?: string;
18
+ }
19
+ export interface ThinkingBlock {
20
+ type: "thinking";
21
+ thinking: string;
22
+ signature: string;
23
+ }
24
+ export interface CitationBlock {
25
+ type: "cite";
26
+ cited_text: string;
27
+ document_index: number;
28
+ document_title?: string;
29
+ start_char_index: number;
30
+ end_char_index: number;
31
+ }
32
+ /** Result of processing a complete SSE stream */
33
+ export interface StreamResult {
34
+ text: string;
35
+ toolUseBlocks: ToolUseBlock[];
36
+ thinkingBlocks: ThinkingBlock[];
37
+ thinkingTokens: number;
38
+ citations: CitationBlock[];
39
+ usage: {
40
+ inputTokens: number;
41
+ outputTokens: number;
42
+ cacheCreationTokens: number;
43
+ cacheReadTokens: number;
44
+ };
45
+ compactionContent: string | null;
46
+ contextManagementApplied: boolean;
47
+ stopReason: string;
48
+ }
49
+ /** Callbacks for real-time stream processing (used by agent-loop for UI) */
50
+ export interface StreamCallbacks {
51
+ onText?: (text: string) => void;
52
+ onToolStart?: (name: string, input?: Record<string, unknown>) => void;
53
+ onThinking?: (text: string) => void;
54
+ onCitation?: (citation: CitationBlock) => void;
55
+ }
56
+ export type ContextProfile = "main" | "subagent" | "teammate";
57
+ export interface APIRequestConfig {
58
+ betas: string[];
59
+ contextManagement: {
60
+ edits: Array<Record<string, unknown>>;
61
+ };
62
+ thinking?: {
63
+ type: string;
64
+ budget_tokens?: number;
65
+ };
66
+ maxTokens: number;
67
+ }
68
+ export interface ToolResultMessage {
69
+ type: "tool_result";
70
+ tool_use_id: string;
71
+ content: string | Array<Record<string, unknown>>;
72
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared Types — unified interfaces used by both CLI and server.
3
+ *
4
+ * Replaces 3 separate ToolResult definitions and provides typed SSE events.
5
+ * Pure TypeScript, no runtime dependencies.
6
+ */
7
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * OTA Auto-Updater for SwagManager MCP Server
3
+ *
4
+ * Checks the npm registry for newer versions and self-updates.
5
+ * - Runs on server startup (non-blocking)
6
+ * - Runs periodically (default: every 4 hours)
7
+ * - Updates in-place via `npm install -g` or local install
8
+ * - Signals the process to restart after update
9
+ */
10
+ export interface UpdateCheckResult {
11
+ currentVersion: string;
12
+ latestVersion: string | null;
13
+ updateAvailable: boolean;
14
+ updated: boolean;
15
+ }
16
+ /**
17
+ * Check for updates and install if available.
18
+ * Returns the result without restarting — caller decides restart behavior.
19
+ */
20
+ export declare function checkForUpdates(autoInstall?: boolean): Promise<UpdateCheckResult>;
21
+ /**
22
+ * Start periodic update checks in the background.
23
+ * First check runs immediately (non-blocking), then every CHECK_INTERVAL_MS.
24
+ */
25
+ export declare function startUpdateLoop(autoInstall?: boolean): NodeJS.Timeout;