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,16 @@
1
+ /**
2
+ * /init command — scan project and generate .whale/CLAUDE.md
3
+ *
4
+ * Two exports:
5
+ * - runInit() — standalone CLI subcommand (console.log output)
6
+ * - runInitInline() — returns string for in-chat /init
7
+ */
8
+ /**
9
+ * Standalone CLI: `whale init`
10
+ */
11
+ export declare function runInit(): Promise<void>;
12
+ /**
13
+ * In-chat: /init
14
+ * Returns a string to display as an assistant message.
15
+ */
16
+ export declare function runInitInline(): Promise<string>;
@@ -0,0 +1,278 @@
1
+ /**
2
+ * /init command — scan project and generate .whale/CLAUDE.md
3
+ *
4
+ * Two exports:
5
+ * - runInit() — standalone CLI subcommand (console.log output)
6
+ * - runInitInline() — returns string for in-chat /init
7
+ */
8
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, statSync } from "fs";
9
+ import { join, basename } from "path";
10
+ function detectProject(cwd) {
11
+ const info = {
12
+ name: basename(cwd),
13
+ description: "",
14
+ language: "",
15
+ framework: "",
16
+ buildCmd: "",
17
+ testCmd: "",
18
+ srcDir: "",
19
+ testDir: "",
20
+ conventions: [],
21
+ gitRemote: "",
22
+ };
23
+ // ── package.json (Node/JS/TS) ──
24
+ const pkgPath = join(cwd, "package.json");
25
+ if (existsSync(pkgPath)) {
26
+ try {
27
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
28
+ info.name = pkg.name || info.name;
29
+ info.description = pkg.description || "";
30
+ // Detect language
31
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
32
+ if (existsSync(join(cwd, "tsconfig.json")) || deps["typescript"]) {
33
+ info.language = "TypeScript";
34
+ }
35
+ else {
36
+ info.language = "JavaScript";
37
+ }
38
+ // Detect framework
39
+ if (deps["next"])
40
+ info.framework = "Next.js";
41
+ else if (deps["react"] && deps["ink"])
42
+ info.framework = "React + Ink (CLI)";
43
+ else if (deps["react"])
44
+ info.framework = "React";
45
+ else if (deps["vue"])
46
+ info.framework = "Vue";
47
+ else if (deps["svelte"])
48
+ info.framework = "Svelte";
49
+ else if (deps["express"])
50
+ info.framework = "Express";
51
+ else if (deps["fastify"])
52
+ info.framework = "Fastify";
53
+ else if (deps["hono"])
54
+ info.framework = "Hono";
55
+ else if (deps["@angular/core"])
56
+ info.framework = "Angular";
57
+ // Build & test commands
58
+ if (pkg.scripts?.build)
59
+ info.buildCmd = `npm run build`;
60
+ if (pkg.scripts?.test)
61
+ info.testCmd = `npm test`;
62
+ if (pkg.scripts?.dev)
63
+ info.buildCmd = info.buildCmd || `npm run dev`;
64
+ }
65
+ catch { /* corrupt package.json */ }
66
+ }
67
+ // ── pyproject.toml / requirements.txt (Python) ──
68
+ if (existsSync(join(cwd, "pyproject.toml"))) {
69
+ info.language = info.language || "Python";
70
+ try {
71
+ const toml = readFileSync(join(cwd, "pyproject.toml"), "utf-8");
72
+ const nameMatch = toml.match(/name\s*=\s*"([^"]+)"/);
73
+ if (nameMatch)
74
+ info.name = nameMatch[1];
75
+ if (toml.includes("django"))
76
+ info.framework = "Django";
77
+ else if (toml.includes("fastapi"))
78
+ info.framework = "FastAPI";
79
+ else if (toml.includes("flask"))
80
+ info.framework = "Flask";
81
+ }
82
+ catch { /* ignore */ }
83
+ if (!info.buildCmd)
84
+ info.buildCmd = "python -m build";
85
+ if (!info.testCmd)
86
+ info.testCmd = "pytest";
87
+ }
88
+ else if (existsSync(join(cwd, "requirements.txt"))) {
89
+ info.language = info.language || "Python";
90
+ if (!info.testCmd)
91
+ info.testCmd = "pytest";
92
+ }
93
+ // ── Cargo.toml (Rust) ──
94
+ if (existsSync(join(cwd, "Cargo.toml"))) {
95
+ info.language = info.language || "Rust";
96
+ try {
97
+ const cargo = readFileSync(join(cwd, "Cargo.toml"), "utf-8");
98
+ const nameMatch = cargo.match(/name\s*=\s*"([^"]+)"/);
99
+ if (nameMatch)
100
+ info.name = nameMatch[1];
101
+ }
102
+ catch { /* ignore */ }
103
+ info.buildCmd = info.buildCmd || "cargo build";
104
+ info.testCmd = info.testCmd || "cargo test";
105
+ }
106
+ // ── go.mod (Go) ──
107
+ if (existsSync(join(cwd, "go.mod"))) {
108
+ info.language = info.language || "Go";
109
+ try {
110
+ const gomod = readFileSync(join(cwd, "go.mod"), "utf-8");
111
+ const moduleMatch = gomod.match(/module\s+(\S+)/);
112
+ if (moduleMatch)
113
+ info.name = moduleMatch[1].split("/").pop() || info.name;
114
+ }
115
+ catch { /* ignore */ }
116
+ info.buildCmd = info.buildCmd || "go build ./...";
117
+ info.testCmd = info.testCmd || "go test ./...";
118
+ }
119
+ // ── README.md — first paragraph for description ──
120
+ if (!info.description) {
121
+ const readmePath = join(cwd, "README.md");
122
+ if (existsSync(readmePath)) {
123
+ try {
124
+ const readme = readFileSync(readmePath, "utf-8");
125
+ const lines = readme.split("\n");
126
+ // Skip title lines (# heading), blank lines, badges
127
+ let para = "";
128
+ for (const line of lines) {
129
+ if (line.startsWith("#") || line.startsWith("![") || line.startsWith("[![") || !line.trim()) {
130
+ if (para)
131
+ break; // End of first paragraph
132
+ continue;
133
+ }
134
+ para += (para ? " " : "") + line.trim();
135
+ }
136
+ if (para && para.length < 200)
137
+ info.description = para;
138
+ }
139
+ catch { /* ignore */ }
140
+ }
141
+ }
142
+ // ── Git remote ──
143
+ const gitConfigPath = join(cwd, ".git", "config");
144
+ if (existsSync(gitConfigPath)) {
145
+ try {
146
+ const gitConfig = readFileSync(gitConfigPath, "utf-8");
147
+ const urlMatch = gitConfig.match(/url\s*=\s*(.+)/);
148
+ if (urlMatch)
149
+ info.gitRemote = urlMatch[1].trim();
150
+ }
151
+ catch { /* ignore */ }
152
+ }
153
+ // ── Directory structure ──
154
+ const dirExists = (name) => {
155
+ try {
156
+ return statSync(join(cwd, name)).isDirectory();
157
+ }
158
+ catch {
159
+ return false;
160
+ }
161
+ };
162
+ if (dirExists("src"))
163
+ info.srcDir = "src/";
164
+ else if (dirExists("lib"))
165
+ info.srcDir = "lib/";
166
+ else if (dirExists("app"))
167
+ info.srcDir = "app/";
168
+ if (dirExists("tests"))
169
+ info.testDir = "tests/";
170
+ else if (dirExists("test"))
171
+ info.testDir = "test/";
172
+ else if (dirExists("__tests__"))
173
+ info.testDir = "__tests__/";
174
+ else if (dirExists("spec"))
175
+ info.testDir = "spec/";
176
+ // ── Conventions ──
177
+ if (existsSync(join(cwd, ".eslintrc.json")) || existsSync(join(cwd, ".eslintrc.js")) || existsSync(join(cwd, "eslint.config.js")) || existsSync(join(cwd, "eslint.config.mjs"))) {
178
+ info.conventions.push("ESLint configured");
179
+ }
180
+ if (existsSync(join(cwd, ".prettierrc")) || existsSync(join(cwd, ".prettierrc.json")) || existsSync(join(cwd, "prettier.config.js"))) {
181
+ info.conventions.push("Prettier configured");
182
+ }
183
+ if (existsSync(join(cwd, ".editorconfig"))) {
184
+ info.conventions.push("EditorConfig");
185
+ }
186
+ if (existsSync(join(cwd, "Dockerfile")) || existsSync(join(cwd, "docker-compose.yml"))) {
187
+ info.conventions.push("Docker");
188
+ }
189
+ if (existsSync(join(cwd, ".github"))) {
190
+ info.conventions.push("GitHub Actions CI");
191
+ }
192
+ return info;
193
+ }
194
+ // ============================================================================
195
+ // MARKDOWN GENERATOR
196
+ // ============================================================================
197
+ function generateMarkdown(info) {
198
+ const lines = [];
199
+ lines.push(`# ${info.name}`);
200
+ lines.push("");
201
+ if (info.description) {
202
+ lines.push(info.description);
203
+ lines.push("");
204
+ }
205
+ lines.push("## Stack");
206
+ if (info.language)
207
+ lines.push(`- Language: ${info.language}`);
208
+ if (info.framework)
209
+ lines.push(`- Framework: ${info.framework}`);
210
+ if (info.buildCmd)
211
+ lines.push(`- Build: \`${info.buildCmd}\``);
212
+ if (info.testCmd)
213
+ lines.push(`- Test: \`${info.testCmd}\``);
214
+ lines.push("");
215
+ if (info.srcDir || info.testDir) {
216
+ lines.push("## Key Paths");
217
+ if (info.srcDir)
218
+ lines.push(`- Source: \`${info.srcDir}\``);
219
+ if (info.testDir)
220
+ lines.push(`- Tests: \`${info.testDir}\``);
221
+ lines.push("");
222
+ }
223
+ if (info.conventions.length > 0) {
224
+ lines.push("## Conventions");
225
+ for (const c of info.conventions) {
226
+ lines.push(`- ${c}`);
227
+ }
228
+ lines.push("");
229
+ }
230
+ if (info.gitRemote) {
231
+ lines.push("## Repository");
232
+ lines.push(`- ${info.gitRemote}`);
233
+ lines.push("");
234
+ }
235
+ return lines.join("\n");
236
+ }
237
+ // ============================================================================
238
+ // PUBLIC API
239
+ // ============================================================================
240
+ /**
241
+ * Standalone CLI: `whale init`
242
+ */
243
+ export async function runInit() {
244
+ const cwd = process.cwd();
245
+ const whaleDir = join(cwd, ".whale");
246
+ const outPath = join(whaleDir, "CLAUDE.md");
247
+ if (existsSync(outPath)) {
248
+ console.log(` .whale/CLAUDE.md already exists. Delete it first to regenerate.`);
249
+ return;
250
+ }
251
+ const info = detectProject(cwd);
252
+ const markdown = generateMarkdown(info);
253
+ if (!existsSync(whaleDir))
254
+ mkdirSync(whaleDir, { recursive: true });
255
+ writeFileSync(outPath, markdown, "utf-8");
256
+ console.log(` Created .whale/CLAUDE.md`);
257
+ console.log(` Detected: ${[info.language, info.framework].filter(Boolean).join(" + ") || "unknown stack"}`);
258
+ console.log(` Edit the file to add project-specific instructions.`);
259
+ }
260
+ /**
261
+ * In-chat: /init
262
+ * Returns a string to display as an assistant message.
263
+ */
264
+ export async function runInitInline() {
265
+ const cwd = process.cwd();
266
+ const whaleDir = join(cwd, ".whale");
267
+ const outPath = join(whaleDir, "CLAUDE.md");
268
+ if (existsSync(outPath)) {
269
+ return " .whale/CLAUDE.md already exists. Delete it first to regenerate.";
270
+ }
271
+ const info = detectProject(cwd);
272
+ const markdown = generateMarkdown(info);
273
+ if (!existsSync(whaleDir))
274
+ mkdirSync(whaleDir, { recursive: true });
275
+ writeFileSync(outPath, markdown, "utf-8");
276
+ const stack = [info.language, info.framework].filter(Boolean).join(" + ") || "unknown stack";
277
+ return ` Created .whale/CLAUDE.md\n Detected: ${stack}\n Edit the file to add project-specific instructions.`;
278
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * whale mcp — Manage MCP server configurations
3
+ *
4
+ * Usage:
5
+ * whale mcp list List configured servers
6
+ * whale mcp add <name> -- <cmd> [args...] Add stdio server
7
+ * whale mcp add --transport http <name> <url> Add HTTP server
8
+ * whale mcp add -e KEY=VAL <name> -- <cmd> Add with env vars
9
+ * whale mcp remove <name> Remove server
10
+ * whale mcp get <name> Show server config
11
+ */
12
+ export declare function runMcpCommand(args: string[]): Promise<void>;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * whale mcp — Manage MCP server configurations
3
+ *
4
+ * Usage:
5
+ * whale mcp list List configured servers
6
+ * whale mcp add <name> -- <cmd> [args...] Add stdio server
7
+ * whale mcp add --transport http <name> <url> Add HTTP server
8
+ * whale mcp add -e KEY=VAL <name> -- <cmd> Add with env vars
9
+ * whale mcp remove <name> Remove server
10
+ * whale mcp get <name> Show server config
11
+ */
12
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
13
+ import { join } from "path";
14
+ import { homedir } from "os";
15
+ const CONFIG_PATH = join(homedir(), ".swagmanager", "config.json");
16
+ function loadConfig() {
17
+ if (!existsSync(CONFIG_PATH))
18
+ return {};
19
+ try {
20
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
21
+ }
22
+ catch {
23
+ return {};
24
+ }
25
+ }
26
+ function saveConfig(config) {
27
+ const dir = join(homedir(), ".swagmanager");
28
+ if (!existsSync(dir))
29
+ mkdirSync(dir, { recursive: true });
30
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
31
+ }
32
+ function getServers(config) {
33
+ return config.mcpServers || {};
34
+ }
35
+ export async function runMcpCommand(args) {
36
+ const subcommand = args[0];
37
+ if (!subcommand || subcommand === "list") {
38
+ const config = loadConfig();
39
+ const servers = getServers(config);
40
+ const names = Object.keys(servers);
41
+ if (names.length === 0) {
42
+ console.log("No MCP servers configured.");
43
+ console.log("Add one: whale mcp add <name> -- <command> [args...]");
44
+ return;
45
+ }
46
+ console.log("Configured MCP servers:\n");
47
+ for (const name of names) {
48
+ const s = servers[name];
49
+ if (s.transport === "http") {
50
+ console.log(` ${name} (http) → ${s.url}`);
51
+ }
52
+ else {
53
+ const cmd = [s.command, ...(s.args || [])].join(" ");
54
+ console.log(` ${name} (stdio) → ${cmd}`);
55
+ }
56
+ if (s.env && Object.keys(s.env).length > 0) {
57
+ console.log(` env: ${Object.keys(s.env).join(", ")}`);
58
+ }
59
+ }
60
+ return;
61
+ }
62
+ if (subcommand === "add") {
63
+ const restArgs = args.slice(1);
64
+ // Parse -e KEY=VAL and --transport flags
65
+ const envVars = {};
66
+ let transport = "stdio";
67
+ const filteredArgs = [];
68
+ for (let i = 0; i < restArgs.length; i++) {
69
+ if (restArgs[i] === "-e" && i + 1 < restArgs.length) {
70
+ const kv = restArgs[++i];
71
+ const eqIdx = kv.indexOf("=");
72
+ if (eqIdx > 0) {
73
+ envVars[kv.slice(0, eqIdx)] = kv.slice(eqIdx + 1);
74
+ }
75
+ }
76
+ else if (restArgs[i] === "--transport" && i + 1 < restArgs.length) {
77
+ transport = restArgs[++i];
78
+ }
79
+ else {
80
+ filteredArgs.push(restArgs[i]);
81
+ }
82
+ }
83
+ if (transport === "http") {
84
+ // whale mcp add --transport http <name> <url>
85
+ const name = filteredArgs[0];
86
+ const url = filteredArgs[1];
87
+ if (!name || !url) {
88
+ console.error("Usage: whale mcp add --transport http <name> <url>");
89
+ process.exit(1);
90
+ }
91
+ const config = loadConfig();
92
+ const servers = getServers(config);
93
+ servers[name] = { transport: "http", url, env: Object.keys(envVars).length > 0 ? envVars : undefined };
94
+ config.mcpServers = servers;
95
+ saveConfig(config);
96
+ console.log(`Added HTTP MCP server: ${name} → ${url}`);
97
+ return;
98
+ }
99
+ // stdio: whale mcp add <name> -- <cmd> [args...]
100
+ const dashDash = filteredArgs.indexOf("--");
101
+ if (dashDash < 1) {
102
+ console.error("Usage: whale mcp add <name> -- <command> [args...]");
103
+ process.exit(1);
104
+ }
105
+ const name = filteredArgs[0];
106
+ const command = filteredArgs[dashDash + 1];
107
+ const cmdArgs = filteredArgs.slice(dashDash + 2);
108
+ if (!name || !command) {
109
+ console.error("Usage: whale mcp add <name> -- <command> [args...]");
110
+ process.exit(1);
111
+ }
112
+ const config = loadConfig();
113
+ const servers = getServers(config);
114
+ servers[name] = {
115
+ command,
116
+ args: cmdArgs.length > 0 ? cmdArgs : undefined,
117
+ env: Object.keys(envVars).length > 0 ? envVars : undefined,
118
+ transport: "stdio",
119
+ };
120
+ config.mcpServers = servers;
121
+ saveConfig(config);
122
+ console.log(`Added stdio MCP server: ${name} → ${[command, ...cmdArgs].join(" ")}`);
123
+ return;
124
+ }
125
+ if (subcommand === "remove") {
126
+ const name = args[1];
127
+ if (!name) {
128
+ console.error("Usage: whale mcp remove <name>");
129
+ process.exit(1);
130
+ }
131
+ const config = loadConfig();
132
+ const servers = getServers(config);
133
+ if (!servers[name]) {
134
+ console.error(`MCP server not found: ${name}`);
135
+ process.exit(1);
136
+ }
137
+ delete servers[name];
138
+ config.mcpServers = servers;
139
+ saveConfig(config);
140
+ console.log(`Removed MCP server: ${name}`);
141
+ return;
142
+ }
143
+ if (subcommand === "get") {
144
+ const name = args[1];
145
+ if (!name) {
146
+ console.error("Usage: whale mcp get <name>");
147
+ process.exit(1);
148
+ }
149
+ const config = loadConfig();
150
+ const servers = getServers(config);
151
+ const server = servers[name];
152
+ if (!server) {
153
+ console.error(`MCP server not found: ${name}`);
154
+ process.exit(1);
155
+ }
156
+ console.log(JSON.stringify(server, null, 2));
157
+ return;
158
+ }
159
+ console.error(`Unknown mcp subcommand: ${subcommand}`);
160
+ console.error("Usage: whale mcp list|add|remove|get");
161
+ process.exit(1);
162
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Login Flow — browser-first with email/password fallback
3
+ *
4
+ * Default: opens browser → whaletools.dev/auth/cli → localhost callback
5
+ * Fallback: press E for terminal-based email/password (legacy)
6
+ */
7
+ export declare function LoginApp(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,157 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * Login Flow — browser-first with email/password fallback
4
+ *
5
+ * Default: opens browser → whaletools.dev/auth/cli → localhost callback
6
+ * Fallback: press E for terminal-based email/password (legacy)
7
+ */
8
+ import { useState, useEffect } from "react";
9
+ import { Box, Text, useApp, useInput } from "ink";
10
+ import TextInput from "ink-text-input";
11
+ import Spinner from "ink-spinner";
12
+ import SelectInput from "ink-select-input";
13
+ import { signIn, signUp, getStoresForUser, selectStore, } from "../services/auth-service.js";
14
+ import { signInWithBrowser } from "../services/browser-auth.js";
15
+ import { WhaleBanner } from "../shared/WhaleBanner.js";
16
+ import { colors, symbols, boxLine } from "../shared/Theme.js";
17
+ export function LoginApp() {
18
+ const { exit } = useApp();
19
+ const [step, setStep] = useState("browser_opening");
20
+ const [mode, setMode] = useState("login");
21
+ const [email, setEmail] = useState("");
22
+ const [inputValue, setInputValue] = useState("");
23
+ const [error, setError] = useState("");
24
+ const [stores, setStores] = useState([]);
25
+ const [resultEmail, setResultEmail] = useState("");
26
+ const [resultStore, setResultStore] = useState("");
27
+ const [loginUrl, setLoginUrl] = useState("");
28
+ const [browserFallback, setBrowserFallback] = useState(false);
29
+ // Auto-exit after success
30
+ useEffect(() => {
31
+ if (step === "done") {
32
+ const timer = setTimeout(() => exit(), 300);
33
+ return () => clearTimeout(timer);
34
+ }
35
+ }, [step, exit]);
36
+ // Start browser auth on mount
37
+ useEffect(() => {
38
+ if (browserFallback)
39
+ return;
40
+ signInWithBrowser(undefined, {
41
+ onBrowserOpening: (url) => {
42
+ setLoginUrl(url);
43
+ setStep("browser_opening");
44
+ },
45
+ onWaitingForCallback: () => {
46
+ setStep("browser_waiting");
47
+ },
48
+ onExchangingCode: () => {
49
+ // Stay on browser_waiting with spinner
50
+ },
51
+ }).then((result) => {
52
+ if (browserFallback)
53
+ return; // User already switched to email mode
54
+ if (!result.success) {
55
+ // If browser auth failed and user hasn't switched, show error
56
+ setError(result.error || "Browser login failed");
57
+ setStep("error");
58
+ return;
59
+ }
60
+ const config = result.config;
61
+ setResultEmail(config.email || "");
62
+ if (result.stores && result.stores.length > 1) {
63
+ // Multiple stores — need selection
64
+ setStores(result.stores);
65
+ setStep("store_select");
66
+ }
67
+ else {
68
+ setResultStore(config.store_name || config.store_id || "");
69
+ setStep("done");
70
+ }
71
+ });
72
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
73
+ // Listen for 'E' key to switch to email/password fallback
74
+ useInput((input, key) => {
75
+ if ((step === "browser_opening" || step === "browser_waiting") &&
76
+ (input === "e" || input === "E") &&
77
+ !browserFallback) {
78
+ setBrowserFallback(true);
79
+ setStep("mode");
80
+ }
81
+ });
82
+ // ── Legacy email/password handlers ──
83
+ const handleModeSubmit = (value) => {
84
+ if (value === "1" || value.toLowerCase().startsWith("l")) {
85
+ setMode("login");
86
+ setStep("email");
87
+ }
88
+ else if (value === "2" || value.toLowerCase().startsWith("s")) {
89
+ setMode("signup");
90
+ setStep("email");
91
+ }
92
+ setInputValue("");
93
+ };
94
+ const handleEmailSubmit = (value) => {
95
+ if (!value.trim())
96
+ return;
97
+ setEmail(value.trim());
98
+ setInputValue("");
99
+ setStep("password");
100
+ };
101
+ const handlePasswordSubmit = async (value) => {
102
+ if (!value.trim())
103
+ return;
104
+ setInputValue("");
105
+ setStep("authenticating");
106
+ try {
107
+ const result = mode === "login"
108
+ ? await signIn(email, value)
109
+ : await signUp(email, value);
110
+ if (!result.success) {
111
+ setError(result.error || "Authentication failed");
112
+ setStep("error");
113
+ return;
114
+ }
115
+ if (result.error && !result.config) {
116
+ setError(result.error);
117
+ setStep("error");
118
+ return;
119
+ }
120
+ const config = result.config;
121
+ setResultEmail(config.email || email);
122
+ if (config.store_id) {
123
+ setResultStore(config.store_name || config.store_id);
124
+ setStep("done");
125
+ }
126
+ else {
127
+ const userStores = await getStoresForUser(config.access_token, config.user_id);
128
+ if (userStores.length === 0) {
129
+ setError("No stores found. Contact your admin.");
130
+ setStep("error");
131
+ }
132
+ else if (userStores.length === 1) {
133
+ selectStore(userStores[0].id, userStores[0].name);
134
+ setResultStore(userStores[0].name);
135
+ setStep("done");
136
+ }
137
+ else {
138
+ setStores(userStores);
139
+ setStep("store_select");
140
+ }
141
+ }
142
+ }
143
+ catch (err) {
144
+ setError(String(err));
145
+ setStep("error");
146
+ }
147
+ };
148
+ const handleStoreSelect = (item) => {
149
+ const store = stores.find((s) => s.id === item.value);
150
+ if (store) {
151
+ selectStore(store.id, store.name);
152
+ setResultStore(store.name);
153
+ setStep("done");
154
+ }
155
+ };
156
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(WhaleBanner, { subtitle: "authenticate" }), _jsx(Box, { height: 1 }), _jsx(Text, { color: colors.border, children: boxLine(44) }), _jsx(Box, { height: 1 }), step === "browser_opening" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: colors.brand, children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: colors.muted, children: " Opening browser..." })] }), loginUrl && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Text, { color: colors.dim, children: " If the browser didn't open, visit:" }), _jsxs(Text, { color: colors.text, children: [" ", loginUrl] })] })), _jsx(Box, { height: 1 }), _jsxs(Text, { color: colors.dim, children: [" Press ", _jsx(Text, { color: colors.brand, children: "E" }), " for email/password login"] })] })), step === "browser_waiting" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: colors.brand, children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: colors.muted, children: " Waiting for browser login..." })] }), loginUrl && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Text, { color: colors.dim, children: " If the browser didn't open, visit:" }), _jsxs(Text, { color: colors.text, children: [" ", loginUrl] })] })), _jsx(Box, { height: 1 }), _jsxs(Text, { color: colors.dim, children: [" Press ", _jsx(Text, { color: colors.brand, children: "E" }), " for email/password login"] })] })), step === "mode" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: colors.muted, children: " 1 " }), _jsx(Text, { color: colors.text, children: "Login to existing account" })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: colors.muted, children: " 2 " }), _jsx(Text, { color: colors.text, children: "Create new account" })] }), _jsx(Box, { height: 1 }), _jsxs(Box, { children: [_jsxs(Text, { color: colors.brand, children: [symbols.arrowRight, " "] }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleModeSubmit, placeholder: "1 or 2" })] })] })), step === "email" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.muted, children: mode === "login" ? "Login" : "Sign Up" }), _jsx(Box, { height: 1 }), _jsxs(Box, { children: [_jsx(Text, { color: colors.brand, children: "email " }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleEmailSubmit })] })] })), step === "password" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: colors.dim, children: ["email: ", email] }), _jsx(Box, { height: 1 }), _jsxs(Box, { children: [_jsx(Text, { color: colors.brand, children: "password " }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, mask: "*", onSubmit: handlePasswordSubmit })] })] })), step === "authenticating" && (_jsxs(Box, { children: [_jsx(Text, { color: colors.brand, children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: colors.muted, children: " authenticating\u2026" })] })), step === "store_select" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.muted, children: "Select your store:" }), _jsx(Box, { height: 1 }), _jsx(SelectInput, { items: stores.map((s) => ({ label: s.name + (s.slug ? ` (${s.slug})` : ""), value: s.id })), onSelect: handleStoreSelect, indicatorComponent: ({ isSelected }) => (_jsxs(Text, { color: isSelected ? colors.brand : colors.dim, children: [isSelected ? symbols.arrowRight : " ", " "] })) })] })), step === "done" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: colors.success, children: [symbols.check, " "] }), _jsx(Text, { color: colors.text, bold: true, children: "Logged in" })] }), _jsx(Box, { height: 1 }), _jsxs(Box, { children: [_jsxs(Text, { color: colors.dim, children: [" ", "user "] }), _jsx(Text, { color: colors.text, children: resultEmail })] }), _jsxs(Box, { children: [_jsxs(Text, { color: colors.dim, children: [" ", "store "] }), _jsx(Text, { color: colors.text, children: resultStore })] }), _jsx(Box, { height: 1 }), _jsx(Text, { color: colors.muted, children: " Run `whale` to start chatting." })] })), step === "error" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: colors.error, children: [symbols.cross, " "] }), _jsx(Text, { color: colors.error, children: error })] }), _jsx(Box, { height: 1 }), _jsx(Text, { color: colors.dim, children: " Try again: whale login" })] }))] }));
157
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Print Mode — non-interactive headless agent runner
3
+ *
4
+ * Used for:
5
+ * whale -p "prompt" Text output to stdout
6
+ * whale -p --output-format json "..." Single JSON result
7
+ * whale -p --output-format stream-json NDJSON event stream
8
+ * echo "..." | whale -p Read prompt from stdin
9
+ *
10
+ * Auto-yolo mode (no permission prompts).
11
+ * Exit codes: 0=success, 1=error, 2=budget exceeded, 130=SIGINT
12
+ */
13
+ export interface PrintModeOptions {
14
+ message: string;
15
+ outputFormat: "text" | "json" | "stream-json";
16
+ model?: string;
17
+ permissionMode?: string;
18
+ resumeSessionId?: string;
19
+ continueLastSession?: boolean;
20
+ sessionId?: string;
21
+ noSessionPersistence?: boolean;
22
+ maxTurns?: number;
23
+ maxBudgetUsd?: number;
24
+ effort?: string;
25
+ allowedTools?: string[];
26
+ disallowedTools?: string[];
27
+ fallbackModel?: string;
28
+ debug?: boolean;
29
+ verbose?: boolean;
30
+ }
31
+ export declare function runPrintMode(opts: PrintModeOptions): Promise<number>;