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,84 @@
1
+ /**
2
+ * Rewind — checkpoint tracking and file revert for conversation rewind
3
+ *
4
+ * After each assistant turn, a checkpoint is recorded with:
5
+ * - The turn index and message count at that point
6
+ * - A summary of what happened (first 80 chars of assistant text)
7
+ * - File changes made during that turn (with backup paths from file-history)
8
+ *
9
+ * On rewind, files are restored from their backups in reverse chronological
10
+ * order. Files that were CREATED (not edited) during reverted turns are deleted.
11
+ *
12
+ * Integrates with the existing file-history.ts backup system.
13
+ */
14
+ export interface FileChange {
15
+ filePath: string;
16
+ backupPath: string;
17
+ operation: "write" | "edit" | "multi_edit";
18
+ isNewFile: boolean;
19
+ }
20
+ export interface RewindCheckpoint {
21
+ turnIndex: number;
22
+ messageCount: number;
23
+ timestamp: number;
24
+ summary: string;
25
+ fileChanges: FileChange[];
26
+ }
27
+ export interface RewindResult {
28
+ messageCount: number;
29
+ filesReverted: string[];
30
+ filesDeleted: string[];
31
+ errors: string[];
32
+ }
33
+ export declare class RewindManager {
34
+ private checkpoints;
35
+ private pendingFileChanges;
36
+ /**
37
+ * Record a checkpoint after an assistant turn completes.
38
+ */
39
+ addCheckpoint(turnIndex: number, messageCount: number, summary: string, fileChanges: FileChange[]): void;
40
+ /**
41
+ * Get all checkpoints for display.
42
+ */
43
+ getCheckpoints(): RewindCheckpoint[];
44
+ /**
45
+ * Get the number of recorded checkpoints.
46
+ */
47
+ getCheckpointCount(): number;
48
+ /**
49
+ * Rewind to a specific checkpoint index. All checkpoints AFTER this index
50
+ * are removed, and their file changes are reverted.
51
+ *
52
+ * Returns the message count to truncate to, plus lists of reverted/deleted files.
53
+ */
54
+ rewindTo(checkpointIndex: number): RewindResult;
55
+ /**
56
+ * Revert only file changes (without truncating conversation).
57
+ * Used when user wants to undo file changes but keep conversation history.
58
+ */
59
+ revertFilesFrom(checkpointIndex: number): Omit<RewindResult, "messageCount">;
60
+ /**
61
+ * Track a file change for the current (uncommitted) turn.
62
+ */
63
+ trackFileChange(change: FileChange): void;
64
+ /**
65
+ * Get the current turn's pending file changes.
66
+ */
67
+ getCurrentFileChanges(): FileChange[];
68
+ /**
69
+ * Clear current turn tracking (called when checkpoint is committed).
70
+ */
71
+ commitTurn(): void;
72
+ /**
73
+ * Check if there are any checkpoints with file changes that could be reverted.
74
+ */
75
+ hasFileChanges(): boolean;
76
+ /**
77
+ * Get the total number of file changes across all checkpoints after a given index.
78
+ */
79
+ getFileChangeCountAfter(checkpointIndex: number): number;
80
+ /**
81
+ * Reset all state.
82
+ */
83
+ reset(): void;
84
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Rewind — checkpoint tracking and file revert for conversation rewind
3
+ *
4
+ * After each assistant turn, a checkpoint is recorded with:
5
+ * - The turn index and message count at that point
6
+ * - A summary of what happened (first 80 chars of assistant text)
7
+ * - File changes made during that turn (with backup paths from file-history)
8
+ *
9
+ * On rewind, files are restored from their backups in reverse chronological
10
+ * order. Files that were CREATED (not edited) during reverted turns are deleted.
11
+ *
12
+ * Integrates with the existing file-history.ts backup system.
13
+ */
14
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
15
+ // ============================================================================
16
+ // REWIND MANAGER
17
+ // ============================================================================
18
+ export class RewindManager {
19
+ checkpoints = [];
20
+ pendingFileChanges = [];
21
+ /**
22
+ * Record a checkpoint after an assistant turn completes.
23
+ */
24
+ addCheckpoint(turnIndex, messageCount, summary, fileChanges) {
25
+ this.checkpoints.push({
26
+ turnIndex,
27
+ messageCount,
28
+ timestamp: Date.now(),
29
+ summary: summary.slice(0, 80),
30
+ fileChanges,
31
+ });
32
+ }
33
+ /**
34
+ * Get all checkpoints for display.
35
+ */
36
+ getCheckpoints() {
37
+ return [...this.checkpoints];
38
+ }
39
+ /**
40
+ * Get the number of recorded checkpoints.
41
+ */
42
+ getCheckpointCount() {
43
+ return this.checkpoints.length;
44
+ }
45
+ /**
46
+ * Rewind to a specific checkpoint index. All checkpoints AFTER this index
47
+ * are removed, and their file changes are reverted.
48
+ *
49
+ * Returns the message count to truncate to, plus lists of reverted/deleted files.
50
+ */
51
+ rewindTo(checkpointIndex) {
52
+ if (checkpointIndex < 0 || checkpointIndex >= this.checkpoints.length) {
53
+ return {
54
+ messageCount: 0,
55
+ filesReverted: [],
56
+ filesDeleted: [],
57
+ errors: [`Invalid checkpoint index: ${checkpointIndex}`],
58
+ };
59
+ }
60
+ const targetCheckpoint = this.checkpoints[checkpointIndex];
61
+ const removedCheckpoints = this.checkpoints.slice(checkpointIndex + 1);
62
+ const filesReverted = [];
63
+ const filesDeleted = [];
64
+ const errors = [];
65
+ // Revert file changes in reverse chronological order
66
+ // Process checkpoints from newest to oldest
67
+ for (let i = removedCheckpoints.length - 1; i >= 0; i--) {
68
+ const cp = removedCheckpoints[i];
69
+ // Process file changes within each checkpoint in reverse order
70
+ for (let j = cp.fileChanges.length - 1; j >= 0; j--) {
71
+ const change = cp.fileChanges[j];
72
+ try {
73
+ if (change.isNewFile) {
74
+ // File was created during this turn — delete it
75
+ if (existsSync(change.filePath)) {
76
+ unlinkSync(change.filePath);
77
+ filesDeleted.push(change.filePath);
78
+ }
79
+ }
80
+ else if (change.backupPath && existsSync(change.backupPath)) {
81
+ // File was edited — restore from backup
82
+ const backupContent = readFileSync(change.backupPath);
83
+ writeFileSync(change.filePath, backupContent);
84
+ filesReverted.push(change.filePath);
85
+ }
86
+ else {
87
+ errors.push(`No backup found for ${change.filePath}`);
88
+ }
89
+ }
90
+ catch (err) {
91
+ const msg = err instanceof Error ? err.message : String(err);
92
+ errors.push(`Failed to revert ${change.filePath}: ${msg}`);
93
+ }
94
+ }
95
+ }
96
+ // Truncate checkpoints to the target
97
+ this.checkpoints = this.checkpoints.slice(0, checkpointIndex + 1);
98
+ // Clear any pending file changes
99
+ this.pendingFileChanges = [];
100
+ return {
101
+ messageCount: targetCheckpoint.messageCount,
102
+ filesReverted: [...new Set(filesReverted)],
103
+ filesDeleted: [...new Set(filesDeleted)],
104
+ errors,
105
+ };
106
+ }
107
+ /**
108
+ * Revert only file changes (without truncating conversation).
109
+ * Used when user wants to undo file changes but keep conversation history.
110
+ */
111
+ revertFilesFrom(checkpointIndex) {
112
+ if (checkpointIndex < 0 || checkpointIndex >= this.checkpoints.length) {
113
+ return {
114
+ filesReverted: [],
115
+ filesDeleted: [],
116
+ errors: [`Invalid checkpoint index: ${checkpointIndex}`],
117
+ };
118
+ }
119
+ const removedCheckpoints = this.checkpoints.slice(checkpointIndex + 1);
120
+ const filesReverted = [];
121
+ const filesDeleted = [];
122
+ const errors = [];
123
+ for (let i = removedCheckpoints.length - 1; i >= 0; i--) {
124
+ const cp = removedCheckpoints[i];
125
+ for (let j = cp.fileChanges.length - 1; j >= 0; j--) {
126
+ const change = cp.fileChanges[j];
127
+ try {
128
+ if (change.isNewFile) {
129
+ if (existsSync(change.filePath)) {
130
+ unlinkSync(change.filePath);
131
+ filesDeleted.push(change.filePath);
132
+ }
133
+ }
134
+ else if (change.backupPath && existsSync(change.backupPath)) {
135
+ const backupContent = readFileSync(change.backupPath);
136
+ writeFileSync(change.filePath, backupContent);
137
+ filesReverted.push(change.filePath);
138
+ }
139
+ else {
140
+ errors.push(`No backup found for ${change.filePath}`);
141
+ }
142
+ }
143
+ catch (err) {
144
+ const msg = err instanceof Error ? err.message : String(err);
145
+ errors.push(`Failed to revert ${change.filePath}: ${msg}`);
146
+ }
147
+ }
148
+ }
149
+ return {
150
+ filesReverted: [...new Set(filesReverted)],
151
+ filesDeleted: [...new Set(filesDeleted)],
152
+ errors,
153
+ };
154
+ }
155
+ /**
156
+ * Track a file change for the current (uncommitted) turn.
157
+ */
158
+ trackFileChange(change) {
159
+ this.pendingFileChanges.push(change);
160
+ }
161
+ /**
162
+ * Get the current turn's pending file changes.
163
+ */
164
+ getCurrentFileChanges() {
165
+ return [...this.pendingFileChanges];
166
+ }
167
+ /**
168
+ * Clear current turn tracking (called when checkpoint is committed).
169
+ */
170
+ commitTurn() {
171
+ this.pendingFileChanges = [];
172
+ }
173
+ /**
174
+ * Check if there are any checkpoints with file changes that could be reverted.
175
+ */
176
+ hasFileChanges() {
177
+ return this.checkpoints.some(cp => cp.fileChanges.length > 0);
178
+ }
179
+ /**
180
+ * Get the total number of file changes across all checkpoints after a given index.
181
+ */
182
+ getFileChangeCountAfter(checkpointIndex) {
183
+ return this.checkpoints
184
+ .slice(checkpointIndex + 1)
185
+ .reduce((sum, cp) => sum + cp.fileChanges.length, 0);
186
+ }
187
+ /**
188
+ * Reset all state.
189
+ */
190
+ reset() {
191
+ this.checkpoints = [];
192
+ this.pendingFileChanges = [];
193
+ }
194
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Ripgrep Integration — fast search via `rg` binary
3
+ *
4
+ * Tries system `rg` first, then falls back to @vscode/ripgrep package.
5
+ * If neither available, callers fall back to grep/find.
6
+ */
7
+ export declare function getRgPath(): string | null;
8
+ export declare function isRgAvailable(): boolean;
9
+ export interface RgGrepOptions {
10
+ pattern: string;
11
+ path: string;
12
+ outputMode?: "content" | "files_with_matches" | "count";
13
+ glob?: string;
14
+ type?: string;
15
+ caseInsensitive?: boolean;
16
+ multiline?: boolean;
17
+ context?: number;
18
+ before?: number;
19
+ after?: number;
20
+ headLimit?: number;
21
+ }
22
+ export declare function rgGrep(opts: RgGrepOptions): string | null;
23
+ export interface RgGlobOptions {
24
+ pattern: string;
25
+ path: string;
26
+ headLimit?: number;
27
+ }
28
+ export declare function rgGlob(opts: RgGlobOptions): string | null;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Ripgrep Integration — fast search via `rg` binary
3
+ *
4
+ * Tries system `rg` first, then falls back to @vscode/ripgrep package.
5
+ * If neither available, callers fall back to grep/find.
6
+ */
7
+ import { execSync, execFileSync } from "child_process";
8
+ // ============================================================================
9
+ // RG BINARY DISCOVERY
10
+ // ============================================================================
11
+ let rgPathCache = undefined; // undefined = unchecked
12
+ function findSystemRg() {
13
+ try {
14
+ const path = execSync("which rg", { encoding: "utf-8", timeout: 3000 }).trim();
15
+ if (path)
16
+ return path;
17
+ }
18
+ catch { /* not on PATH */ }
19
+ return null;
20
+ }
21
+ function findVscodeRg() {
22
+ try {
23
+ const rgModule = require("@vscode/ripgrep");
24
+ if (rgModule?.rgPath)
25
+ return rgModule.rgPath;
26
+ }
27
+ catch { /* package not installed */ }
28
+ return null;
29
+ }
30
+ export function getRgPath() {
31
+ if (rgPathCache !== undefined)
32
+ return rgPathCache;
33
+ rgPathCache = findSystemRg() || findVscodeRg();
34
+ return rgPathCache;
35
+ }
36
+ export function isRgAvailable() {
37
+ return getRgPath() !== null;
38
+ }
39
+ export function rgGrep(opts) {
40
+ const rg = getRgPath();
41
+ if (!rg)
42
+ return null;
43
+ const args = [];
44
+ // Output mode
45
+ switch (opts.outputMode) {
46
+ case "files_with_matches":
47
+ args.push("-l");
48
+ break;
49
+ case "count":
50
+ args.push("-c");
51
+ break;
52
+ case "content":
53
+ args.push("-n");
54
+ break;
55
+ default:
56
+ args.push("-l");
57
+ break;
58
+ }
59
+ // Case sensitivity
60
+ if (opts.caseInsensitive)
61
+ args.push("-i");
62
+ // Multiline
63
+ if (opts.multiline) {
64
+ args.push("-U", "--multiline-dotall");
65
+ }
66
+ // Context lines (content mode only)
67
+ if (opts.outputMode === "content") {
68
+ if (opts.context)
69
+ args.push("-C", String(opts.context));
70
+ if (opts.before)
71
+ args.push("-B", String(opts.before));
72
+ if (opts.after)
73
+ args.push("-A", String(opts.after));
74
+ }
75
+ // File type filter
76
+ if (opts.type)
77
+ args.push("--type", opts.type);
78
+ if (opts.glob)
79
+ args.push("--glob", opts.glob);
80
+ // Exclusions
81
+ args.push("--glob", "!node_modules", "--glob", "!.git", "--glob", "!dist");
82
+ // Pattern and path
83
+ args.push("--", opts.pattern, opts.path);
84
+ const limit = opts.headLimit || 200;
85
+ try {
86
+ const output = execFileSync(rg, args, {
87
+ encoding: "utf-8",
88
+ timeout: 30000,
89
+ maxBuffer: 2 * 1024 * 1024,
90
+ stdio: ["pipe", "pipe", "pipe"], // Suppress stderr from leaking to terminal
91
+ });
92
+ // Apply head limit
93
+ const lines = output.split("\n");
94
+ const limited = lines.slice(0, limit).join("\n");
95
+ return limited.trim() || null;
96
+ }
97
+ catch (err) {
98
+ // rg exits 1 for "no matches" — that's not an error
99
+ if (err.status === 1)
100
+ return null;
101
+ // rg exits 2 for actual errors (permission denied etc.) — don't throw, return null
102
+ if (err.status === 2)
103
+ return null;
104
+ throw err;
105
+ }
106
+ }
107
+ export function rgGlob(opts) {
108
+ const rg = getRgPath();
109
+ if (!rg)
110
+ return null;
111
+ const args = [
112
+ "--files",
113
+ "--glob", opts.pattern,
114
+ "--glob", "!node_modules",
115
+ "--glob", "!.git",
116
+ "--glob", "!dist",
117
+ opts.path,
118
+ ];
119
+ const limit = opts.headLimit || 200;
120
+ try {
121
+ const output = execFileSync(rg, args, {
122
+ encoding: "utf-8",
123
+ timeout: 10000,
124
+ maxBuffer: 2 * 1024 * 1024,
125
+ stdio: ["pipe", "pipe", "pipe"], // Suppress stderr from leaking to terminal
126
+ });
127
+ const files = output.trim().split("\n").filter(Boolean);
128
+ const limited = files.slice(0, limit);
129
+ return limited.length > 0 ? limited.join("\n") : null;
130
+ }
131
+ catch (err) {
132
+ if (err.status === 1)
133
+ return null;
134
+ if (err.status === 2)
135
+ return null; // Permission errors etc.
136
+ throw err;
137
+ }
138
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Bash Sandbox — macOS sandbox-exec wrapper for shell commands
3
+ *
4
+ * Restricts file writes to:
5
+ * - Current working directory (cwd)
6
+ * - /tmp and /private/tmp
7
+ * - ~/.swagmanager/
8
+ * - /dev (for terminal I/O)
9
+ * - /private/var/folders (macOS temp)
10
+ *
11
+ * Allows all reads and network access.
12
+ * Only active on macOS. Linux: passthrough (future work).
13
+ */
14
+ /**
15
+ * Wrap a command with macOS sandbox-exec.
16
+ * Returns the original command unchanged on non-macOS platforms.
17
+ */
18
+ export declare function sandboxCommand(command: string, cwd: string): {
19
+ wrapped: string;
20
+ profilePath: string | null;
21
+ };
22
+ /**
23
+ * Clean up sandbox profile after command execution.
24
+ */
25
+ export declare function cleanupSandbox(profilePath: string | null): void;
26
+ /**
27
+ * Check if sandbox-exec is available on this platform.
28
+ */
29
+ export declare function isSandboxAvailable(): boolean;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Bash Sandbox — macOS sandbox-exec wrapper for shell commands
3
+ *
4
+ * Restricts file writes to:
5
+ * - Current working directory (cwd)
6
+ * - /tmp and /private/tmp
7
+ * - ~/.swagmanager/
8
+ * - /dev (for terminal I/O)
9
+ * - /private/var/folders (macOS temp)
10
+ *
11
+ * Allows all reads and network access.
12
+ * Only active on macOS. Linux: passthrough (future work).
13
+ */
14
+ import { writeFileSync, unlinkSync, existsSync, mkdirSync } from "fs";
15
+ import { join } from "path";
16
+ import { homedir } from "os";
17
+ // ============================================================================
18
+ // SANDBOX PROFILE
19
+ // ============================================================================
20
+ function buildSandboxProfile(cwd) {
21
+ const home = homedir();
22
+ return `(version 1)
23
+ (allow default)
24
+ (deny file-write*)
25
+ (allow file-write* (subpath "${cwd}"))
26
+ (allow file-write* (subpath "/tmp"))
27
+ (allow file-write* (subpath "/private/tmp"))
28
+ (allow file-write* (subpath "${home}/.swagmanager"))
29
+ (allow file-write* (subpath "/dev"))
30
+ (allow file-write* (subpath "/private/var/folders"))
31
+ `;
32
+ }
33
+ // ============================================================================
34
+ // TEMP PROFILE MANAGEMENT
35
+ // ============================================================================
36
+ const SANDBOX_DIR = join(homedir(), ".swagmanager", "sandbox");
37
+ let profileCounter = 0;
38
+ function writeTempProfile(profile) {
39
+ if (!existsSync(SANDBOX_DIR)) {
40
+ mkdirSync(SANDBOX_DIR, { recursive: true });
41
+ }
42
+ const profilePath = join(SANDBOX_DIR, `profile-${process.pid}-${profileCounter++}.sb`);
43
+ writeFileSync(profilePath, profile, "utf-8");
44
+ return profilePath;
45
+ }
46
+ function cleanupProfile(profilePath) {
47
+ try {
48
+ if (existsSync(profilePath))
49
+ unlinkSync(profilePath);
50
+ }
51
+ catch { /* best effort */ }
52
+ }
53
+ // ============================================================================
54
+ // SHELL ESCAPING
55
+ // ============================================================================
56
+ function shellEscape(s) {
57
+ // Use single quotes and escape any existing single quotes
58
+ return "'" + s.replace(/'/g, "'\\''") + "'";
59
+ }
60
+ // ============================================================================
61
+ // PUBLIC API
62
+ // ============================================================================
63
+ /**
64
+ * Wrap a command with macOS sandbox-exec.
65
+ * Returns the original command unchanged on non-macOS platforms.
66
+ */
67
+ export function sandboxCommand(command, cwd) {
68
+ if (process.platform !== "darwin") {
69
+ return { wrapped: command, profilePath: null };
70
+ }
71
+ const profile = buildSandboxProfile(cwd);
72
+ const profilePath = writeTempProfile(profile);
73
+ const wrapped = `sandbox-exec -f ${shellEscape(profilePath)} /bin/bash -c ${shellEscape(command)}`;
74
+ return { wrapped, profilePath };
75
+ }
76
+ /**
77
+ * Clean up sandbox profile after command execution.
78
+ */
79
+ export function cleanupSandbox(profilePath) {
80
+ if (profilePath)
81
+ cleanupProfile(profilePath);
82
+ }
83
+ /**
84
+ * Check if sandbox-exec is available on this platform.
85
+ */
86
+ export function isSandboxAvailable() {
87
+ if (process.platform !== "darwin")
88
+ return false;
89
+ try {
90
+ const { execSync } = require("child_process");
91
+ execSync("which sandbox-exec", { stdio: "pipe", timeout: 3000 });
92
+ return true;
93
+ }
94
+ catch {
95
+ return false;
96
+ }
97
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Server Tools — loaded dynamically from ai_tool_registry
3
+ *
4
+ * Single source of truth: the database. Same as the MCP server (index.ts).
5
+ * No hardcoded definitions. Tools are cached for 60s after first load.
6
+ *
7
+ * Execution: proxied to the Fly.io server or Supabase edge function (mode: "tool").
8
+ * All business logic lives server-side — CLI is a thin client.
9
+ * Claude formats the JSON results for the user (no client-side formatter).
10
+ */
11
+ import type Anthropic from "@anthropic-ai/sdk";
12
+ import type { AgentEventEmitter } from "./agent-events.js";
13
+ import { ToolResult } from "../../shared/types.js";
14
+ export type { ToolResult };
15
+ interface ToolExecutionContext {
16
+ traceId?: string;
17
+ conversationId?: string;
18
+ userId?: string;
19
+ userEmail?: string;
20
+ source?: string;
21
+ }
22
+ /**
23
+ * Set the execution context for server tool calls.
24
+ * Called by agent-loop.ts before each turn so tool calls carry trace/user identity.
25
+ */
26
+ export declare function setServerToolContext(ctx: ToolExecutionContext): void;
27
+ export interface ServerStatus {
28
+ connected: boolean;
29
+ storeId: string;
30
+ storeName: string;
31
+ toolCount: number;
32
+ authMethod: "service_role" | "jwt" | "none";
33
+ }
34
+ export declare function resetServerToolClient(): void;
35
+ export declare function checkConnection(): Promise<boolean>;
36
+ /**
37
+ * Load server tool definitions from ai_tool_registry.
38
+ * Same query as the MCP server (index.ts). Cached for 60s.
39
+ * Filters out tool_mode='code' (those are local CLI tools).
40
+ */
41
+ export declare function loadServerToolDefinitions(force?: boolean): Promise<Anthropic.Tool[]>;
42
+ /**
43
+ * Check if a tool name is a server tool.
44
+ * After first load, checks against the dynamically loaded set.
45
+ */
46
+ export declare function isServerTool(name: string): boolean;
47
+ /**
48
+ * Get currently loaded definitions (for /tools listing).
49
+ * Returns whatever is cached — call loadServerToolDefinitions() first to populate.
50
+ */
51
+ export declare function getAllServerToolDefinitions(): Anthropic.Tool[];
52
+ export declare function getServerStatus(): Promise<ServerStatus>;
53
+ /**
54
+ * Execute a server tool via the Fly.io server or Supabase edge function (mode: "tool").
55
+ * Returns the raw JSON — Claude formats it for the user.
56
+ * No client-side formatting: the model is the presentation layer.
57
+ *
58
+ * For tools that support live progress (kali exec), uses `mode: "tool_stream"` with NDJSON
59
+ * and emits `tool_output` events via the optional emitter for real-time CLI rendering.
60
+ */
61
+ export declare function executeServerTool(name: string, input: Record<string, unknown>, emitter?: AgentEventEmitter): Promise<ToolResult>;