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,387 @@
1
+ /**
2
+ * useSlashCommands — slash command handler extracted from ChatApp
3
+ *
4
+ * All consumers should import from ChatApp (re-export facade).
5
+ */
6
+ import { useCallback } from "react";
7
+ import { execSync } from "child_process";
8
+ import { setModel, getModel, getModelShortName, loadClaudeMd, getSessionTokens, resetSessionState, saveSession, loadSession, listSessions, addMemory, removeMemory, listMemories, setPermissionMode, getPermissionMode, getServerStatus, mcpClientManager, } from "../../services/agent-loop.js";
9
+ import { setConversationId } from "../../services/telemetry.js";
10
+ import { getAllServerToolDefinitions, resetServerToolClient } from "../../services/server-tools.js";
11
+ import { LOCAL_TOOL_DEFINITIONS, loadTodos, setTodoSessionId } from "../../services/local-tools.js";
12
+ import { loadAgentDefinitions } from "../../services/agent-definitions.js";
13
+ import { SLASH_COMMANDS } from "../ChatInput.js";
14
+ import { MODEL_OPTIONS } from "../ModelSelector.js";
15
+ import { symbols } from "../../shared/Theme.js";
16
+ import { loadKeybindings } from "../../services/keybinding-manager.js";
17
+ import { loadConfig, updateConfig } from "../../services/config-store.js";
18
+ import { getStoresForUser, getValidToken, selectStore } from "../../services/auth-service.js";
19
+ import { getServerToolCount } from "../../services/agent-loop.js";
20
+ export function useSlashCommands(deps) {
21
+ const { exit, toolsExpanded, serverToolsAvailable, sessionId, thinkingEnabled, conversationRef, setMessages, setStreamingText, setActiveTools, setTeamState, setStoreList, setStoreSelectMode, setModelSelectMode, setCurrentModel, setSessionId, setThinkingEnabled, setUserLabel, setServerToolsAvailable, setShowRewind, rewindCheckpointCount, PKG_NAME, PKG_VERSION, } = deps;
22
+ const handleCommand = useCallback(async (command) => {
23
+ const parts = command.trim().split(/\s+/);
24
+ const cmd = parts[0];
25
+ const args = parts.slice(1).join(" ");
26
+ switch (cmd) {
27
+ case "/help": {
28
+ const helpLines = SLASH_COMMANDS
29
+ .map((c) => ` ${c.name.padEnd(14)}${c.description}`)
30
+ .join("\n");
31
+ const kb = loadKeybindings();
32
+ setMessages((prev) => [...prev, {
33
+ role: "assistant",
34
+ text: helpLines + `\n\n ${kb.exit} exit ${kb.cancel_stream} cancel ${kb.toggle_expand} expand tools`,
35
+ }]);
36
+ break;
37
+ }
38
+ case "/clear":
39
+ setMessages([]);
40
+ setStreamingText("");
41
+ setActiveTools([]);
42
+ setTeamState(null);
43
+ conversationRef.current = [];
44
+ resetSessionState();
45
+ break;
46
+ case "/exit":
47
+ exit();
48
+ break;
49
+ case "/status": {
50
+ const config = loadConfig();
51
+ const localCount = LOCAL_TOOL_DEFINITIONS.length;
52
+ const toolsLine = serverToolsAvailable > 0
53
+ ? ` tools ${localCount} local + ${serverToolsAvailable} server`
54
+ : ` tools ${localCount} local`;
55
+ const claudeMd = loadClaudeMd();
56
+ const tokens = getSessionTokens();
57
+ const tokenLine = tokens.input > 0
58
+ ? ` tokens ${(tokens.input / 1000).toFixed(1)}K in / ${(tokens.output / 1000).toFixed(1)}K out`
59
+ : ` tokens (no usage yet)`;
60
+ const lines = [
61
+ ` version v${PKG_VERSION}`,
62
+ ` user ${config.email || "—"}`,
63
+ ` store ${config.store_name || "—"}`,
64
+ ` model ${getModelShortName()} (${getModel()})`,
65
+ ` output 16384 max tokens`,
66
+ toolsLine,
67
+ tokenLine,
68
+ ` session ${sessionId || "(unsaved)"}`,
69
+ ` CLAUDE.md ${claudeMd ? claudeMd.path : "not found"}`,
70
+ ` mode ${getPermissionMode()}`,
71
+ ` thinking ${thinkingEnabled ? "on" : "off"} (^T)`,
72
+ ` context ${conversationRef.current.length} messages`,
73
+ ` expand ${toolsExpanded ? "on" : "off"} (^E)`,
74
+ ];
75
+ setMessages((prev) => [...prev, { role: "assistant", text: lines.join("\n") }]);
76
+ break;
77
+ }
78
+ case "/mcp": {
79
+ getServerStatus().then((status) => {
80
+ const lines = [];
81
+ if (status.connected) {
82
+ lines.push(` Server tools:`);
83
+ lines.push(` ● Connected (${status.authMethod === "service_role" ? "service role" : "user JWT"})`);
84
+ lines.push(` store ${status.storeName || status.storeId || "—"}`);
85
+ lines.push(` tools ${status.toolCount} active`);
86
+ lines.push("");
87
+ const serverDefs = getAllServerToolDefinitions();
88
+ for (const t of serverDefs) {
89
+ lines.push(` ${t.name.padEnd(20)} ${(t.description || "").slice(0, 45)}`);
90
+ }
91
+ }
92
+ else {
93
+ lines.push(` Server tools:`);
94
+ lines.push(` ○ Disconnected — run: whale login`);
95
+ }
96
+ const mcpStatus = mcpClientManager.getStatus();
97
+ if (mcpStatus.length > 0) {
98
+ lines.push("");
99
+ lines.push(` External MCP servers:`);
100
+ for (const s of mcpStatus) {
101
+ lines.push(` ● ${s.name} (${s.toolCount} tool${s.toolCount !== 1 ? "s" : ""})`);
102
+ }
103
+ }
104
+ setMessages((prev) => [...prev, { role: "assistant", text: lines.join("\n") }]);
105
+ });
106
+ break;
107
+ }
108
+ case "/store": {
109
+ getValidToken().then(async (token) => {
110
+ if (!token) {
111
+ setMessages((prev) => [...prev, { role: "assistant", text: " Not logged in. Run: whale login" }]);
112
+ return;
113
+ }
114
+ const config = loadConfig();
115
+ const stores = await getStoresForUser(token, config.user_id || "");
116
+ if (stores.length === 0) {
117
+ setMessages((prev) => [...prev, { role: "assistant", text: " No stores found for this account." }]);
118
+ }
119
+ else if (stores.length === 1) {
120
+ setMessages((prev) => [...prev, { role: "assistant", text: ` Only one store: ${stores[0].name}` }]);
121
+ }
122
+ else {
123
+ setStoreList(stores);
124
+ setStoreSelectMode(true);
125
+ }
126
+ });
127
+ break;
128
+ }
129
+ case "/update": {
130
+ setMessages((prev) => [...prev, { role: "assistant", text: ` Checking for updates...` }]);
131
+ try {
132
+ const latest = execSync(`npm view ${PKG_NAME} version 2>/dev/null`, { encoding: "utf-8" }).trim();
133
+ if (latest === PKG_VERSION) {
134
+ setMessages((prev) => [...prev, { role: "assistant", text: ` ${symbols.check} Already on latest v${PKG_VERSION}` }]);
135
+ }
136
+ else {
137
+ setMessages((prev) => [...prev, { role: "assistant", text: ` v${PKG_VERSION} → v${latest} Installing...` }]);
138
+ try {
139
+ execSync(`npm install -g ${PKG_NAME}@latest 2>&1`, { encoding: "utf-8", timeout: 30000 });
140
+ setMessages((prev) => [...prev, { role: "assistant", text: ` ${symbols.check} Updated to v${latest}\n Restart whale to use the new version.` }]);
141
+ }
142
+ catch {
143
+ setMessages((prev) => [...prev, { role: "assistant", text: ` ${symbols.cross} Install failed. Try manually:\n npm install -g ${PKG_NAME}@latest` }]);
144
+ }
145
+ }
146
+ }
147
+ catch {
148
+ setMessages((prev) => [...prev, { role: "assistant", text: ` ${symbols.cross} Could not check npm. Are you online?` }]);
149
+ }
150
+ break;
151
+ }
152
+ case "/model": {
153
+ const match = args && MODEL_OPTIONS.find((m) => m.value === args);
154
+ if (match) {
155
+ setModel(match.value);
156
+ setCurrentModel(match.value);
157
+ setMessages((prev) => [...prev, {
158
+ role: "assistant",
159
+ text: ` ${symbols.check} Model: ${match.label} (${match.modelId})`,
160
+ }]);
161
+ }
162
+ else {
163
+ setModelSelectMode(true);
164
+ }
165
+ break;
166
+ }
167
+ case "/compact": {
168
+ setMessages((prev) => [...prev, {
169
+ role: "assistant",
170
+ text: ` Context management is now handled server-side by the Anthropic API. Compaction fires automatically when context exceeds 150K tokens.`,
171
+ }]);
172
+ break;
173
+ }
174
+ case "/save": {
175
+ if (conversationRef.current.length === 0) {
176
+ setMessages((prev) => [...prev, { role: "assistant", text: " Nothing to save." }]);
177
+ }
178
+ else {
179
+ const id = saveSession(conversationRef.current, sessionId || undefined);
180
+ setSessionId(id);
181
+ setTodoSessionId(id);
182
+ setMessages((prev) => [...prev, {
183
+ role: "assistant",
184
+ text: ` ${symbols.check} Session saved: ${id}`,
185
+ }]);
186
+ }
187
+ break;
188
+ }
189
+ case "/sessions": {
190
+ const sessions = listSessions();
191
+ if (sessions.length === 0) {
192
+ setMessages((prev) => [...prev, { role: "assistant", text: " No saved sessions." }]);
193
+ }
194
+ else {
195
+ const lines = sessions.map((s, i) => ` ${String(i + 1).padStart(2)}. ${s.title.slice(0, 40).padEnd(42)} ${s.messageCount} msgs ${s.updatedAt.slice(0, 10)}`);
196
+ setMessages((prev) => [...prev, {
197
+ role: "assistant",
198
+ text: ` Saved sessions:\n${lines.join("\n")}\n\n Use /resume to load a session.`,
199
+ }]);
200
+ }
201
+ break;
202
+ }
203
+ case "/resume": {
204
+ const sessions = listSessions();
205
+ if (sessions.length === 0) {
206
+ setMessages((prev) => [...prev, { role: "assistant", text: " No saved sessions." }]);
207
+ }
208
+ else {
209
+ const latest = sessions[0];
210
+ const loaded = loadSession(latest.id);
211
+ if (loaded) {
212
+ conversationRef.current = loaded.messages;
213
+ setSessionId(latest.id);
214
+ setConversationId(latest.id);
215
+ setTodoSessionId(latest.id);
216
+ loadTodos(latest.id);
217
+ if (loaded.meta.model)
218
+ setModel(loaded.meta.model);
219
+ setMessages((prev) => [...prev, {
220
+ role: "assistant",
221
+ text: ` ${symbols.check} Resumed: ${latest.title}\n ${latest.messageCount} messages, model: ${getModelShortName()}`,
222
+ }]);
223
+ }
224
+ else {
225
+ setMessages((prev) => [...prev, { role: "assistant", text: " Failed to load session." }]);
226
+ }
227
+ }
228
+ break;
229
+ }
230
+ case "/agents": {
231
+ const builtIn = ["explore", "plan", "general-purpose", "research"];
232
+ const custom = loadAgentDefinitions();
233
+ const lines = [];
234
+ lines.push(" Built-in:");
235
+ for (const a of builtIn)
236
+ lines.push(` ${a.padEnd(20)} (built-in)`);
237
+ if (custom.length > 0) {
238
+ lines.push("");
239
+ lines.push(" Custom:");
240
+ for (const a of custom) {
241
+ lines.push(` ${a.name.padEnd(20)} ${a.description || `(${a.source})`}`);
242
+ }
243
+ }
244
+ else {
245
+ lines.push("");
246
+ lines.push(" No custom agents. Add .md files to .whale/agents/ or ~/.swagmanager/agents/");
247
+ }
248
+ setMessages((prev) => [...prev, { role: "assistant", text: lines.join("\n") }]);
249
+ break;
250
+ }
251
+ case "/remember": {
252
+ if (!args) {
253
+ setMessages((prev) => [...prev, { role: "assistant", text: " Usage: /remember <fact to remember>" }]);
254
+ }
255
+ else {
256
+ const result = addMemory(args);
257
+ setMessages((prev) => [...prev, {
258
+ role: "assistant",
259
+ text: ` ${result.success ? symbols.check : symbols.cross} ${result.message}`,
260
+ }]);
261
+ }
262
+ break;
263
+ }
264
+ case "/forget": {
265
+ if (!args) {
266
+ setMessages((prev) => [...prev, { role: "assistant", text: " Usage: /forget <pattern to match>" }]);
267
+ }
268
+ else {
269
+ const result = removeMemory(args);
270
+ setMessages((prev) => [...prev, {
271
+ role: "assistant",
272
+ text: ` ${result.success ? symbols.check : symbols.cross} ${result.message}`,
273
+ }]);
274
+ }
275
+ break;
276
+ }
277
+ case "/memory": {
278
+ const memories = listMemories();
279
+ if (memories.length === 0) {
280
+ setMessages((prev) => [...prev, { role: "assistant", text: " No memories stored. Use /remember <fact> to add one." }]);
281
+ }
282
+ else {
283
+ const lines = memories.map((m, i) => ` ${i + 1}. ${m}`);
284
+ setMessages((prev) => [...prev, {
285
+ role: "assistant",
286
+ text: ` ${memories.length} remembered fact${memories.length !== 1 ? "s" : ""}:\n${lines.join("\n")}`,
287
+ }]);
288
+ }
289
+ break;
290
+ }
291
+ case "/mode": {
292
+ const modeDesc = {
293
+ default: "all tools, normal operation",
294
+ plan: "read-only tools only (no writes, no commands)",
295
+ yolo: "all tools, no confirmation",
296
+ };
297
+ const modes = ["default", "plan", "yolo"];
298
+ if (args && modes.includes(args)) {
299
+ setPermissionMode(args);
300
+ setMessages((prev) => [...prev, {
301
+ role: "assistant",
302
+ text: ` ${symbols.check} Mode: ${args} (${modeDesc[args]})`,
303
+ }]);
304
+ }
305
+ else {
306
+ const current = getPermissionMode();
307
+ const nextIdx = (modes.indexOf(current) + 1) % modes.length;
308
+ const next = modes[nextIdx];
309
+ setPermissionMode(next);
310
+ setMessages((prev) => [...prev, {
311
+ role: "assistant",
312
+ text: ` ${symbols.check} Mode: ${next} (${modeDesc[next]})`,
313
+ }]);
314
+ }
315
+ break;
316
+ }
317
+ case "/thinking": {
318
+ setThinkingEnabled(prev => {
319
+ const next = !prev;
320
+ try {
321
+ updateConfig({ thinking_enabled: next });
322
+ }
323
+ catch { /* best effort */ }
324
+ setMessages(msgs => [...msgs, {
325
+ role: "assistant",
326
+ text: ` Thinking: ${next ? "on" : "off"}`,
327
+ }]);
328
+ return next;
329
+ });
330
+ break;
331
+ }
332
+ case "/init": {
333
+ const { runInitInline } = await import("../../commands/init.js");
334
+ const result = await runInitInline();
335
+ setMessages(prev => [...prev, { role: "assistant", text: result }]);
336
+ break;
337
+ }
338
+ case "/rewind": {
339
+ if (rewindCheckpointCount === 0) {
340
+ setMessages((prev) => [...prev, { role: "assistant", text: " Nothing to rewind to." }]);
341
+ }
342
+ else {
343
+ setShowRewind(true);
344
+ }
345
+ break;
346
+ }
347
+ case "/tools": {
348
+ const lines = [];
349
+ lines.push(` Local (${LOCAL_TOOL_DEFINITIONS.length})`);
350
+ for (const t of LOCAL_TOOL_DEFINITIONS) {
351
+ lines.push(` ${t.name.padEnd(20)} ${t.description.slice(0, 48)}`);
352
+ }
353
+ lines.push("");
354
+ if (serverToolsAvailable > 0) {
355
+ lines.push(` Server (${serverToolsAvailable})`);
356
+ const serverDefs = getAllServerToolDefinitions();
357
+ for (const t of serverDefs) {
358
+ lines.push(` ${t.name.padEnd(20)} ${(t.description || "").slice(0, 48)}`);
359
+ }
360
+ }
361
+ else {
362
+ lines.push(" Server (unavailable — /mcp for details)");
363
+ }
364
+ setMessages((prev) => [...prev, { role: "assistant", text: lines.join("\n") }]);
365
+ break;
366
+ }
367
+ }
368
+ }, [exit, toolsExpanded, serverToolsAvailable, sessionId, thinkingEnabled, rewindCheckpointCount]);
369
+ // Store select handlers
370
+ const handleStoreSelect = useCallback((store) => {
371
+ selectStore(store.id, store.name);
372
+ resetServerToolClient();
373
+ setStoreSelectMode(false);
374
+ setStoreList([]);
375
+ setUserLabel(store.name);
376
+ setMessages((prev) => [...prev, {
377
+ role: "assistant",
378
+ text: ` ${symbols.check} Switched to ${store.name}`,
379
+ }]);
380
+ getServerToolCount().then((count) => setServerToolsAvailable(count));
381
+ }, []);
382
+ const handleStoreCancel = useCallback(() => {
383
+ setStoreSelectMode(false);
384
+ setStoreList([]);
385
+ }, []);
386
+ return { handleCommand, handleStoreSelect, handleStoreCancel };
387
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * whale config — View and set configuration from the CLI
3
+ *
4
+ * Usage:
5
+ * whale config Show all settings
6
+ * whale config <key> Read single key
7
+ * whale config <key> <value> Write single key
8
+ * whale config --reset Reset to defaults
9
+ */
10
+ export declare function runConfigCommand(args: string[], flags: Record<string, unknown>): Promise<void>;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * whale config — View and set configuration from the CLI
3
+ *
4
+ * Usage:
5
+ * whale config Show all settings
6
+ * whale config <key> Read single key
7
+ * whale config <key> <value> Write single key
8
+ * whale config --reset Reset to defaults
9
+ */
10
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
11
+ import { join } from "path";
12
+ import { homedir } from "os";
13
+ const CONFIG_PATH = join(homedir(), ".swagmanager", "config.json");
14
+ const DIM = "\x1b[2m";
15
+ const BOLD = "\x1b[1m";
16
+ const RESET = "\x1b[0m";
17
+ function loadConfig() {
18
+ if (!existsSync(CONFIG_PATH))
19
+ return {};
20
+ try {
21
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ }
27
+ function saveConfig(config) {
28
+ const dir = join(homedir(), ".swagmanager");
29
+ if (!existsSync(dir))
30
+ mkdirSync(dir, { recursive: true });
31
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
32
+ }
33
+ function maskSecret(key, value) {
34
+ if (key.includes("key") || key.includes("token") || key.includes("secret")) {
35
+ if (value.length > 8) {
36
+ return value.slice(0, 4) + "..." + value.slice(-4);
37
+ }
38
+ return "***";
39
+ }
40
+ return value;
41
+ }
42
+ export async function runConfigCommand(args, flags) {
43
+ if (flags.reset) {
44
+ const dir = join(homedir(), ".swagmanager");
45
+ if (!existsSync(dir))
46
+ mkdirSync(dir, { recursive: true });
47
+ writeFileSync(CONFIG_PATH, JSON.stringify({}, null, 2), { mode: 0o600 });
48
+ console.log("Configuration reset to defaults.");
49
+ return;
50
+ }
51
+ const key = args[0];
52
+ const value = args[1];
53
+ if (!key) {
54
+ // Show all settings
55
+ const config = loadConfig();
56
+ console.log(`\n ${BOLD}whale config${RESET} ${DIM}(${CONFIG_PATH})${RESET}\n`);
57
+ if (Object.keys(config).length === 0) {
58
+ console.log(" No configuration set.");
59
+ console.log(` ${DIM}Set a value: whale config <key> <value>${RESET}`);
60
+ }
61
+ else {
62
+ for (const [k, v] of Object.entries(config)) {
63
+ if (typeof v === "object" && v !== null) {
64
+ console.log(` ${k}:`);
65
+ for (const [sk, sv] of Object.entries(v)) {
66
+ const display = typeof sv === "string" ? maskSecret(sk, sv) : JSON.stringify(sv);
67
+ console.log(` ${sk}: ${DIM}${display}${RESET}`);
68
+ }
69
+ }
70
+ else {
71
+ const display = typeof v === "string" ? maskSecret(k, v) : String(v);
72
+ console.log(` ${k}: ${DIM}${display}${RESET}`);
73
+ }
74
+ }
75
+ }
76
+ console.log();
77
+ return;
78
+ }
79
+ if (!value) {
80
+ // Read single key
81
+ const config = loadConfig();
82
+ const v = config[key];
83
+ if (v === undefined) {
84
+ console.log(`${key}: (not set)`);
85
+ }
86
+ else if (typeof v === "object") {
87
+ console.log(JSON.stringify(v, null, 2));
88
+ }
89
+ else {
90
+ console.log(typeof v === "string" ? maskSecret(key, v) : String(v));
91
+ }
92
+ return;
93
+ }
94
+ // Write single key
95
+ const config = loadConfig();
96
+ config[key] = value;
97
+ saveConfig(config);
98
+ console.log(`${key} = ${value}`);
99
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * whale doctor — Run diagnostics
3
+ *
4
+ * Checks:
5
+ * - Node.js version (>=20)
6
+ * - ripgrep availability
7
+ * - Supabase connection
8
+ * - Auth status
9
+ * - Server tools loadable
10
+ * - MCP servers configured
11
+ * - Disk space
12
+ * - Package version vs latest
13
+ */
14
+ export declare function runDoctor(): Promise<void>;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * whale doctor — Run diagnostics
3
+ *
4
+ * Checks:
5
+ * - Node.js version (>=20)
6
+ * - ripgrep availability
7
+ * - Supabase connection
8
+ * - Auth status
9
+ * - Server tools loadable
10
+ * - MCP servers configured
11
+ * - Disk space
12
+ * - Package version vs latest
13
+ */
14
+ import { execSync } from "child_process";
15
+ import { existsSync, readFileSync } from "fs";
16
+ import { join } from "path";
17
+ import { homedir } from "os";
18
+ const CHECK = "\x1b[32m✓\x1b[0m";
19
+ const CROSS = "\x1b[31m✗\x1b[0m";
20
+ const WARN = "\x1b[33m!\x1b[0m";
21
+ const DIM = "\x1b[2m";
22
+ const RESET = "\x1b[0m";
23
+ function icon(status) {
24
+ if (status === "ok")
25
+ return CHECK;
26
+ if (status === "warn")
27
+ return WARN;
28
+ return CROSS;
29
+ }
30
+ async function checkNodeVersion() {
31
+ const version = process.version;
32
+ const major = parseInt(version.slice(1).split(".")[0], 10);
33
+ if (major >= 20) {
34
+ return { status: "ok", label: "Node.js", detail: version };
35
+ }
36
+ return { status: "error", label: "Node.js", detail: `${version} (need >=20)` };
37
+ }
38
+ async function checkRipgrep() {
39
+ try {
40
+ const version = execSync("rg --version 2>/dev/null", { encoding: "utf-8", timeout: 3000 }).trim().split("\n")[0];
41
+ return { status: "ok", label: "ripgrep", detail: version };
42
+ }
43
+ catch {
44
+ // Check if @vscode/ripgrep is available
45
+ try {
46
+ const { rgPath } = await import("@vscode/ripgrep");
47
+ return { status: "ok", label: "ripgrep", detail: `@vscode/ripgrep (${rgPath})` };
48
+ }
49
+ catch {
50
+ return { status: "warn", label: "ripgrep", detail: "not found (search will use fallback)" };
51
+ }
52
+ }
53
+ }
54
+ async function checkSupabase() {
55
+ try {
56
+ const { SUPABASE_URL } = await import("../services/auth-service.js");
57
+ const resp = await fetch(`${SUPABASE_URL}/rest/v1/`, {
58
+ method: "HEAD",
59
+ signal: AbortSignal.timeout(5000),
60
+ });
61
+ if (resp.ok || resp.status === 401) {
62
+ return { status: "ok", label: "Supabase", detail: "reachable" };
63
+ }
64
+ return { status: "warn", label: "Supabase", detail: `status ${resp.status}` };
65
+ }
66
+ catch (err) {
67
+ return { status: "error", label: "Supabase", detail: err.message?.slice(0, 60) || "unreachable" };
68
+ }
69
+ }
70
+ async function checkAuth() {
71
+ try {
72
+ const { isLoggedIn, getValidToken } = await import("../services/auth-service.js");
73
+ if (!isLoggedIn()) {
74
+ // Check for API key
75
+ const { loadConfig } = await import("../services/config-store.js");
76
+ const config = loadConfig();
77
+ if (process.env.ANTHROPIC_API_KEY || config.anthropic_api_key) {
78
+ return { status: "ok", label: "Auth", detail: "API key configured" };
79
+ }
80
+ return { status: "warn", label: "Auth", detail: "not logged in (run: whale login)" };
81
+ }
82
+ const token = await getValidToken();
83
+ return token
84
+ ? { status: "ok", label: "Auth", detail: "valid JWT" }
85
+ : { status: "warn", label: "Auth", detail: "token expired" };
86
+ }
87
+ catch {
88
+ return { status: "error", label: "Auth", detail: "check failed" };
89
+ }
90
+ }
91
+ async function checkServerTools() {
92
+ try {
93
+ const { loadServerToolDefinitions } = await import("../services/server-tools.js");
94
+ const tools = await loadServerToolDefinitions();
95
+ return { status: "ok", label: "Server tools", detail: `${tools.length} tools loaded` };
96
+ }
97
+ catch (err) {
98
+ return { status: "warn", label: "Server tools", detail: err.message?.slice(0, 60) || "unavailable" };
99
+ }
100
+ }
101
+ async function checkMcpServers() {
102
+ const configPath = join(homedir(), ".swagmanager", "config.json");
103
+ if (!existsSync(configPath)) {
104
+ return { status: "warn", label: "MCP servers", detail: "none configured" };
105
+ }
106
+ try {
107
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
108
+ const servers = config.mcpServers || {};
109
+ const count = Object.keys(servers).length;
110
+ if (count === 0) {
111
+ return { status: "warn", label: "MCP servers", detail: "none configured" };
112
+ }
113
+ return { status: "ok", label: "MCP servers", detail: `${count} configured` };
114
+ }
115
+ catch {
116
+ return { status: "warn", label: "MCP servers", detail: "config parse error" };
117
+ }
118
+ }
119
+ async function checkDiskSpace() {
120
+ const dir = join(homedir(), ".swagmanager");
121
+ if (!existsSync(dir)) {
122
+ return { status: "ok", label: "Data dir", detail: "~/.swagmanager/ (not created yet)" };
123
+ }
124
+ try {
125
+ // Get total size
126
+ const output = execSync(`du -sh "${dir}" 2>/dev/null`, { encoding: "utf-8", timeout: 5000 }).trim();
127
+ const size = output.split("\t")[0];
128
+ return { status: "ok", label: "Data dir", detail: `~/.swagmanager/ (${size})` };
129
+ }
130
+ catch {
131
+ return { status: "ok", label: "Data dir", detail: "~/.swagmanager/" };
132
+ }
133
+ }
134
+ async function checkVersion() {
135
+ try {
136
+ const pkgPath = join(new URL("../../..", import.meta.url).pathname, "package.json");
137
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
138
+ return { status: "ok", label: "Version", detail: `v${pkg.version}` };
139
+ }
140
+ catch {
141
+ return { status: "ok", label: "Version", detail: "unknown" };
142
+ }
143
+ }
144
+ export async function runDoctor() {
145
+ console.log("\n whale doctor\n");
146
+ const checks = await Promise.all([
147
+ checkNodeVersion(),
148
+ checkRipgrep(),
149
+ checkSupabase(),
150
+ checkAuth(),
151
+ checkServerTools(),
152
+ checkMcpServers(),
153
+ checkDiskSpace(),
154
+ checkVersion(),
155
+ ]);
156
+ for (const check of checks) {
157
+ console.log(` ${icon(check.status)} ${check.label.padEnd(16)} ${DIM}${check.detail}${RESET}`);
158
+ }
159
+ const errors = checks.filter(c => c.status === "error").length;
160
+ const warnings = checks.filter(c => c.status === "warn").length;
161
+ console.log();
162
+ if (errors > 0) {
163
+ console.log(` ${CROSS} ${errors} error${errors > 1 ? "s" : ""}, ${warnings} warning${warnings !== 1 ? "s" : ""}`);
164
+ }
165
+ else if (warnings > 0) {
166
+ console.log(` ${WARN} All good, ${warnings} warning${warnings !== 1 ? "s" : ""}`);
167
+ }
168
+ else {
169
+ console.log(` ${CHECK} All checks passed`);
170
+ }
171
+ console.log();
172
+ }