whale-code 6.5.4 → 6.5.6

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 (853) hide show
  1. package/README.md +39 -31
  2. package/bin/{swagmanager-mcp.js → whale-code.js} +17 -2
  3. package/dist/cli/app.js +148 -72
  4. package/dist/cli/app.js.map +1 -0
  5. package/dist/cli/chat/AgentSelector.js +105 -10
  6. package/dist/cli/chat/AgentSelector.js.map +1 -0
  7. package/dist/cli/chat/ChatApp.d.ts +31 -0
  8. package/dist/cli/chat/ChatApp.js +539 -286
  9. package/dist/cli/chat/ChatApp.js.map +1 -0
  10. package/dist/cli/chat/ChatInput.js +1088 -770
  11. package/dist/cli/chat/ChatInput.js.map +1 -0
  12. package/dist/cli/chat/MarkdownText.js +39 -14
  13. package/dist/cli/chat/MarkdownText.js.map +1 -0
  14. package/dist/cli/chat/MemoryManager.js +181 -46
  15. package/dist/cli/chat/MemoryManager.js.map +1 -0
  16. package/dist/cli/chat/MessageList.d.ts +2 -3
  17. package/dist/cli/chat/MessageList.js +186 -45
  18. package/dist/cli/chat/MessageList.js.map +1 -0
  19. package/dist/cli/chat/ModelSelector.js +282 -63
  20. package/dist/cli/chat/ModelSelector.js.map +1 -0
  21. package/dist/cli/chat/NodeManager.js +165 -75
  22. package/dist/cli/chat/NodeManager.js.map +1 -0
  23. package/dist/cli/chat/NodeSelector.js +171 -30
  24. package/dist/cli/chat/NodeSelector.js.map +1 -0
  25. package/dist/cli/chat/PlanApproval.js +281 -57
  26. package/dist/cli/chat/PlanApproval.js.map +1 -0
  27. package/dist/cli/chat/RewindViewer.js +559 -144
  28. package/dist/cli/chat/RewindViewer.js.map +1 -0
  29. package/dist/cli/chat/SessionManager.js +137 -30
  30. package/dist/cli/chat/SessionManager.js.map +1 -0
  31. package/dist/cli/chat/SlashMenu.js +293 -164
  32. package/dist/cli/chat/SlashMenu.js.map +1 -0
  33. package/dist/cli/chat/StatusBar.js +172 -9
  34. package/dist/cli/chat/StatusBar.js.map +1 -0
  35. package/dist/cli/chat/StoreSelector.js +147 -18
  36. package/dist/cli/chat/StoreSelector.js.map +1 -0
  37. package/dist/cli/chat/StreamingText.d.ts +1 -5
  38. package/dist/cli/chat/StreamingText.js +22 -7
  39. package/dist/cli/chat/StreamingText.js.map +1 -0
  40. package/dist/cli/chat/SubagentPanel.d.ts +1 -2
  41. package/dist/cli/chat/SubagentPanel.js +612 -72
  42. package/dist/cli/chat/SubagentPanel.js.map +1 -0
  43. package/dist/cli/chat/TeamPanel.d.ts +1 -0
  44. package/dist/cli/chat/TeamPanel.js +230 -30
  45. package/dist/cli/chat/TeamPanel.js.map +1 -0
  46. package/dist/cli/chat/ThemeSelector.js +84 -24
  47. package/dist/cli/chat/ThemeSelector.js.map +1 -0
  48. package/dist/cli/chat/ToolIndicator.js +1476 -371
  49. package/dist/cli/chat/ToolIndicator.js.map +1 -0
  50. package/dist/cli/chat/hooks/useAgentLoop.d.ts +1 -0
  51. package/dist/cli/chat/hooks/useAgentLoop.js +481 -367
  52. package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -0
  53. package/dist/cli/chat/hooks/useSlashCommands.d.ts +3 -14
  54. package/dist/cli/chat/hooks/useSlashCommands.js +744 -572
  55. package/dist/cli/chat/hooks/useSlashCommands.js.map +1 -0
  56. package/dist/cli/commands/config-cmd.js +56 -57
  57. package/dist/cli/commands/config-cmd.js.map +1 -0
  58. package/dist/cli/commands/db.js +184 -169
  59. package/dist/cli/commands/db.js.map +1 -0
  60. package/dist/cli/commands/doctor.js +212 -122
  61. package/dist/cli/commands/doctor.js.map +1 -0
  62. package/dist/cli/commands/init.js +211 -244
  63. package/dist/cli/commands/init.js.map +1 -0
  64. package/dist/cli/commands/mcp.js +127 -122
  65. package/dist/cli/commands/mcp.js.map +1 -0
  66. package/dist/cli/login/LoginApp.js +355 -141
  67. package/dist/cli/login/LoginApp.js.map +1 -0
  68. package/dist/cli/print-mode.js +196 -177
  69. package/dist/cli/print-mode.js.map +1 -0
  70. package/dist/cli/serve-mode.js +615 -530
  71. package/dist/cli/serve-mode.js.map +1 -0
  72. package/dist/cli/services/agent-config.d.ts +29 -0
  73. package/dist/cli/services/agent-config.js +91 -0
  74. package/dist/cli/services/agent-config.js.map +1 -0
  75. package/dist/cli/services/agent-definitions.d.ts +4 -1
  76. package/dist/cli/services/agent-definitions.js +97 -56
  77. package/dist/cli/services/agent-definitions.js.map +1 -0
  78. package/dist/cli/services/agent-events.js +225 -162
  79. package/dist/cli/services/agent-events.js.map +1 -0
  80. package/dist/cli/services/agent-loop.js +978 -669
  81. package/dist/cli/services/agent-loop.js.map +1 -0
  82. package/dist/cli/services/agent-worker-base.d.ts +35 -5
  83. package/dist/cli/services/agent-worker-base.js +337 -153
  84. package/dist/cli/services/agent-worker-base.js.map +1 -0
  85. package/dist/cli/services/api-retry.js +69 -64
  86. package/dist/cli/services/api-retry.js.map +1 -0
  87. package/dist/cli/services/auth-service.d.ts +3 -3
  88. package/dist/cli/services/auth-service.js +209 -132
  89. package/dist/cli/services/auth-service.js.map +1 -0
  90. package/dist/cli/services/background-processes.js +343 -267
  91. package/dist/cli/services/background-processes.js.map +1 -0
  92. package/dist/cli/services/browser-auth.d.ts +2 -2
  93. package/dist/cli/services/browser-auth.js +159 -118
  94. package/dist/cli/services/browser-auth.js.map +1 -0
  95. package/dist/cli/services/claude-md-loader.js +40 -36
  96. package/dist/cli/services/claude-md-loader.js.map +1 -0
  97. package/dist/cli/services/config-store.d.ts +9 -4
  98. package/dist/cli/services/config-store.js +164 -117
  99. package/dist/cli/services/config-store.js.map +1 -0
  100. package/dist/cli/services/debug-log.d.ts +1 -1
  101. package/dist/cli/services/debug-log.js +34 -35
  102. package/dist/cli/services/debug-log.js.map +1 -0
  103. package/dist/cli/services/env-detect.d.ts +7 -0
  104. package/dist/cli/services/env-detect.js +9 -0
  105. package/dist/cli/services/env-detect.js.map +1 -0
  106. package/dist/cli/services/error-logger.d.ts +2 -3
  107. package/dist/cli/services/error-logger.js +189 -180
  108. package/dist/cli/services/error-logger.js.map +1 -0
  109. package/dist/cli/services/file-history.d.ts +1 -1
  110. package/dist/cli/services/file-history.js +50 -54
  111. package/dist/cli/services/file-history.js.map +1 -0
  112. package/dist/cli/services/format-server-response.js +332 -372
  113. package/dist/cli/services/format-server-response.js.map +1 -0
  114. package/dist/cli/services/git-context.js +61 -45
  115. package/dist/cli/services/git-context.js.map +1 -0
  116. package/dist/cli/services/hooks.d.ts +2 -2
  117. package/dist/cli/services/hooks.js +195 -180
  118. package/dist/cli/services/hooks.js.map +1 -0
  119. package/dist/cli/services/ink-incremental.d.ts +19 -0
  120. package/dist/cli/services/ink-incremental.js +59 -0
  121. package/dist/cli/services/ink-incremental.js.map +1 -0
  122. package/dist/cli/services/ink-resize-fix.js +54 -44
  123. package/dist/cli/services/ink-resize-fix.js.map +1 -0
  124. package/dist/cli/services/ink-sync-output.d.ts +12 -0
  125. package/dist/cli/services/ink-sync-output.js +16 -0
  126. package/dist/cli/services/ink-sync-output.js.map +1 -0
  127. package/dist/cli/services/interactive-tools.js +268 -212
  128. package/dist/cli/services/interactive-tools.js.map +1 -0
  129. package/dist/cli/services/keybinding-manager.d.ts +11 -1
  130. package/dist/cli/services/keybinding-manager.js +126 -63
  131. package/dist/cli/services/keybinding-manager.js.map +1 -0
  132. package/dist/cli/services/local-tools.d.ts +1 -1
  133. package/dist/cli/services/local-tools.js +939 -656
  134. package/dist/cli/services/local-tools.js.map +1 -0
  135. package/dist/cli/services/lsp-manager.js +757 -594
  136. package/dist/cli/services/lsp-manager.js.map +1 -0
  137. package/dist/cli/services/mcp-client.d.ts +1 -1
  138. package/dist/cli/services/mcp-client.js +173 -134
  139. package/dist/cli/services/mcp-client.js.map +1 -0
  140. package/dist/cli/services/memory-manager.js +53 -40
  141. package/dist/cli/services/memory-manager.js.map +1 -0
  142. package/dist/cli/services/model-manager.js +55 -40
  143. package/dist/cli/services/model-manager.js.map +1 -0
  144. package/dist/cli/services/model-router.js +115 -85
  145. package/dist/cli/services/model-router.js.map +1 -0
  146. package/dist/cli/services/paths.d.ts +30 -0
  147. package/dist/cli/services/paths.js +81 -0
  148. package/dist/cli/services/paths.js.map +1 -0
  149. package/dist/cli/services/permission-modes.js +32 -25
  150. package/dist/cli/services/permission-modes.js.map +1 -0
  151. package/dist/cli/services/rewind.js +182 -168
  152. package/dist/cli/services/rewind.js.map +1 -0
  153. package/dist/cli/services/ripgrep.js +115 -115
  154. package/dist/cli/services/ripgrep.js.map +1 -0
  155. package/dist/cli/services/sandbox.d.ts +1 -1
  156. package/dist/cli/services/sandbox.js +58 -37
  157. package/dist/cli/services/sandbox.js.map +1 -0
  158. package/dist/cli/services/server-tools.js +738 -565
  159. package/dist/cli/services/server-tools.js.map +1 -0
  160. package/dist/cli/services/session-persistence.js +69 -74
  161. package/dist/cli/services/session-persistence.js.map +1 -0
  162. package/dist/cli/services/subagent-worker.js +42 -27
  163. package/dist/cli/services/subagent-worker.js.map +1 -0
  164. package/dist/cli/services/subagent.d.ts +2 -0
  165. package/dist/cli/services/subagent.js +606 -430
  166. package/dist/cli/services/subagent.js.map +1 -0
  167. package/dist/cli/services/system-prompt.js +86 -78
  168. package/dist/cli/services/system-prompt.js.map +1 -0
  169. package/dist/cli/services/task-decomposer.d.ts +1 -1
  170. package/dist/cli/services/task-decomposer.js +172 -139
  171. package/dist/cli/services/task-decomposer.js.map +1 -0
  172. package/dist/cli/services/team-lead.d.ts +2 -2
  173. package/dist/cli/services/team-lead.js +727 -529
  174. package/dist/cli/services/team-lead.js.map +1 -0
  175. package/dist/cli/services/team-state.js +319 -319
  176. package/dist/cli/services/team-state.js.map +1 -0
  177. package/dist/cli/services/teammate.d.ts +8 -2
  178. package/dist/cli/services/teammate.js +862 -560
  179. package/dist/cli/services/teammate.js.map +1 -0
  180. package/dist/cli/services/telemetry.d.ts +6 -1
  181. package/dist/cli/services/telemetry.js +180 -157
  182. package/dist/cli/services/telemetry.js.map +1 -0
  183. package/dist/cli/services/tools/agent-tools.d.ts +3 -3
  184. package/dist/cli/services/tools/agent-tools.js +480 -322
  185. package/dist/cli/services/tools/agent-tools.js.map +1 -0
  186. package/dist/cli/services/tools/file-ops.js +563 -450
  187. package/dist/cli/services/tools/file-ops.js.map +1 -0
  188. package/dist/cli/services/tools/search-tools.js +231 -162
  189. package/dist/cli/services/tools/search-tools.js.map +1 -0
  190. package/dist/cli/services/tools/shell-exec.js +197 -151
  191. package/dist/cli/services/tools/shell-exec.js.map +1 -0
  192. package/dist/cli/services/tools/task-manager.js +206 -173
  193. package/dist/cli/services/tools/task-manager.js.map +1 -0
  194. package/dist/cli/services/tools/web-tools.js +388 -341
  195. package/dist/cli/services/tools/web-tools.js.map +1 -0
  196. package/dist/cli/setup/SetupApp.d.ts +2 -2
  197. package/dist/cli/setup/SetupApp.js +608 -160
  198. package/dist/cli/setup/SetupApp.js.map +1 -0
  199. package/dist/cli/shared/ErrorBoundary.d.ts +22 -0
  200. package/dist/cli/shared/ErrorBoundary.js +73 -0
  201. package/dist/cli/shared/ErrorBoundary.js.map +1 -0
  202. package/dist/cli/shared/MatrixIntro.js +66 -69
  203. package/dist/cli/shared/MatrixIntro.js.map +1 -0
  204. package/dist/cli/shared/SpinnerSlot.d.ts +14 -0
  205. package/dist/cli/shared/SpinnerSlot.js +63 -0
  206. package/dist/cli/shared/SpinnerSlot.js.map +1 -0
  207. package/dist/cli/shared/Theme.d.ts +1 -1
  208. package/dist/cli/shared/Theme.js +136 -92
  209. package/dist/cli/shared/Theme.js.map +1 -0
  210. package/dist/cli/shared/WhaleBanner.js +99 -11
  211. package/dist/cli/shared/WhaleBanner.js.map +1 -0
  212. package/dist/cli/shared/markdown.d.ts +3 -1
  213. package/dist/cli/shared/markdown.js +736 -674
  214. package/dist/cli/shared/markdown.js.map +1 -0
  215. package/dist/cli/shared/marked-terminal.d.js +2 -0
  216. package/dist/cli/shared/marked-terminal.d.js.map +1 -0
  217. package/dist/cli/shared/theme-manager.js +99 -90
  218. package/dist/cli/shared/theme-manager.js.map +1 -0
  219. package/dist/cli/shared/theme-presets.js +256 -254
  220. package/dist/cli/shared/theme-presets.js.map +1 -0
  221. package/dist/cli/status/StatusApp.js +235 -86
  222. package/dist/cli/status/StatusApp.js.map +1 -0
  223. package/dist/cli/stores/StoreApp.js +275 -65
  224. package/dist/cli/stores/StoreApp.js.map +1 -0
  225. package/dist/index.d.ts +2 -2
  226. package/dist/index.js +509 -396
  227. package/dist/index.js.map +1 -0
  228. package/dist/local-agent/connection.d.ts +2 -2
  229. package/dist/local-agent/connection.js +352 -293
  230. package/dist/local-agent/connection.js.map +1 -0
  231. package/dist/local-agent/discovery.js +259 -122
  232. package/dist/local-agent/discovery.js.map +1 -0
  233. package/dist/local-agent/executor.js +216 -193
  234. package/dist/local-agent/executor.js.map +1 -0
  235. package/dist/local-agent/index.d.ts +2 -2
  236. package/dist/local-agent/index.js +156 -156
  237. package/dist/local-agent/index.js.map +1 -0
  238. package/dist/node/adapters/base.js +18 -8
  239. package/dist/node/adapters/base.js.map +1 -0
  240. package/dist/node/adapters/discord.js +286 -275
  241. package/dist/node/adapters/discord.js.map +1 -0
  242. package/dist/node/adapters/email.js +189 -202
  243. package/dist/node/adapters/email.js.map +1 -0
  244. package/dist/node/adapters/imessage.js +145 -142
  245. package/dist/node/adapters/imessage.js.map +1 -0
  246. package/dist/node/adapters/slack.js +237 -236
  247. package/dist/node/adapters/slack.js.map +1 -0
  248. package/dist/node/adapters/sms.js +149 -151
  249. package/dist/node/adapters/sms.js.map +1 -0
  250. package/dist/node/adapters/telegram.js +88 -92
  251. package/dist/node/adapters/telegram.js.map +1 -0
  252. package/dist/node/adapters/webchat.js +160 -136
  253. package/dist/node/adapters/webchat.js.map +1 -0
  254. package/dist/node/adapters/whatsapp.js +212 -215
  255. package/dist/node/adapters/whatsapp.js.map +1 -0
  256. package/dist/node/cli.js +884 -653
  257. package/dist/node/cli.js.map +1 -0
  258. package/dist/node/config.js +20 -18
  259. package/dist/node/config.js.map +1 -0
  260. package/dist/node/gateway-client.js +191 -181
  261. package/dist/node/gateway-client.js.map +1 -0
  262. package/dist/node/portal/clipboard.js +161 -130
  263. package/dist/node/portal/clipboard.js.map +1 -0
  264. package/dist/node/portal/discovery.js +51 -45
  265. package/dist/node/portal/discovery.js.map +1 -0
  266. package/dist/node/portal/forward.js +64 -58
  267. package/dist/node/portal/forward.js.map +1 -0
  268. package/dist/node/portal/index.js +246 -221
  269. package/dist/node/portal/index.js.map +1 -0
  270. package/dist/node/portal/multiplexer.js +192 -182
  271. package/dist/node/portal/multiplexer.js.map +1 -0
  272. package/dist/node/portal/permissions.js +102 -70
  273. package/dist/node/portal/permissions.js.map +1 -0
  274. package/dist/node/portal/protocol.js +153 -116
  275. package/dist/node/portal/protocol.js.map +1 -0
  276. package/dist/node/portal/screen.js +80 -69
  277. package/dist/node/portal/screen.js.map +1 -0
  278. package/dist/node/portal/session.js +124 -117
  279. package/dist/node/portal/session.js.map +1 -0
  280. package/dist/node/portal/shell.js +140 -113
  281. package/dist/node/portal/shell.js.map +1 -0
  282. package/dist/node/portal/stream.js +77 -75
  283. package/dist/node/portal/stream.js.map +1 -0
  284. package/dist/node/portal/transfer.js +190 -167
  285. package/dist/node/portal/transfer.js.map +1 -0
  286. package/dist/node/portal/ui.js +124 -99
  287. package/dist/node/portal/ui.js.map +1 -0
  288. package/dist/node/remote-desktop/compile-helper.js +50 -45
  289. package/dist/node/remote-desktop/compile-helper.js.map +1 -0
  290. package/dist/node/remote-desktop/index.js +215 -187
  291. package/dist/node/remote-desktop/index.js.map +1 -0
  292. package/dist/node/remote-desktop/protocol.js +45 -29
  293. package/dist/node/remote-desktop/protocol.js.map +1 -0
  294. package/dist/node/runtime.js +493 -410
  295. package/dist/node/runtime.js.map +1 -0
  296. package/dist/server/handlers/__test-utils__/test-db.js +39 -89
  297. package/dist/server/handlers/__test-utils__/test-db.js.map +1 -0
  298. package/dist/server/handlers/analytics.js +467 -261
  299. package/dist/server/handlers/analytics.js.map +1 -0
  300. package/dist/server/handlers/api-docs.d.ts +6 -0
  301. package/dist/server/handlers/api-docs.js +1613 -0
  302. package/dist/server/handlers/api-docs.js.map +1 -0
  303. package/dist/server/handlers/api-keys.js +295 -232
  304. package/dist/server/handlers/api-keys.js.map +1 -0
  305. package/dist/server/handlers/billing.js +330 -239
  306. package/dist/server/handlers/billing.js.map +1 -0
  307. package/dist/server/handlers/browser.js +468 -395
  308. package/dist/server/handlers/browser.js.map +1 -0
  309. package/dist/server/handlers/catalog.js +1377 -978
  310. package/dist/server/handlers/catalog.js.map +1 -0
  311. package/dist/server/handlers/clickhouse.js +157 -109
  312. package/dist/server/handlers/clickhouse.js.map +1 -0
  313. package/dist/server/handlers/comms.d.ts +0 -53
  314. package/dist/server/handlers/comms.js +1443 -970
  315. package/dist/server/handlers/comms.js.map +1 -0
  316. package/dist/server/handlers/creations.js +461 -394
  317. package/dist/server/handlers/creations.js.map +1 -0
  318. package/dist/server/handlers/crm.js +1082 -791
  319. package/dist/server/handlers/crm.js.map +1 -0
  320. package/dist/server/handlers/discovery.js +251 -232
  321. package/dist/server/handlers/discovery.js.map +1 -0
  322. package/dist/server/handlers/embeddings.js +241 -164
  323. package/dist/server/handlers/embeddings.js.map +1 -0
  324. package/dist/server/handlers/enrichment.js +887 -718
  325. package/dist/server/handlers/enrichment.js.map +1 -0
  326. package/dist/server/handlers/image-gen.js +467 -376
  327. package/dist/server/handlers/image-gen.js.map +1 -0
  328. package/dist/server/handlers/inventory.js +797 -424
  329. package/dist/server/handlers/inventory.js.map +1 -0
  330. package/dist/server/handlers/kali.js +272 -230
  331. package/dist/server/handlers/kali.js.map +1 -0
  332. package/dist/server/handlers/llm-providers.js +803 -580
  333. package/dist/server/handlers/llm-providers.js.map +1 -0
  334. package/dist/server/handlers/local-agent.js +133 -105
  335. package/dist/server/handlers/local-agent.js.map +1 -0
  336. package/dist/server/handlers/media.js +1179 -857
  337. package/dist/server/handlers/media.js.map +1 -0
  338. package/dist/server/handlers/meta-ads.js +2669 -2093
  339. package/dist/server/handlers/meta-ads.js.map +1 -0
  340. package/dist/server/handlers/nodes.js +1321 -913
  341. package/dist/server/handlers/nodes.js.map +1 -0
  342. package/dist/server/handlers/operations.js +183 -157
  343. package/dist/server/handlers/operations.js.map +1 -0
  344. package/dist/server/handlers/platform.js +346 -210
  345. package/dist/server/handlers/platform.js.map +1 -0
  346. package/dist/server/handlers/remove-bg.js +118 -86
  347. package/dist/server/handlers/remove-bg.js.map +1 -0
  348. package/dist/server/handlers/storefront.js +586 -446
  349. package/dist/server/handlers/storefront.js.map +1 -0
  350. package/dist/server/handlers/supply-chain.js +546 -326
  351. package/dist/server/handlers/supply-chain.js.map +1 -0
  352. package/dist/server/handlers/transcription.js +106 -97
  353. package/dist/server/handlers/transcription.js.map +1 -0
  354. package/dist/server/handlers/video-gen.js +593 -424
  355. package/dist/server/handlers/video-gen.js.map +1 -0
  356. package/dist/server/handlers/voice.js +1458 -1017
  357. package/dist/server/handlers/voice.js.map +1 -0
  358. package/dist/server/handlers/workflow-steps.js +2837 -2116
  359. package/dist/server/handlers/workflow-steps.js.map +1 -0
  360. package/dist/server/handlers/workflows.js +1630 -933
  361. package/dist/server/handlers/workflows.js.map +1 -0
  362. package/dist/server/index.js +3166 -2390
  363. package/dist/server/index.js.map +1 -0
  364. package/dist/server/lib/batch-client.js +471 -409
  365. package/dist/server/lib/batch-client.js.map +1 -0
  366. package/dist/server/lib/clickhouse-buffer.js +118 -104
  367. package/dist/server/lib/clickhouse-buffer.js.map +1 -0
  368. package/dist/server/lib/clickhouse-client.js +107 -107
  369. package/dist/server/lib/clickhouse-client.js.map +1 -0
  370. package/dist/server/lib/coa-renderer.js +1786 -356
  371. package/dist/server/lib/coa-renderer.js.map +1 -0
  372. package/dist/server/lib/code-worker-pool.js +227 -177
  373. package/dist/server/lib/code-worker-pool.js.map +1 -0
  374. package/dist/server/lib/code-worker.js +174 -164
  375. package/dist/server/lib/code-worker.js.map +1 -0
  376. package/dist/server/lib/compaction-service.d.ts +2 -12
  377. package/dist/server/lib/compaction-service.js +74 -184
  378. package/dist/server/lib/compaction-service.js.map +1 -0
  379. package/dist/server/lib/logger.js +36 -24
  380. package/dist/server/lib/logger.js.map +1 -0
  381. package/dist/server/lib/otel.js +101 -80
  382. package/dist/server/lib/otel.js.map +1 -0
  383. package/dist/server/lib/pdf-renderer.d.ts +1 -1
  384. package/dist/server/lib/pdf-renderer.js +954 -776
  385. package/dist/server/lib/pdf-renderer.js.map +1 -0
  386. package/dist/server/lib/prompt-sanitizer.js +188 -108
  387. package/dist/server/lib/prompt-sanitizer.js.map +1 -0
  388. package/dist/server/lib/provider-capabilities.js +136 -138
  389. package/dist/server/lib/provider-capabilities.js.map +1 -0
  390. package/dist/server/lib/provider-failover.js +190 -168
  391. package/dist/server/lib/provider-failover.js.map +1 -0
  392. package/dist/server/lib/rate-limiter.js +186 -117
  393. package/dist/server/lib/rate-limiter.js.map +1 -0
  394. package/dist/server/lib/react-pdf-layout.js +551 -382
  395. package/dist/server/lib/react-pdf-layout.js.map +1 -0
  396. package/dist/server/lib/server-agent-loop.d.ts +9 -0
  397. package/dist/server/lib/server-agent-loop.js +906 -624
  398. package/dist/server/lib/server-agent-loop.js.map +1 -0
  399. package/dist/server/lib/server-subagent.d.ts +2 -0
  400. package/dist/server/lib/server-subagent.js +260 -162
  401. package/dist/server/lib/server-subagent.js.map +1 -0
  402. package/dist/server/lib/session-checkpoint.js +105 -96
  403. package/dist/server/lib/session-checkpoint.js.map +1 -0
  404. package/dist/server/lib/ssrf-guard.js +193 -184
  405. package/dist/server/lib/ssrf-guard.js.map +1 -0
  406. package/dist/server/lib/supabase-client.js +94 -82
  407. package/dist/server/lib/supabase-client.js.map +1 -0
  408. package/dist/server/lib/template-resolver.js +154 -176
  409. package/dist/server/lib/template-resolver.js.map +1 -0
  410. package/dist/server/lib/utils.js +242 -133
  411. package/dist/server/lib/utils.js.map +1 -0
  412. package/dist/server/local-agent-gateway.d.ts +2 -2
  413. package/dist/server/local-agent-gateway.js +785 -627
  414. package/dist/server/local-agent-gateway.js.map +1 -0
  415. package/dist/server/providers/anthropic.js +254 -176
  416. package/dist/server/providers/anthropic.js.map +1 -0
  417. package/dist/server/providers/bedrock.js +221 -162
  418. package/dist/server/providers/bedrock.js.map +1 -0
  419. package/dist/server/providers/gemini.js +548 -418
  420. package/dist/server/providers/gemini.js.map +1 -0
  421. package/dist/server/providers/openai.js +571 -437
  422. package/dist/server/providers/openai.js.map +1 -0
  423. package/dist/server/providers/registry.js +23 -18
  424. package/dist/server/providers/registry.js.map +1 -0
  425. package/dist/server/providers/shared.js +123 -95
  426. package/dist/server/providers/shared.js.map +1 -0
  427. package/dist/server/providers/types.js +1 -11
  428. package/dist/server/providers/types.js.map +1 -0
  429. package/dist/server/proxy-handlers.js +209 -165
  430. package/dist/server/proxy-handlers.js.map +1 -0
  431. package/dist/server/tool-router.d.ts +13 -0
  432. package/dist/server/tool-router.js +960 -598
  433. package/dist/server/tool-router.js.map +1 -0
  434. package/dist/server/validation.js +248 -188
  435. package/dist/server/validation.js.map +1 -0
  436. package/dist/server/worker.js +202 -133
  437. package/dist/server/worker.js.map +1 -0
  438. package/dist/setup.d.ts +2 -2
  439. package/dist/setup.js +151 -147
  440. package/dist/setup.js.map +1 -0
  441. package/dist/shared/agent-core.d.ts +191 -24
  442. package/dist/shared/agent-core.js +971 -462
  443. package/dist/shared/agent-core.js.map +1 -0
  444. package/dist/shared/anthropic-types.js +1 -6
  445. package/dist/shared/anthropic-types.js.map +1 -0
  446. package/dist/shared/api-client.d.ts +17 -9
  447. package/dist/shared/api-client.js +419 -327
  448. package/dist/shared/api-client.js.map +1 -0
  449. package/dist/shared/compaction.d.ts +36 -0
  450. package/dist/shared/compaction.js +138 -0
  451. package/dist/shared/compaction.js.map +1 -0
  452. package/dist/shared/constants.js +67 -64
  453. package/dist/shared/constants.js.map +1 -0
  454. package/dist/shared/sse-parser.js +221 -219
  455. package/dist/shared/sse-parser.js.map +1 -0
  456. package/dist/shared/tool-dispatch.d.ts +4 -2
  457. package/dist/shared/tool-dispatch.js +226 -165
  458. package/dist/shared/tool-dispatch.js.map +1 -0
  459. package/dist/shared/types.js +1 -6
  460. package/dist/shared/types.js.map +1 -0
  461. package/dist/types/cli-highlight.d.js +2 -0
  462. package/dist/types/cli-highlight.d.js.map +1 -0
  463. package/dist/types/diff.d.js +2 -0
  464. package/dist/types/diff.d.js.map +1 -0
  465. package/dist/types/pdf-parse.d.js +2 -0
  466. package/dist/types/pdf-parse.d.js.map +1 -0
  467. package/dist/updater.d.ts +1 -1
  468. package/dist/updater.js +118 -92
  469. package/dist/updater.js.map +1 -0
  470. package/dist/webchat/widget.js +227 -380
  471. package/dist/webchat/widget.js.map +1 -0
  472. package/package.json +22 -10
  473. package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
  474. package/vendor/ink/build/ansi-tokenizer.js +316 -0
  475. package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
  476. package/vendor/ink/build/apply-styles.js +175 -0
  477. package/vendor/ink/build/build-layout.js +77 -0
  478. package/vendor/ink/build/calculate-wrapped-text.js +53 -0
  479. package/vendor/ink/build/colorize.d.ts +3 -0
  480. package/vendor/ink/build/colorize.js +48 -0
  481. package/vendor/ink/build/colorize.js.map +1 -0
  482. package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
  483. package/vendor/ink/build/components/AccessibilityContext.js +5 -0
  484. package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
  485. package/vendor/ink/build/components/App.d.ts +18 -0
  486. package/vendor/ink/build/components/App.js +351 -0
  487. package/vendor/ink/build/components/App.js.map +1 -0
  488. package/vendor/ink/build/components/AppContext.d.ts +15 -0
  489. package/vendor/ink/build/components/AppContext.js +11 -0
  490. package/vendor/ink/build/components/AppContext.js.map +1 -0
  491. package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
  492. package/vendor/ink/build/components/BackgroundContext.js +3 -0
  493. package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
  494. package/vendor/ink/build/components/Box.d.ts +117 -0
  495. package/vendor/ink/build/components/Box.js +34 -0
  496. package/vendor/ink/build/components/Box.js.map +1 -0
  497. package/vendor/ink/build/components/Color.js +62 -0
  498. package/vendor/ink/build/components/Cursor.d.ts +83 -0
  499. package/vendor/ink/build/components/Cursor.js +53 -0
  500. package/vendor/ink/build/components/Cursor.js.map +1 -0
  501. package/vendor/ink/build/components/CursorContext.d.ts +11 -0
  502. package/vendor/ink/build/components/CursorContext.js +8 -0
  503. package/vendor/ink/build/components/CursorContext.js.map +1 -0
  504. package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
  505. package/vendor/ink/build/components/ErrorBoundary.js +23 -0
  506. package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
  507. package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
  508. package/vendor/ink/build/components/ErrorOverview.js +84 -0
  509. package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
  510. package/vendor/ink/build/components/FocusContext.d.ts +16 -0
  511. package/vendor/ink/build/components/FocusContext.js +17 -0
  512. package/vendor/ink/build/components/FocusContext.js.map +1 -0
  513. package/vendor/ink/build/components/Newline.d.ts +13 -0
  514. package/vendor/ink/build/components/Newline.js +8 -0
  515. package/vendor/ink/build/components/Newline.js.map +1 -0
  516. package/vendor/ink/build/components/Spacer.d.ts +7 -0
  517. package/vendor/ink/build/components/Spacer.js +11 -0
  518. package/vendor/ink/build/components/Spacer.js.map +1 -0
  519. package/vendor/ink/build/components/Static.d.ts +24 -0
  520. package/vendor/ink/build/components/Static.js +28 -0
  521. package/vendor/ink/build/components/Static.js.map +1 -0
  522. package/vendor/ink/build/components/StderrContext.d.ts +15 -0
  523. package/vendor/ink/build/components/StderrContext.js +13 -0
  524. package/vendor/ink/build/components/StderrContext.js.map +1 -0
  525. package/vendor/ink/build/components/StdinContext.d.ts +22 -0
  526. package/vendor/ink/build/components/StdinContext.js +19 -0
  527. package/vendor/ink/build/components/StdinContext.js.map +1 -0
  528. package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
  529. package/vendor/ink/build/components/StdoutContext.js +13 -0
  530. package/vendor/ink/build/components/StdoutContext.js.map +1 -0
  531. package/vendor/ink/build/components/Text.d.ts +55 -0
  532. package/vendor/ink/build/components/Text.js +50 -0
  533. package/vendor/ink/build/components/Text.js.map +1 -0
  534. package/vendor/ink/build/components/Transform.d.ts +16 -0
  535. package/vendor/ink/build/components/Transform.js +15 -0
  536. package/vendor/ink/build/components/Transform.js.map +1 -0
  537. package/vendor/ink/build/cursor-helpers.d.ts +38 -0
  538. package/vendor/ink/build/cursor-helpers.js +56 -0
  539. package/vendor/ink/build/cursor-helpers.js.map +1 -0
  540. package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
  541. package/vendor/ink/build/devtools-window-polyfill.js +65 -0
  542. package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
  543. package/vendor/ink/build/devtools.d.ts +1 -0
  544. package/vendor/ink/build/devtools.js +11 -0
  545. package/vendor/ink/build/devtools.js.map +1 -0
  546. package/vendor/ink/build/dom.d.ts +56 -0
  547. package/vendor/ink/build/dom.js +124 -0
  548. package/vendor/ink/build/dom.js.map +1 -0
  549. package/vendor/ink/build/experimental/apply-style.js +140 -0
  550. package/vendor/ink/build/experimental/dom.js +123 -0
  551. package/vendor/ink/build/experimental/output.js +91 -0
  552. package/vendor/ink/build/experimental/reconciler.js +141 -0
  553. package/vendor/ink/build/experimental/renderer.js +81 -0
  554. package/vendor/ink/build/get-max-width.d.ts +3 -0
  555. package/vendor/ink/build/get-max-width.js +10 -0
  556. package/vendor/ink/build/get-max-width.js.map +1 -0
  557. package/vendor/ink/build/hooks/use-app.d.ts +5 -0
  558. package/vendor/ink/build/hooks/use-app.js +8 -0
  559. package/vendor/ink/build/hooks/use-app.js.map +1 -0
  560. package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
  561. package/vendor/ink/build/hooks/use-cursor.js +29 -0
  562. package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
  563. package/vendor/ink/build/hooks/use-focus-manager.d.ts +28 -0
  564. package/vendor/ink/build/hooks/use-focus-manager.js +17 -0
  565. package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
  566. package/vendor/ink/build/hooks/use-focus.d.ts +29 -0
  567. package/vendor/ink/build/hooks/use-focus.js +42 -0
  568. package/vendor/ink/build/hooks/use-focus.js.map +1 -0
  569. package/vendor/ink/build/hooks/use-input.d.ts +131 -0
  570. package/vendor/ink/build/hooks/use-input.js +124 -0
  571. package/vendor/ink/build/hooks/use-input.js.map +1 -0
  572. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +5 -0
  573. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +11 -0
  574. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  575. package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
  576. package/vendor/ink/build/hooks/use-stderr.js +8 -0
  577. package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
  578. package/vendor/ink/build/hooks/use-stdin.d.ts +5 -0
  579. package/vendor/ink/build/hooks/use-stdin.js +8 -0
  580. package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
  581. package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
  582. package/vendor/ink/build/hooks/use-stdout.js +8 -0
  583. package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
  584. package/vendor/ink/build/hooks/useInput.js +38 -0
  585. package/vendor/ink/build/index.d.ts +34 -0
  586. package/vendor/ink/build/index.js +20 -0
  587. package/vendor/ink/build/index.js.map +1 -0
  588. package/vendor/ink/build/ink.d.ts +90 -0
  589. package/vendor/ink/build/ink.js +654 -0
  590. package/vendor/ink/build/ink.js.map +1 -0
  591. package/vendor/ink/build/input-parser.d.ts +7 -0
  592. package/vendor/ink/build/input-parser.js +154 -0
  593. package/vendor/ink/build/input-parser.js.map +1 -0
  594. package/vendor/ink/build/instance.js +205 -0
  595. package/vendor/ink/build/instances.d.ts +3 -0
  596. package/vendor/ink/build/instances.js +8 -0
  597. package/vendor/ink/build/instances.js.map +1 -0
  598. package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
  599. package/vendor/ink/build/kitty-keyboard.js +32 -0
  600. package/vendor/ink/build/kitty-keyboard.js.map +1 -0
  601. package/vendor/ink/build/layout.d.ts +7 -0
  602. package/vendor/ink/build/layout.js +33 -0
  603. package/vendor/ink/build/layout.js.map +1 -0
  604. package/vendor/ink/build/log-update.d.ts +19 -0
  605. package/vendor/ink/build/log-update.js +243 -0
  606. package/vendor/ink/build/log-update.js.map +1 -0
  607. package/vendor/ink/build/measure-element.d.ts +16 -0
  608. package/vendor/ink/build/measure-element.js +9 -0
  609. package/vendor/ink/build/measure-element.js.map +1 -0
  610. package/vendor/ink/build/measure-text.d.ts +6 -0
  611. package/vendor/ink/build/measure-text.js +21 -0
  612. package/vendor/ink/build/measure-text.js.map +1 -0
  613. package/vendor/ink/build/options.d.ts +52 -0
  614. package/vendor/ink/build/options.js +2 -0
  615. package/vendor/ink/build/options.js.map +1 -0
  616. package/vendor/ink/build/output.d.ts +35 -0
  617. package/vendor/ink/build/output.js +183 -0
  618. package/vendor/ink/build/output.js.map +1 -0
  619. package/vendor/ink/build/parse-keypress.d.ts +22 -0
  620. package/vendor/ink/build/parse-keypress.js +493 -0
  621. package/vendor/ink/build/parse-keypress.js.map +1 -0
  622. package/vendor/ink/build/reconciler.d.ts +4 -0
  623. package/vendor/ink/build/reconciler.js +274 -0
  624. package/vendor/ink/build/reconciler.js.map +1 -0
  625. package/vendor/ink/build/render-background.d.ts +4 -0
  626. package/vendor/ink/build/render-background.js +25 -0
  627. package/vendor/ink/build/render-background.js.map +1 -0
  628. package/vendor/ink/build/render-border.d.ts +4 -0
  629. package/vendor/ink/build/render-border.js +73 -0
  630. package/vendor/ink/build/render-border.js.map +1 -0
  631. package/vendor/ink/build/render-node-to-output.d.ts +14 -0
  632. package/vendor/ink/build/render-node-to-output.js +147 -0
  633. package/vendor/ink/build/render-node-to-output.js.map +1 -0
  634. package/vendor/ink/build/render-to-string.d.ts +38 -0
  635. package/vendor/ink/build/render-to-string.js +115 -0
  636. package/vendor/ink/build/render-to-string.js.map +1 -0
  637. package/vendor/ink/build/render.d.ts +121 -0
  638. package/vendor/ink/build/render.js +55 -0
  639. package/vendor/ink/build/render.js.map +1 -0
  640. package/vendor/ink/build/renderer.d.ts +8 -0
  641. package/vendor/ink/build/renderer.js +55 -0
  642. package/vendor/ink/build/renderer.js.map +1 -0
  643. package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
  644. package/vendor/ink/build/sanitize-ansi.js +27 -0
  645. package/vendor/ink/build/sanitize-ansi.js.map +1 -0
  646. package/vendor/ink/build/screen-reader-update.d.ts +13 -0
  647. package/vendor/ink/build/screen-reader-update.js +38 -0
  648. package/vendor/ink/build/screen-reader-update.js.map +1 -0
  649. package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
  650. package/vendor/ink/build/squash-text-nodes.js +36 -0
  651. package/vendor/ink/build/squash-text-nodes.js.map +1 -0
  652. package/vendor/ink/build/styles.d.ts +240 -0
  653. package/vendor/ink/build/styles.js +232 -0
  654. package/vendor/ink/build/styles.js.map +1 -0
  655. package/vendor/ink/build/utils.d.ts +2 -0
  656. package/vendor/ink/build/utils.js +4 -0
  657. package/vendor/ink/build/utils.js.map +1 -0
  658. package/vendor/ink/build/wrap-text.d.ts +3 -0
  659. package/vendor/ink/build/wrap-text.js +31 -0
  660. package/vendor/ink/build/wrap-text.js.map +1 -0
  661. package/vendor/ink/build/write-synchronized.d.ts +4 -0
  662. package/vendor/ink/build/write-synchronized.js +7 -0
  663. package/vendor/ink/build/write-synchronized.js.map +1 -0
  664. package/vendor/ink/license +10 -0
  665. package/vendor/ink/node_modules/@types/node/LICENSE +21 -0
  666. package/vendor/ink/node_modules/@types/node/README.md +15 -0
  667. package/vendor/ink/node_modules/@types/node/assert/strict.d.ts +105 -0
  668. package/vendor/ink/node_modules/@types/node/assert.d.ts +955 -0
  669. package/vendor/ink/node_modules/@types/node/async_hooks.d.ts +623 -0
  670. package/vendor/ink/node_modules/@types/node/buffer.buffer.d.ts +466 -0
  671. package/vendor/ink/node_modules/@types/node/buffer.d.ts +1810 -0
  672. package/vendor/ink/node_modules/@types/node/child_process.d.ts +1428 -0
  673. package/vendor/ink/node_modules/@types/node/cluster.d.ts +486 -0
  674. package/vendor/ink/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
  675. package/vendor/ink/node_modules/@types/node/console.d.ts +151 -0
  676. package/vendor/ink/node_modules/@types/node/constants.d.ts +20 -0
  677. package/vendor/ink/node_modules/@types/node/crypto.d.ts +4065 -0
  678. package/vendor/ink/node_modules/@types/node/dgram.d.ts +564 -0
  679. package/vendor/ink/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  680. package/vendor/ink/node_modules/@types/node/dns/promises.d.ts +503 -0
  681. package/vendor/ink/node_modules/@types/node/dns.d.ts +922 -0
  682. package/vendor/ink/node_modules/@types/node/domain.d.ts +166 -0
  683. package/vendor/ink/node_modules/@types/node/events.d.ts +1054 -0
  684. package/vendor/ink/node_modules/@types/node/fs/promises.d.ts +1329 -0
  685. package/vendor/ink/node_modules/@types/node/fs.d.ts +4676 -0
  686. package/vendor/ink/node_modules/@types/node/globals.d.ts +150 -0
  687. package/vendor/ink/node_modules/@types/node/globals.typedarray.d.ts +101 -0
  688. package/vendor/ink/node_modules/@types/node/http.d.ts +2167 -0
  689. package/vendor/ink/node_modules/@types/node/http2.d.ts +2480 -0
  690. package/vendor/ink/node_modules/@types/node/https.d.ts +405 -0
  691. package/vendor/ink/node_modules/@types/node/index.d.ts +115 -0
  692. package/vendor/ink/node_modules/@types/node/inspector/promises.d.ts +41 -0
  693. package/vendor/ink/node_modules/@types/node/inspector.d.ts +224 -0
  694. package/vendor/ink/node_modules/@types/node/inspector.generated.d.ts +4226 -0
  695. package/vendor/ink/node_modules/@types/node/module.d.ts +819 -0
  696. package/vendor/ink/node_modules/@types/node/net.d.ts +933 -0
  697. package/vendor/ink/node_modules/@types/node/os.d.ts +507 -0
  698. package/vendor/ink/node_modules/@types/node/package.json +155 -0
  699. package/vendor/ink/node_modules/@types/node/path/posix.d.ts +8 -0
  700. package/vendor/ink/node_modules/@types/node/path/win32.d.ts +8 -0
  701. package/vendor/ink/node_modules/@types/node/path.d.ts +187 -0
  702. package/vendor/ink/node_modules/@types/node/perf_hooks.d.ts +643 -0
  703. package/vendor/ink/node_modules/@types/node/process.d.ts +2156 -0
  704. package/vendor/ink/node_modules/@types/node/punycode.d.ts +117 -0
  705. package/vendor/ink/node_modules/@types/node/querystring.d.ts +152 -0
  706. package/vendor/ink/node_modules/@types/node/quic.d.ts +910 -0
  707. package/vendor/ink/node_modules/@types/node/readline/promises.d.ts +161 -0
  708. package/vendor/ink/node_modules/@types/node/readline.d.ts +541 -0
  709. package/vendor/ink/node_modules/@types/node/repl.d.ts +415 -0
  710. package/vendor/ink/node_modules/@types/node/sea.d.ts +162 -0
  711. package/vendor/ink/node_modules/@types/node/sqlite.d.ts +955 -0
  712. package/vendor/ink/node_modules/@types/node/stream/consumers.d.ts +38 -0
  713. package/vendor/ink/node_modules/@types/node/stream/promises.d.ts +211 -0
  714. package/vendor/ink/node_modules/@types/node/stream/web.d.ts +296 -0
  715. package/vendor/ink/node_modules/@types/node/stream.d.ts +1760 -0
  716. package/vendor/ink/node_modules/@types/node/string_decoder.d.ts +67 -0
  717. package/vendor/ink/node_modules/@types/node/test/reporters.d.ts +96 -0
  718. package/vendor/ink/node_modules/@types/node/test.d.ts +2240 -0
  719. package/vendor/ink/node_modules/@types/node/timers/promises.d.ts +108 -0
  720. package/vendor/ink/node_modules/@types/node/timers.d.ts +159 -0
  721. package/vendor/ink/node_modules/@types/node/tls.d.ts +1198 -0
  722. package/vendor/ink/node_modules/@types/node/trace_events.d.ts +197 -0
  723. package/vendor/ink/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +462 -0
  724. package/vendor/ink/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
  725. package/vendor/ink/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
  726. package/vendor/ink/node_modules/@types/node/ts5.6/index.d.ts +117 -0
  727. package/vendor/ink/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
  728. package/vendor/ink/node_modules/@types/node/ts5.7/index.d.ts +117 -0
  729. package/vendor/ink/node_modules/@types/node/tty.d.ts +250 -0
  730. package/vendor/ink/node_modules/@types/node/url.d.ts +519 -0
  731. package/vendor/ink/node_modules/@types/node/util/types.d.ts +558 -0
  732. package/vendor/ink/node_modules/@types/node/util.d.ts +1662 -0
  733. package/vendor/ink/node_modules/@types/node/v8.d.ts +983 -0
  734. package/vendor/ink/node_modules/@types/node/vm.d.ts +1208 -0
  735. package/vendor/ink/node_modules/@types/node/wasi.d.ts +202 -0
  736. package/vendor/ink/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
  737. package/vendor/ink/node_modules/@types/node/web-globals/blob.d.ts +23 -0
  738. package/vendor/ink/node_modules/@types/node/web-globals/console.d.ts +9 -0
  739. package/vendor/ink/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
  740. package/vendor/ink/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  741. package/vendor/ink/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
  742. package/vendor/ink/node_modules/@types/node/web-globals/events.d.ts +106 -0
  743. package/vendor/ink/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
  744. package/vendor/ink/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
  745. package/vendor/ink/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
  746. package/vendor/ink/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
  747. package/vendor/ink/node_modules/@types/node/web-globals/performance.d.ts +45 -0
  748. package/vendor/ink/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  749. package/vendor/ink/node_modules/@types/node/web-globals/streams.d.ts +115 -0
  750. package/vendor/ink/node_modules/@types/node/web-globals/timers.d.ts +44 -0
  751. package/vendor/ink/node_modules/@types/node/web-globals/url.d.ts +24 -0
  752. package/vendor/ink/node_modules/@types/node/worker_threads.d.ts +717 -0
  753. package/vendor/ink/node_modules/@types/node/zlib.d.ts +618 -0
  754. package/vendor/ink/node_modules/node-pty/LICENSE +69 -0
  755. package/vendor/ink/node_modules/node-pty/README.md +164 -0
  756. package/vendor/ink/node_modules/node-pty/binding.gyp +150 -0
  757. package/vendor/ink/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  758. package/vendor/ink/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  759. package/vendor/ink/node_modules/node-pty/lib/index.js +52 -0
  760. package/vendor/ink/node_modules/node-pty/lib/interfaces.js +7 -0
  761. package/vendor/ink/node_modules/node-pty/lib/shared/conout.js +11 -0
  762. package/vendor/ink/node_modules/node-pty/lib/terminal.js +190 -0
  763. package/vendor/ink/node_modules/node-pty/lib/types.js +7 -0
  764. package/vendor/ink/node_modules/node-pty/lib/unixTerminal.js +349 -0
  765. package/vendor/ink/node_modules/node-pty/lib/utils.js +39 -0
  766. package/vendor/ink/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
  767. package/vendor/ink/node_modules/node-pty/lib/windowsPtyAgent.js +287 -0
  768. package/vendor/ink/node_modules/node-pty/lib/windowsTerminal.js +201 -0
  769. package/vendor/ink/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  770. package/vendor/ink/node_modules/node-pty/package.json +65 -0
  771. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  772. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  773. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  774. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  775. package/vendor/ink/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  776. package/vendor/ink/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  777. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  778. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  779. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  780. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
  781. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  782. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  783. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  784. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  785. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  786. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
  787. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  788. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  789. package/vendor/ink/node_modules/node-pty/scripts/post-install.js +76 -0
  790. package/vendor/ink/node_modules/node-pty/scripts/prebuild.js +34 -0
  791. package/vendor/ink/node_modules/node-pty/src/unix/pty.cc +875 -0
  792. package/vendor/ink/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
  793. package/vendor/ink/node_modules/node-pty/src/win/conpty.cc +582 -0
  794. package/vendor/ink/node_modules/node-pty/src/win/conpty.h +41 -0
  795. package/vendor/ink/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
  796. package/vendor/ink/node_modules/node-pty/src/win/path_util.cc +95 -0
  797. package/vendor/ink/node_modules/node-pty/src/win/path_util.h +26 -0
  798. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
  799. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
  800. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
  801. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
  802. package/vendor/ink/node_modules/node-pty/typings/node-pty.d.ts +215 -0
  803. package/vendor/ink/node_modules/undici-types/LICENSE +21 -0
  804. package/vendor/ink/node_modules/undici-types/README.md +6 -0
  805. package/vendor/ink/node_modules/undici-types/agent.d.ts +32 -0
  806. package/vendor/ink/node_modules/undici-types/api.d.ts +43 -0
  807. package/vendor/ink/node_modules/undici-types/balanced-pool.d.ts +30 -0
  808. package/vendor/ink/node_modules/undici-types/cache-interceptor.d.ts +173 -0
  809. package/vendor/ink/node_modules/undici-types/cache.d.ts +36 -0
  810. package/vendor/ink/node_modules/undici-types/client-stats.d.ts +15 -0
  811. package/vendor/ink/node_modules/undici-types/client.d.ts +108 -0
  812. package/vendor/ink/node_modules/undici-types/connector.d.ts +34 -0
  813. package/vendor/ink/node_modules/undici-types/content-type.d.ts +21 -0
  814. package/vendor/ink/node_modules/undici-types/cookies.d.ts +30 -0
  815. package/vendor/ink/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
  816. package/vendor/ink/node_modules/undici-types/dispatcher.d.ts +276 -0
  817. package/vendor/ink/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
  818. package/vendor/ink/node_modules/undici-types/errors.d.ts +161 -0
  819. package/vendor/ink/node_modules/undici-types/eventsource.d.ts +66 -0
  820. package/vendor/ink/node_modules/undici-types/fetch.d.ts +211 -0
  821. package/vendor/ink/node_modules/undici-types/formdata.d.ts +108 -0
  822. package/vendor/ink/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  823. package/vendor/ink/node_modules/undici-types/global-origin.d.ts +7 -0
  824. package/vendor/ink/node_modules/undici-types/h2c-client.d.ts +73 -0
  825. package/vendor/ink/node_modules/undici-types/handlers.d.ts +15 -0
  826. package/vendor/ink/node_modules/undici-types/header.d.ts +160 -0
  827. package/vendor/ink/node_modules/undici-types/index.d.ts +88 -0
  828. package/vendor/ink/node_modules/undici-types/interceptors.d.ts +73 -0
  829. package/vendor/ink/node_modules/undici-types/mock-agent.d.ts +68 -0
  830. package/vendor/ink/node_modules/undici-types/mock-call-history.d.ts +111 -0
  831. package/vendor/ink/node_modules/undici-types/mock-client.d.ts +27 -0
  832. package/vendor/ink/node_modules/undici-types/mock-errors.d.ts +12 -0
  833. package/vendor/ink/node_modules/undici-types/mock-interceptor.d.ts +94 -0
  834. package/vendor/ink/node_modules/undici-types/mock-pool.d.ts +27 -0
  835. package/vendor/ink/node_modules/undici-types/package.json +55 -0
  836. package/vendor/ink/node_modules/undici-types/patch.d.ts +29 -0
  837. package/vendor/ink/node_modules/undici-types/pool-stats.d.ts +19 -0
  838. package/vendor/ink/node_modules/undici-types/pool.d.ts +41 -0
  839. package/vendor/ink/node_modules/undici-types/proxy-agent.d.ts +29 -0
  840. package/vendor/ink/node_modules/undici-types/readable.d.ts +68 -0
  841. package/vendor/ink/node_modules/undici-types/retry-agent.d.ts +8 -0
  842. package/vendor/ink/node_modules/undici-types/retry-handler.d.ts +125 -0
  843. package/vendor/ink/node_modules/undici-types/round-robin-pool.d.ts +41 -0
  844. package/vendor/ink/node_modules/undici-types/snapshot-agent.d.ts +109 -0
  845. package/vendor/ink/node_modules/undici-types/util.d.ts +18 -0
  846. package/vendor/ink/node_modules/undici-types/utility.d.ts +7 -0
  847. package/vendor/ink/node_modules/undici-types/webidl.d.ts +341 -0
  848. package/vendor/ink/node_modules/undici-types/websocket.d.ts +186 -0
  849. package/vendor/ink/package.json +201 -0
  850. package/vendor/ink/readme.md +2636 -0
  851. package/bin/swag-agent.js +0 -9
  852. package/dist/server/lib/pg-rate-limiter.d.ts +0 -21
  853. package/dist/server/lib/pg-rate-limiter.js +0 -86
@@ -0,0 +1,1613 @@
1
+ // server/handlers/api-docs.ts — Static API documentation reference for agents
2
+
3
+ const GATEWAY_BASE_URL = "https://whale-gateway.fly.dev";
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Types
7
+ // ---------------------------------------------------------------------------
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Endpoint registry — every public REST API route
11
+ // ---------------------------------------------------------------------------
12
+
13
+ const SECTIONS = {
14
+ products: {
15
+ name: "Products",
16
+ description: "Product catalog CRUD, variations, and categories",
17
+ base: "/v1/stores/:storeId/products",
18
+ endpoints: [{
19
+ method: "GET",
20
+ path: "/v1/stores/:storeId/products",
21
+ scope: "read:products",
22
+ description: "List products with pagination and filters",
23
+ params: {
24
+ limit: "Number (1-100, default 25)",
25
+ starting_after: "Product ID cursor for forward pagination",
26
+ ending_before: "Product ID cursor for backward pagination",
27
+ category_id: "Filter by category UUID",
28
+ status: "Filter by status: published, draft, archived",
29
+ type: "Filter by type: simple, variable, grouped",
30
+ search: "Full-text search on name and SKU",
31
+ include: "Set to 'none' to skip loading variations (faster for large catalogs)"
32
+ },
33
+ response: '{ object: "list", data: Product[], has_more: boolean, url: string }'
34
+ }, {
35
+ method: "GET",
36
+ path: "/v1/stores/:storeId/products/:id",
37
+ scope: "read:products",
38
+ description: "Get a single product with variations and inventory",
39
+ response: "Product (includes pricing_data, field_values, inventory, variations)"
40
+ }, {
41
+ method: "POST",
42
+ path: "/v1/stores/:storeId/products",
43
+ scope: "write:products",
44
+ description: "Create a new product",
45
+ body: {
46
+ name: "Required. Product name",
47
+ sku: "SKU code",
48
+ category_id: "Category UUID",
49
+ status: "published | draft (default: draft)",
50
+ type: "simple | variable | grouped (default: simple)",
51
+ description: "Full description",
52
+ short_description: "Summary text",
53
+ cost_price: "Cost per unit",
54
+ pricing_data: "Pricing tiers JSON",
55
+ field_values: "Custom fields JSON (must match category field schema)",
56
+ featured_image: "Image URL",
57
+ image_gallery: "Array of image URLs",
58
+ manage_stock: "Boolean — track inventory",
59
+ stock_quantity: "Initial stock (if manage_stock)"
60
+ },
61
+ response: "Product"
62
+ }, {
63
+ method: "PATCH",
64
+ path: "/v1/stores/:storeId/products/:id",
65
+ scope: "write:products",
66
+ description: "Update an existing product (partial update)",
67
+ body: {
68
+ "...": "Any product fields to update"
69
+ },
70
+ response: "Product"
71
+ }, {
72
+ method: "DELETE",
73
+ path: "/v1/stores/:storeId/products/:id",
74
+ scope: "write:products",
75
+ description: "Archive a product (soft delete)",
76
+ response: "{ deleted: true }"
77
+ }, {
78
+ method: "GET",
79
+ path: "/v1/stores/:storeId/products/:id/variations",
80
+ scope: "read:products",
81
+ description: "List variations for a product",
82
+ response: '{ object: "list", data: Variation[] }'
83
+ }, {
84
+ method: "POST",
85
+ path: "/v1/stores/:storeId/products/:id/variations",
86
+ scope: "write:products",
87
+ description: "Create a product variation",
88
+ body: {
89
+ name: "Variation name (e.g. 'Small', '1oz')",
90
+ sku: "Variation SKU",
91
+ pricing_data: "Variation-specific pricing",
92
+ field_values: "Variation-specific field values",
93
+ stock_quantity: "Initial stock"
94
+ },
95
+ response: "Variation"
96
+ }, {
97
+ method: "PATCH",
98
+ path: "/v1/stores/:storeId/products/:id/variations/:variationId",
99
+ scope: "write:products",
100
+ description: "Update a variation",
101
+ body: {
102
+ "...": "Any variation fields"
103
+ },
104
+ response: "Variation"
105
+ }, {
106
+ method: "DELETE",
107
+ path: "/v1/stores/:storeId/products/:id/variations/:variationId",
108
+ scope: "write:products",
109
+ description: "Delete a variation",
110
+ response: "{ deleted: true }"
111
+ }]
112
+ },
113
+ orders: {
114
+ name: "Orders",
115
+ description: "Order management — list, view, update status, void, and refund",
116
+ base: "/v1/stores/:storeId/orders",
117
+ endpoints: [{
118
+ method: "GET",
119
+ path: "/v1/stores/:storeId/orders",
120
+ scope: "read:orders",
121
+ description: "List orders with pagination",
122
+ params: {
123
+ limit: "Number (1-100, default 25)",
124
+ starting_after: "Order ID cursor",
125
+ ending_before: "Order ID cursor",
126
+ status: "Filter: pending, confirmed, processing, shipped, delivered, cancelled",
127
+ customer_id: "Filter by customer UUID",
128
+ location_id: "Filter by location UUID",
129
+ created_after: "ISO datetime — filter orders created on or after this date",
130
+ created_before: "ISO datetime — filter orders created on or before this date"
131
+ },
132
+ response: '{ object: "list", data: Order[], has_more: boolean }'
133
+ }, {
134
+ method: "GET",
135
+ path: "/v1/stores/:storeId/orders/:id",
136
+ scope: "read:orders",
137
+ description: "Get a single order with line items",
138
+ response: "Order (includes line_items[], customer, payment_details)"
139
+ }, {
140
+ method: "PATCH",
141
+ path: "/v1/stores/:storeId/orders/:id",
142
+ scope: "write:orders",
143
+ description: "Update order status or fields",
144
+ body: {
145
+ status: "Order status: pending, confirmed, processing, preparing, packed, ready, shipped, in_transit, delivered, completed, cancelled, refunded",
146
+ fulfillment_status: "unfulfilled, partial, fulfilled, cancelled, shipped, in_transit, delivered, ready_for_pickup, ready",
147
+ tracking_number: "Shipping tracking number",
148
+ tracking_url: "Tracking URL",
149
+ shipping_service: "Carrier name",
150
+ shipping_method: "Shipping method",
151
+ staff_notes: "Internal notes"
152
+ },
153
+ response: "Order"
154
+ }, {
155
+ method: "POST",
156
+ path: "/v1/stores/:storeId/orders/:id/void",
157
+ scope: "write:orders",
158
+ description: "Void an unsettled order",
159
+ response: "Order (status: voided)",
160
+ notes: "Only works on orders where payment has not yet settled"
161
+ }, {
162
+ method: "POST",
163
+ path: "/v1/stores/:storeId/orders/:id/refund",
164
+ scope: "write:orders",
165
+ description: "Refund a settled order",
166
+ body: {
167
+ amount: "Partial refund amount (optional — omit for full refund)",
168
+ reason: "Refund reason"
169
+ },
170
+ response: "Order (includes refund details)"
171
+ }]
172
+ },
173
+ cart: {
174
+ name: "Cart",
175
+ description: "Shopping cart — create, add/update/remove items, view",
176
+ base: "/v1/stores/:storeId/cart",
177
+ endpoints: [{
178
+ method: "POST",
179
+ path: "/v1/stores/:storeId/cart",
180
+ scope: "write:cart",
181
+ description: "Create a new shopping cart",
182
+ body: {
183
+ customer_id: "Optional customer UUID",
184
+ location_id: "Optional location UUID (auto-resolves default)"
185
+ },
186
+ response: "Cart { id, items: [], totals }"
187
+ }, {
188
+ method: "GET",
189
+ path: "/v1/stores/:storeId/cart/:cartId",
190
+ scope: "read:cart",
191
+ description: "Get cart with all items and computed totals",
192
+ response: "Cart { id, items: CartItem[], totals: { subtotal, tax, total } }"
193
+ }, {
194
+ method: "POST",
195
+ path: "/v1/stores/:storeId/cart/:cartId/items",
196
+ scope: "write:cart",
197
+ description: "Add an item to the cart",
198
+ body: {
199
+ product_id: "Required. Product UUID",
200
+ quantity: "Required. Number of units",
201
+ variation_id: "Variation UUID (for variable products)",
202
+ tier: "Pricing tier name (e.g. 'retail', 'wholesale')",
203
+ unit_price: "Override price (optional — auto-resolved from pricing_data)"
204
+ },
205
+ response: 'CartItem { object: "cart_item", id, product_id, product_name, quantity, unit_price, line_total }'
206
+ }, {
207
+ method: "PATCH",
208
+ path: "/v1/stores/:storeId/cart/:cartId/items/:itemId",
209
+ scope: "write:cart",
210
+ description: "Update cart item quantity",
211
+ body: {
212
+ quantity: "New quantity (must be >= 1)"
213
+ },
214
+ response: 'CartItem { object: "cart_item", id, quantity, unit_price, line_total }'
215
+ }, {
216
+ method: "DELETE",
217
+ path: "/v1/stores/:storeId/cart/:cartId/items/:itemId",
218
+ scope: "write:cart",
219
+ description: "Remove an item from the cart",
220
+ response: '{ object: "cart_item", id, deleted: true }'
221
+ }]
222
+ },
223
+ checkout: {
224
+ name: "Checkout",
225
+ description: "E-commerce checkout and POS payment intents",
226
+ base: "/v1/stores/:storeId/checkout",
227
+ endpoints: [{
228
+ method: "POST",
229
+ path: "/v1/stores/:storeId/checkout",
230
+ scope: "write:checkout",
231
+ description: "Convert a cart into an order (e-commerce checkout)",
232
+ body: {
233
+ cart_id: "Required. Cart UUID",
234
+ customer_email: "Customer email (auto-creates customer if not found)",
235
+ customer_name: "Customer name",
236
+ customer_id: "Existing customer UUID",
237
+ payment_method: "Payment method identifier",
238
+ opaque_data: "Authorize.Net card token { dataDescriptor, dataValue }",
239
+ bill_to: "Billing address { firstName, lastName, address, city, state, zip, country }",
240
+ ship_to: "Shipping address (same shape as bill_to)",
241
+ loyalty_code: "Loyalty/discount code",
242
+ loyalty_points_redeemed: "Points to redeem (integer >= 0)",
243
+ loyalty_discount_amount: "Discount amount from loyalty (number >= 0)"
244
+ },
245
+ response: 'Order { object: "order", id, order_number, status: "completed" }',
246
+ notes: "Cart is consumed — cannot be reused after successful checkout. Supports idempotency (returns existing order on replay)."
247
+ }, {
248
+ method: "POST",
249
+ path: "/v1/stores/:storeId/checkout/intents",
250
+ scope: "write:checkout",
251
+ description: "Create a payment intent (POS terminal flow)",
252
+ body: {
253
+ cartItems: "Required. Array of cart items",
254
+ paymentMethod: "Payment method (card, cash, etc.)",
255
+ locationId: "Location UUID",
256
+ registerId: "POS register ID",
257
+ sessionId: "POS session ID",
258
+ customerId: "Customer UUID",
259
+ customerName: "Customer name",
260
+ userId: "Staff user UUID",
261
+ tipAmount: "Tip amount",
262
+ cashTendered: "Cash amount given (for cash payments)",
263
+ changeGiven: "Change returned",
264
+ idempotencyKey: "Idempotency key for safe retries"
265
+ },
266
+ response: "PaymentIntent { id, status: 'created', amount }"
267
+ }, {
268
+ method: "GET",
269
+ path: "/v1/stores/:storeId/checkout/intents/:id",
270
+ scope: "read:checkout",
271
+ description: "Get payment intent status",
272
+ response: "PaymentIntent { id, status, amount, created_at }"
273
+ }, {
274
+ method: "POST",
275
+ path: "/v1/stores/:storeId/checkout/intents/:id/capture",
276
+ scope: "write:checkout",
277
+ description: "Capture an authorized payment",
278
+ response: "PaymentIntent { status: 'captured' }"
279
+ }, {
280
+ method: "POST",
281
+ path: "/v1/stores/:storeId/checkout/intents/:id/cancel",
282
+ scope: "write:checkout",
283
+ description: "Cancel a payment intent",
284
+ response: "PaymentIntent { status: 'cancelled' }"
285
+ }, {
286
+ method: "POST",
287
+ path: "/v1/stores/:storeId/checkout/intents/:id/charge",
288
+ scope: "write:checkout",
289
+ description: "Charge via Dejavoo POS terminal",
290
+ body: {
291
+ terminal_id: "Dejavoo terminal ID"
292
+ },
293
+ response: "PaymentIntent (with terminal response)",
294
+ notes: "POS-specific — sends charge request to physical terminal"
295
+ }, {
296
+ method: "POST",
297
+ path: "/v1/stores/:storeId/checkout/intents/:id/abort",
298
+ scope: "write:checkout",
299
+ description: "Abort an in-progress terminal charge",
300
+ response: "PaymentIntent { status: 'aborted' }"
301
+ }]
302
+ },
303
+ customers: {
304
+ name: "Customers",
305
+ description: "Customer CRM — CRUD and search",
306
+ base: "/v1/stores/:storeId/customers",
307
+ endpoints: [{
308
+ method: "GET",
309
+ path: "/v1/stores/:storeId/customers",
310
+ scope: "read:customers",
311
+ description: "List customers with pagination and search",
312
+ params: {
313
+ limit: "Number (1-100, default 25)",
314
+ starting_after: "Customer ID cursor",
315
+ search: "Search by name, email, or phone"
316
+ },
317
+ response: '{ object: "list", data: Customer[], has_more: boolean }'
318
+ }, {
319
+ method: "GET",
320
+ path: "/v1/stores/:storeId/customers/:id",
321
+ scope: "read:customers",
322
+ description: "Get a single customer with full profile",
323
+ response: "Customer (includes loyalty_points, total_spent, total_orders)"
324
+ }, {
325
+ method: "POST",
326
+ path: "/v1/stores/:storeId/customers",
327
+ scope: "write:customers",
328
+ description: "Create a new customer",
329
+ body: {
330
+ first_name: "Required",
331
+ last_name: "Required",
332
+ email: "Email address",
333
+ phone: "Phone number",
334
+ date_of_birth: "YYYY-MM-DD"
335
+ },
336
+ response: "Customer"
337
+ }, {
338
+ method: "PATCH",
339
+ path: "/v1/stores/:storeId/customers/:id",
340
+ scope: "write:customers",
341
+ description: "Update a customer",
342
+ body: {
343
+ "...": "Any customer fields"
344
+ },
345
+ response: "Customer"
346
+ }]
347
+ },
348
+ inventory: {
349
+ name: "Inventory",
350
+ description: "Inventory levels, summaries, adjustments, and transfers",
351
+ base: "/v1/stores/:storeId/inventory",
352
+ endpoints: [{
353
+ method: "GET",
354
+ path: "/v1/stores/:storeId/inventory",
355
+ scope: "read:inventory",
356
+ description: "List inventory levels across locations",
357
+ params: {
358
+ limit: "Number (1-100, default 25)",
359
+ starting_after: "Cursor",
360
+ location_id: "Filter by location UUID",
361
+ product_id: "Filter by product UUID",
362
+ low_stock: "Set to 'true' to filter to low_stock or out_of_stock items only"
363
+ },
364
+ response: '{ object: "list", data: InventoryLevel[] }'
365
+ }, {
366
+ method: "GET",
367
+ path: "/v1/stores/:storeId/inventory/summary",
368
+ scope: "read:inventory",
369
+ description: "Inventory summary grouped by location",
370
+ response: "{ locations: [{ id, name, total_products, total_units, total_value }] }"
371
+ }, {
372
+ method: "POST",
373
+ path: "/v1/stores/:storeId/inventory/adjust",
374
+ scope: "write:inventory",
375
+ description: "Adjust inventory quantity for a product at a location",
376
+ body: {
377
+ product_id: "Required. Product UUID",
378
+ location_id: "Required. Location UUID",
379
+ quantity_change: "Required. Number (+/-) to adjust by",
380
+ reason: "Reason for adjustment (default: 'api_adjustment')"
381
+ },
382
+ response: '{ object: "inventory_adjustment", product_id, location_id, quantity_change, new_quantity, reason }'
383
+ }, {
384
+ method: "POST",
385
+ path: "/v1/stores/:storeId/inventory/transfer",
386
+ scope: "write:inventory",
387
+ description: "Transfer inventory between locations",
388
+ body: {
389
+ product_id: "Required. Product UUID",
390
+ from_location_id: "Required. Source location UUID",
391
+ to_location_id: "Required. Destination location UUID",
392
+ quantity: "Required. Number of units to transfer"
393
+ },
394
+ response: "{ from: InventoryLevel, to: InventoryLevel }"
395
+ }]
396
+ },
397
+ locations: {
398
+ name: "Locations",
399
+ description: "Store locations — list and view",
400
+ base: "/v1/stores/:storeId/locations",
401
+ endpoints: [{
402
+ method: "GET",
403
+ path: "/v1/stores/:storeId/locations",
404
+ scope: "read:locations",
405
+ description: "List all store locations",
406
+ response: '{ object: "list", data: Location[] }'
407
+ }, {
408
+ method: "GET",
409
+ path: "/v1/stores/:storeId/locations/:id",
410
+ scope: "read:locations",
411
+ description: "Get a single location",
412
+ response: "Location { id, name, address, city, state, zip, type, is_active }"
413
+ }]
414
+ },
415
+ analytics: {
416
+ name: "Analytics",
417
+ description: "Sales, inventory, traffic, customer, and product analytics",
418
+ base: "/v1/stores/:storeId/analytics",
419
+ endpoints: [{
420
+ method: "GET",
421
+ path: "/v1/stores/:storeId/analytics/sales",
422
+ scope: "read:analytics",
423
+ description: "Sales analytics summary",
424
+ params: {
425
+ start_date: "YYYY-MM-DD (default: 30 days ago)",
426
+ end_date: "YYYY-MM-DD (default: today)",
427
+ location_id: "Filter by location UUID"
428
+ },
429
+ response: '{ object: "analytics.sales", period: { start_date, end_date }, total_orders, completed_orders, total_revenue, total_tax, total_discount, average_order_value, gross_sales, net_sales, total_profit, profit_margin, unique_customers }'
430
+ }, {
431
+ method: "GET",
432
+ path: "/v1/stores/:storeId/analytics/sales/daily",
433
+ scope: "read:analytics",
434
+ description: "Daily sales breakdown",
435
+ params: {
436
+ start_date: "YYYY-MM-DD (default: 30 days ago)",
437
+ end_date: "YYYY-MM-DD (default: today)",
438
+ location_id: "Filter by location UUID"
439
+ },
440
+ response: "{ days: [{ date, revenue, orders, average_order_value }] }"
441
+ }, {
442
+ method: "GET",
443
+ path: "/v1/stores/:storeId/analytics/sales/weekly",
444
+ scope: "read:analytics",
445
+ description: "Weekly sales breakdown",
446
+ params: {
447
+ start_date: "YYYY-MM-DD (default: 30 days ago)",
448
+ end_date: "YYYY-MM-DD (default: today)",
449
+ location_id: "Filter by location UUID"
450
+ },
451
+ response: "{ weeks: [{ week_start, revenue, orders }] }"
452
+ }, {
453
+ method: "GET",
454
+ path: "/v1/stores/:storeId/analytics/inventory",
455
+ scope: "read:analytics",
456
+ description: "Inventory analytics — stock levels and velocity",
457
+ response: "{ total_value, low_stock[], out_of_stock[], velocity[] }"
458
+ }, {
459
+ method: "GET",
460
+ path: "/v1/stores/:storeId/analytics/traffic",
461
+ scope: "read:analytics",
462
+ description: "Storefront traffic analytics",
463
+ response: "{ sessions, page_views, bounce_rate, avg_session_duration }"
464
+ }, {
465
+ method: "GET",
466
+ path: "/v1/stores/:storeId/analytics/funnel",
467
+ scope: "read:analytics",
468
+ description: "Conversion funnel analytics",
469
+ response: "{ steps: [{ name, count, conversion_rate }] }"
470
+ }, {
471
+ method: "GET",
472
+ path: "/v1/stores/:storeId/analytics/customers",
473
+ scope: "read:analytics",
474
+ description: "Customer analytics — segments, retention, lifetime value",
475
+ response: "{ total_customers, new_customers, returning, avg_ltv, segments[] }"
476
+ }, {
477
+ method: "GET",
478
+ path: "/v1/stores/:storeId/analytics/products",
479
+ scope: "read:analytics",
480
+ description: "Per-product performance analytics",
481
+ params: {
482
+ limit: "Number of products",
483
+ category_id: "Filter by category"
484
+ },
485
+ response: "{ products: [{ id, name, revenue, units_sold, avg_price }] }"
486
+ }]
487
+ },
488
+ storefront: {
489
+ name: "Storefront",
490
+ description: "Storefront sessions, event tracking, and customer OTP authentication",
491
+ base: "/v1/stores/:storeId/storefront",
492
+ endpoints: [{
493
+ method: "GET",
494
+ path: "/v1/stores/:storeId/storefront/sessions",
495
+ scope: "read:storefront",
496
+ description: "List storefront sessions",
497
+ response: '{ object: "list", data: Session[] }'
498
+ }, {
499
+ method: "GET",
500
+ path: "/v1/stores/:storeId/storefront/sessions/:id",
501
+ scope: "read:storefront",
502
+ description: "Get a single session",
503
+ response: "Session { id, customer_id, events[], created_at }"
504
+ }, {
505
+ method: "POST",
506
+ path: "/v1/stores/:storeId/storefront/sessions",
507
+ scope: "write:storefront",
508
+ description: "Create a storefront session",
509
+ body: {
510
+ customer_id: "Optional customer UUID",
511
+ metadata: "Optional session metadata"
512
+ },
513
+ response: "Session"
514
+ }, {
515
+ method: "PATCH",
516
+ path: "/v1/stores/:storeId/storefront/sessions/:id",
517
+ scope: "write:storefront",
518
+ description: "Update a session",
519
+ body: {
520
+ metadata: "Updated metadata"
521
+ },
522
+ response: "Session"
523
+ }, {
524
+ method: "POST",
525
+ path: "/v1/stores/:storeId/storefront/events",
526
+ scope: "write:storefront",
527
+ description: "Track a storefront event",
528
+ body: {
529
+ session_id: "Session UUID",
530
+ event_type: "Event name (e.g. page_view, add_to_cart, purchase)",
531
+ event_data: "Event payload JSON"
532
+ },
533
+ response: "{ tracked: true }"
534
+ }, {
535
+ method: "POST",
536
+ path: "/v1/stores/:storeId/storefront/auth/send-code",
537
+ scope: "write:storefront",
538
+ description: "Send passwordless OTP to a customer",
539
+ body: {
540
+ email: "Customer email OR",
541
+ phone: "Customer phone"
542
+ },
543
+ response: "{ sent: true }",
544
+ notes: "Rate-limited to prevent abuse. Code expires in 10 minutes."
545
+ }, {
546
+ method: "POST",
547
+ path: "/v1/stores/:storeId/storefront/auth/verify-code",
548
+ scope: "write:storefront",
549
+ description: "Verify OTP code and authenticate customer",
550
+ body: {
551
+ email: "Customer email OR phone",
552
+ code: "6-digit OTP code"
553
+ },
554
+ response: "{ customer_id, session_token, expires_at }"
555
+ }]
556
+ },
557
+ coa: {
558
+ name: "COA (Certificates of Analysis)",
559
+ description: "Lab test results — list, verify, view, and embed",
560
+ base: "/v1/stores/:storeId/coa",
561
+ endpoints: [{
562
+ method: "GET",
563
+ path: "/v1/stores/:storeId/coa",
564
+ scope: "read:coa",
565
+ description: "List COAs (scoped to client)",
566
+ params: {
567
+ limit: "Number (1-100)",
568
+ starting_after: "Cursor"
569
+ },
570
+ response: '{ object: "list", data: COA[] }'
571
+ }, {
572
+ method: "GET",
573
+ path: "/v1/stores/:storeId/coa/verify",
574
+ scope: "read:coa",
575
+ description: "Verify a COA by sample ID",
576
+ params: {
577
+ sample_id: "Lab sample identifier"
578
+ },
579
+ response: "COA (with verification status)",
580
+ notes: "Public-facing verification — can be linked from product pages"
581
+ }, {
582
+ method: "GET",
583
+ path: "/v1/stores/:storeId/coa/:id",
584
+ scope: "read:coa",
585
+ description: "Get a single COA with full lab data",
586
+ response: "COA { id, product_name, batch_number, sample_id, cannabinoids, terpenes, ... }"
587
+ }, {
588
+ method: "GET",
589
+ path: "/v1/stores/:storeId/coa/:id/embed",
590
+ scope: "read:coa",
591
+ description: "Get embeddable COA data for iframes or widgets",
592
+ response: "{ html: string, data: COA }",
593
+ notes: "Use for embedding lab results on product detail pages"
594
+ }]
595
+ },
596
+ portal: {
597
+ name: "Customer Portal",
598
+ description: "B2B portal — authentication, profiles, and documents",
599
+ base: "/v1/stores/:storeId/portal",
600
+ endpoints: [{
601
+ method: "POST",
602
+ path: "/v1/stores/:storeId/portal/auth/send-code",
603
+ scope: "write:portal",
604
+ description: "Send portal login OTP",
605
+ body: {
606
+ email: "Customer email"
607
+ },
608
+ response: "{ sent: true }"
609
+ }, {
610
+ method: "POST",
611
+ path: "/v1/stores/:storeId/portal/auth/verify",
612
+ scope: "write:portal",
613
+ description: "Verify OTP and get portal session",
614
+ body: {
615
+ email: "Customer email",
616
+ code: "OTP code"
617
+ },
618
+ response: "{ customer_id, token, expires_at }"
619
+ }, {
620
+ method: "POST",
621
+ path: "/v1/stores/:storeId/portal/auth/refresh",
622
+ scope: "write:portal",
623
+ description: "Refresh portal session token",
624
+ body: {
625
+ token: "Current session token"
626
+ },
627
+ response: "{ token, expires_at }"
628
+ }, {
629
+ method: "GET",
630
+ path: "/v1/stores/:storeId/portal/stores",
631
+ scope: "read:portal",
632
+ description: "Get stores the customer belongs to",
633
+ response: "{ stores: Store[] }"
634
+ }, {
635
+ method: "GET",
636
+ path: "/v1/stores/:storeId/portal/profiles",
637
+ scope: "read:portal",
638
+ description: "List customer profiles",
639
+ response: "{ profiles: Profile[] }"
640
+ }, {
641
+ method: "GET",
642
+ path: "/v1/stores/:storeId/portal/documents",
643
+ scope: "read:portal",
644
+ description: "List customer documents",
645
+ response: '{ object: "list", data: Document[] }'
646
+ }, {
647
+ method: "GET",
648
+ path: "/v1/stores/:storeId/portal/documents/:id",
649
+ scope: "read:portal",
650
+ description: "Get a single document",
651
+ response: "Document { id, name, type, url, created_at }"
652
+ }, {
653
+ method: "GET",
654
+ path: "/v1/stores/:storeId/portal/api-key",
655
+ scope: "read:portal",
656
+ description: "Get customer's API key for portal access",
657
+ response: "{ api_key, scopes[], expires_at }"
658
+ }]
659
+ },
660
+ webhooks: {
661
+ name: "Webhooks",
662
+ description: "Inbound webhook ingestion — receives events from external services (HMAC-authenticated, no API key required)",
663
+ base: "/v1/webhooks",
664
+ endpoints: [{
665
+ method: "POST",
666
+ path: "/v1/webhooks/:slug",
667
+ scope: "(none — HMAC signature)",
668
+ description: "Receive an inbound webhook event",
669
+ body: {
670
+ timestamp: "Unix timestamp (optional — replay protection, rejects if > 5 min old)",
671
+ event: "Event type identifier (or 'type' field)",
672
+ "...": "All other fields pass through to webhook_events table"
673
+ },
674
+ response: '{ object: "webhook_event", received: true, event_type: string }',
675
+ notes: "Authenticated via HMAC sha256 signature from the webhook endpoint's signing_secret. No API key required."
676
+ }]
677
+ },
678
+ agent: {
679
+ name: "Agent",
680
+ description: "AI agent chat — SSE streaming proxy to the internal whale-agent service",
681
+ base: "/v1/stores/:storeId/agent",
682
+ endpoints: [{
683
+ method: "POST",
684
+ path: "/v1/stores/:storeId/agent/chat",
685
+ scope: "write:agent",
686
+ description: "Stream an AI agent response via Server-Sent Events",
687
+ body: {
688
+ message: "User message (string — either this or messages required)",
689
+ messages: "Array of { role: 'user'|'assistant'|'system', content: string }",
690
+ conversation_id: "Conversation ID for multi-turn context",
691
+ context: "Additional context object passed to the agent"
692
+ },
693
+ response: "SSE stream (text/event-stream) — streamed tokens from the agent",
694
+ notes: "Proxies to internal whale-agent service. 120s timeout (504 on timeout, 502 on connection failure)."
695
+ }]
696
+ },
697
+ telemetry: {
698
+ name: "Telemetry",
699
+ description: "SDK telemetry ingestion — errors, analytics events, Web Vitals, and AI/LLM call tracking",
700
+ base: "/v1/stores/:storeId/telemetry",
701
+ endpoints: [{
702
+ method: "POST",
703
+ path: "/v1/stores/:storeId/telemetry/ingest",
704
+ scope: "write:telemetry",
705
+ description: "Ingest a batch of telemetry data (errors, events, vitals, AI calls)",
706
+ body: {
707
+ session: "Required. { session_id, visitor_id, started_at, page_url, referrer, user_agent, screen_width, screen_height, device, language, utm_* }",
708
+ user: "Optional. { user_id, email?, name?, traits? }",
709
+ errors: "Array (max 50). Each: { error_type, error_message, fingerprint, occurred_at, severity?, stack_trace?, breadcrumbs? }",
710
+ events: "Array (max 100). Each: { event_name, properties, timestamp }",
711
+ vitals: "Array (max 20). Each: { name: CLS|FID|LCP|INP|TTFB|FCP, value, rating, timestamp }",
712
+ ai_calls: "Array (max 50). Each: { model, provider?, prompt_tokens?, completion_tokens?, cost?, duration_ms?, status?, agent_id? }"
713
+ },
714
+ response: '{ object: "telemetry_batch", accepted: { errors, events, vitals, ai_calls }, session_id }',
715
+ notes: "Used by @neowhale/telemetry SDK. Errors go to ClickHouse, events to Supabase, vitals and AI calls to ClickHouse."
716
+ }, {
717
+ method: "POST",
718
+ path: "/v1/native/telemetry",
719
+ scope: "(JWT-authenticated)",
720
+ description: "Ingest telemetry from native (macOS/iOS) apps",
721
+ body: {
722
+ "...": "Same batch format as /telemetry/ingest"
723
+ },
724
+ response: '{ object: "telemetry_batch", accepted: { ... } }',
725
+ notes: "Authenticated via JWT token (not API key). Bypasses standard API key middleware."
726
+ }]
727
+ },
728
+ media: {
729
+ name: "Media",
730
+ description: "Image and video proxy with on-the-fly transformations (HMAC-signed, no API key required)",
731
+ base: "/v1/stores/:storeId",
732
+ endpoints: [{
733
+ method: "GET",
734
+ path: "/v1/stores/:storeId/media",
735
+ scope: "(HMAC signature via 's' query param)",
736
+ description: "Proxy and transform an image (resize, format conversion, quality)",
737
+ params: {
738
+ url: "Required. Base64url-encoded source image URL",
739
+ w: "Width: 64, 96, 128, 256, 384, 640, 828, 1080, 1280, or 1920",
740
+ q: "Quality 1-100 (default: 80)",
741
+ f: "Format: avif, webp, jpeg, png (default: webp)",
742
+ s: "Required. HMAC signature"
743
+ },
744
+ response: "Binary image data with Cache-Control: public, max-age=86400, s-maxage=604800, immutable",
745
+ notes: "Max 8 concurrent transforms, queues for 5s then returns 503 with Retry-After: 2. Use WhaleClient.signMedia() to generate signatures."
746
+ }, {
747
+ method: "GET",
748
+ path: "/v1/stores/:storeId/video",
749
+ scope: "(HMAC signature via 's' query param)",
750
+ description: "Stream a video with HTTP range request support",
751
+ params: {
752
+ url: "Required. Base64url-encoded source video URL",
753
+ s: "Required. HMAC signature"
754
+ },
755
+ response: "Streamed video (supports Accept-Ranges: bytes for seeking). Auto-resolves optimized -web.mp4 variants.",
756
+ notes: "Cache-Control: public, max-age=86400, s-maxage=604800, immutable. X-Video-Source header indicates original vs optimized."
757
+ }]
758
+ },
759
+ infrastructure: {
760
+ name: "Infrastructure",
761
+ description: "Health checks, OpenAPI spec, and interactive documentation",
762
+ base: "",
763
+ endpoints: [{
764
+ method: "GET",
765
+ path: "/health",
766
+ scope: "(no auth)",
767
+ description: "Health check — simple or detailed with dependency status",
768
+ params: {
769
+ detailed: "Set to 'true' to check Supabase and ClickHouse dependencies"
770
+ },
771
+ response: '{ status: "ok"|"degraded"|"down", version: "2026-02-20", uptime_s?, dependencies?: { supabase, clickhouse } }',
772
+ notes: "Simple response: 200 always. Detailed: 503 if both dependencies are down. Cached for 10s."
773
+ }, {
774
+ method: "GET",
775
+ path: "/openapi.json",
776
+ scope: "(no auth)",
777
+ description: "OpenAPI 3.0 specification",
778
+ response: "OpenAPI JSON spec"
779
+ }, {
780
+ method: "GET",
781
+ path: "/docs",
782
+ scope: "(no auth)",
783
+ description: "Interactive API documentation page",
784
+ response: "HTML page"
785
+ }]
786
+ }
787
+ };
788
+
789
+ // ---------------------------------------------------------------------------
790
+ // Auth reference
791
+ // ---------------------------------------------------------------------------
792
+
793
+ const AUTH_GUIDE = {
794
+ base_url: GATEWAY_BASE_URL,
795
+ api_version: "2026-02-20",
796
+ api_version_header: "X-API-Version",
797
+ authentication: {
798
+ method: "API Key via header",
799
+ header: "x-api-key",
800
+ key_format: "wk_live_<32chars> (production) or wk_test_<32chars> (sandbox)",
801
+ how_to_get: "Use the api_keys tool (action: generate) or the WhaleTools dashboard under Settings → API Keys"
802
+ },
803
+ scopes: {
804
+ wildcard: "* (full access), read:* (all reads), write:* (all writes)",
805
+ per_resource: ["read:products", "write:products", "read:orders", "write:orders", "read:customers", "write:customers", "read:inventory", "write:inventory", "read:locations", "read:analytics", "read:cart", "write:cart", "read:checkout", "write:checkout", "read:storefront", "write:storefront", "read:portal", "write:portal", "read:coa"],
806
+ internal: ["write:agent", "write:telemetry"],
807
+ internal_note: "Agent chat and telemetry scopes are used by WhaleTools SDKs and internal services. Media/video endpoints use HMAC signatures instead of API keys."
808
+ },
809
+ rate_limits: {
810
+ default_per_minute: 60,
811
+ headers: "X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset",
812
+ exceeded_status: 429,
813
+ retry_header: "Retry-After (seconds)"
814
+ },
815
+ pagination: {
816
+ style: "Cursor-based",
817
+ params: "limit (1-100, default 25), starting_after (ID), ending_before (ID)",
818
+ response: '{ object: "list", data: [...], has_more: true|false, url: "..." }'
819
+ },
820
+ error_format: {
821
+ shape: '{ error: { type, message, code, param?, request_id? } }',
822
+ types: {
823
+ authentication_error: "401 — invalid_api_key (also returned for missing key)",
824
+ permission_error: "403 — insufficient_scope, store_mismatch",
825
+ not_found_error: "404 — resource_not_found",
826
+ invalid_request_error: "400/405/409 — validation_error, method_not_allowed, conflict",
827
+ rate_limit_error: "429 — rate_limit_exceeded, auth_rate_limited (too many auth attempts)",
828
+ api_error: "500 — internal_error"
829
+ }
830
+ },
831
+ security_headers: {
832
+ cors: "Configurable per-store. Default: allow all origins",
833
+ idempotency: "Idempotency-Key header supported on all POST/PATCH requests",
834
+ versioning: "X-API-Version header (optional — latest version used if omitted)"
835
+ },
836
+ url_pattern: "All endpoints: /v1/stores/:storeId/<resource>",
837
+ note: "Replace :storeId with your store UUID. Get it from the WhaleTools dashboard or the store tool."
838
+ };
839
+
840
+ // ---------------------------------------------------------------------------
841
+ // Code examples by section
842
+ // ---------------------------------------------------------------------------
843
+
844
+ function getExamples(section) {
845
+ const BASE = GATEWAY_BASE_URL;
846
+ const storeVar = "${STORE_ID}";
847
+ const keyVar = "${API_KEY}";
848
+ const templates = {
849
+ products: {
850
+ raw_fetch: `// List products
851
+ const res = await fetch("${BASE}/v1/stores/${storeVar}/products?limit=25&status=published", {
852
+ headers: { "x-api-key": "${keyVar}" }
853
+ });
854
+ const { data: products, has_more } = await res.json();
855
+
856
+ // Get single product
857
+ const product = await fetch("${BASE}/v1/stores/${storeVar}/products/\${productId}", {
858
+ headers: { "x-api-key": "${keyVar}" }
859
+ }).then(r => r.json());`,
860
+ nextjs_ssr: `// app/products/page.tsx (Next.js App Router — Server Component)
861
+ const API_KEY = process.env.WHALE_API_KEY!;
862
+ const STORE_ID = process.env.WHALE_STORE_ID!;
863
+ const BASE = "${BASE}";
864
+
865
+ async function getProducts(page?: string) {
866
+ const params = new URLSearchParams({ limit: "25", status: "published" });
867
+ if (page) params.set("starting_after", page);
868
+
869
+ const res = await fetch(\`\${BASE}/v1/stores/\${STORE_ID}/products?\${params}\`, {
870
+ headers: { "x-api-key": API_KEY },
871
+ next: { revalidate: 60 }, // ISR: revalidate every 60s
872
+ });
873
+
874
+ if (!res.ok) throw new Error("Failed to fetch products");
875
+ return res.json();
876
+ }
877
+
878
+ export default async function ProductsPage({ searchParams }: { searchParams: { after?: string } }) {
879
+ const { data: products, has_more } = await getProducts(searchParams.after);
880
+
881
+ return (
882
+ <div className="grid grid-cols-3 gap-4">
883
+ {products.map((p: any) => (
884
+ <div key={p.id} className="border rounded p-4">
885
+ {p.featured_image && <img src={p.featured_image} alt={p.name} />}
886
+ <h2>{p.name}</h2>
887
+ <p>{p.pricing_data?.tiers?.[0]?.price ? \`$\${p.pricing_data.tiers[0].price}\` : "Contact for pricing"}</p>
888
+ </div>
889
+ ))}
890
+ {has_more && <a href={\`?after=\${products.at(-1)?.id}\`}>Next page →</a>}
891
+ </div>
892
+ );
893
+ }`,
894
+ react_client: `// hooks/useProducts.ts (React client-side)
895
+ import { useState, useEffect } from "react";
896
+
897
+ const BASE = "${BASE}";
898
+
899
+ export function useProducts(storeId: string, apiKey: string) {
900
+ const [products, setProducts] = useState([]);
901
+ const [loading, setLoading] = useState(true);
902
+
903
+ useEffect(() => {
904
+ fetch(\`\${BASE}/v1/stores/\${storeId}/products?status=published&limit=50\`, {
905
+ headers: { "x-api-key": apiKey },
906
+ })
907
+ .then(r => r.json())
908
+ .then(({ data }) => setProducts(data))
909
+ .finally(() => setLoading(false));
910
+ }, [storeId, apiKey]);
911
+
912
+ return { products, loading };
913
+ }`
914
+ },
915
+ cart: {
916
+ raw_fetch: `// Create cart
917
+ const cart = await fetch("${BASE}/v1/stores/${storeVar}/cart", {
918
+ method: "POST",
919
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
920
+ body: JSON.stringify({ customer_id: customerId })
921
+ }).then(r => r.json());
922
+
923
+ // Add item
924
+ await fetch("${BASE}/v1/stores/${storeVar}/cart/\${cart.id}/items", {
925
+ method: "POST",
926
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
927
+ body: JSON.stringify({ product_id: "...", quantity: 2 })
928
+ }).then(r => r.json());
929
+
930
+ // View cart
931
+ const fullCart = await fetch("${BASE}/v1/stores/${storeVar}/cart/\${cart.id}", {
932
+ headers: { "x-api-key": "${keyVar}" }
933
+ }).then(r => r.json());`,
934
+ nextjs_ssr: `// app/api/cart/route.ts (Next.js Route Handler — server-side proxy)
935
+ import { NextRequest, NextResponse } from "next/server";
936
+
937
+ const API_KEY = process.env.WHALE_API_KEY!;
938
+ const STORE_ID = process.env.WHALE_STORE_ID!;
939
+ const BASE = "${BASE}";
940
+
941
+ export async function POST(req: NextRequest) {
942
+ const body = await req.json();
943
+ const res = await fetch(\`\${BASE}/v1/stores/\${STORE_ID}/cart\`, {
944
+ method: "POST",
945
+ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
946
+ body: JSON.stringify(body),
947
+ });
948
+ return NextResponse.json(await res.json());
949
+ }`,
950
+ react_client: `// hooks/useCart.ts
951
+ import { useState, useCallback } from "react";
952
+
953
+ export function useCart(storeId: string, apiKey: string) {
954
+ const [cart, setCart] = useState<any>(null);
955
+ const BASE = "${BASE}";
956
+ const headers = { "x-api-key": apiKey, "Content-Type": "application/json" };
957
+
958
+ const createCart = useCallback(async () => {
959
+ const res = await fetch(\`\${BASE}/v1/stores/\${storeId}/cart\`, {
960
+ method: "POST", headers,
961
+ });
962
+ const data = await res.json();
963
+ setCart(data);
964
+ return data;
965
+ }, [storeId]);
966
+
967
+ const addItem = useCallback(async (productId: string, quantity: number) => {
968
+ if (!cart) return;
969
+ const res = await fetch(\`\${BASE}/v1/stores/\${storeId}/cart/\${cart.id}/items\`, {
970
+ method: "POST", headers,
971
+ body: JSON.stringify({ product_id: productId, quantity }),
972
+ });
973
+ const data = await res.json();
974
+ setCart(data);
975
+ return data;
976
+ }, [storeId, cart]);
977
+
978
+ const removeItem = useCallback(async (itemId: string) => {
979
+ if (!cart) return;
980
+ const res = await fetch(\`\${BASE}/v1/stores/\${storeId}/cart/\${cart.id}/items/\${itemId}\`, {
981
+ method: "DELETE", headers,
982
+ });
983
+ const data = await res.json();
984
+ setCart(data);
985
+ return data;
986
+ }, [storeId, cart]);
987
+
988
+ return { cart, createCart, addItem, removeItem };
989
+ }`
990
+ },
991
+ checkout: {
992
+ raw_fetch: `// E-commerce checkout (convert cart to order)
993
+ const order = await fetch("${BASE}/v1/stores/${storeVar}/checkout", {
994
+ method: "POST",
995
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
996
+ body: JSON.stringify({
997
+ cart_id: cartId,
998
+ payment_method: "card",
999
+ shipping_address: { street: "123 Main St", city: "Charlotte", state: "NC", zip: "28202" }
1000
+ })
1001
+ }).then(r => r.json());
1002
+
1003
+ // POS payment intent flow
1004
+ const intent = await fetch("${BASE}/v1/stores/${storeVar}/checkout/intents", {
1005
+ method: "POST",
1006
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1007
+ body: JSON.stringify({ cart_id: cartId, amount: 49.99 })
1008
+ }).then(r => r.json());
1009
+
1010
+ // Capture after authorization
1011
+ await fetch("${BASE}/v1/stores/${storeVar}/checkout/intents/\${intent.id}/capture", {
1012
+ method: "POST",
1013
+ headers: { "x-api-key": "${keyVar}" }
1014
+ });`,
1015
+ nextjs_ssr: `// app/api/checkout/route.ts (Server-side checkout — keep API key secret)
1016
+ import { NextRequest, NextResponse } from "next/server";
1017
+
1018
+ const API_KEY = process.env.WHALE_API_KEY!;
1019
+ const STORE_ID = process.env.WHALE_STORE_ID!;
1020
+ const BASE = "${BASE}";
1021
+
1022
+ export async function POST(req: NextRequest) {
1023
+ const { cart_id, shipping_address } = await req.json();
1024
+
1025
+ const res = await fetch(\`\${BASE}/v1/stores/\${STORE_ID}/checkout\`, {
1026
+ method: "POST",
1027
+ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
1028
+ body: JSON.stringify({ cart_id, shipping_address }),
1029
+ });
1030
+
1031
+ if (!res.ok) {
1032
+ const err = await res.json();
1033
+ return NextResponse.json(err, { status: res.status });
1034
+ }
1035
+
1036
+ return NextResponse.json(await res.json());
1037
+ }`,
1038
+ react_client: `// components/CheckoutButton.tsx
1039
+ "use client";
1040
+ import { useState } from "react";
1041
+
1042
+ export function CheckoutButton({ cartId }: { cartId: string }) {
1043
+ const [loading, setLoading] = useState(false);
1044
+
1045
+ const handleCheckout = async () => {
1046
+ setLoading(true);
1047
+ try {
1048
+ // Call YOUR server-side route (never expose API key to client)
1049
+ const res = await fetch("/api/checkout", {
1050
+ method: "POST",
1051
+ headers: { "Content-Type": "application/json" },
1052
+ body: JSON.stringify({ cart_id: cartId }),
1053
+ });
1054
+ const order = await res.json();
1055
+ if (order.id) window.location.href = \`/orders/\${order.id}/confirmation\`;
1056
+ } finally {
1057
+ setLoading(false);
1058
+ }
1059
+ };
1060
+
1061
+ return <button onClick={handleCheckout} disabled={loading}>{loading ? "Processing..." : "Checkout"}</button>;
1062
+ }`
1063
+ },
1064
+ orders: {
1065
+ raw_fetch: `// List orders
1066
+ const { data: orders } = await fetch("${BASE}/v1/stores/${storeVar}/orders?limit=25", {
1067
+ headers: { "x-api-key": "${keyVar}" }
1068
+ }).then(r => r.json());
1069
+
1070
+ // Get order details
1071
+ const order = await fetch("${BASE}/v1/stores/${storeVar}/orders/\${orderId}", {
1072
+ headers: { "x-api-key": "${keyVar}" }
1073
+ }).then(r => r.json());
1074
+
1075
+ // Update order status
1076
+ await fetch("${BASE}/v1/stores/${storeVar}/orders/\${orderId}", {
1077
+ method: "PATCH",
1078
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1079
+ body: JSON.stringify({ status: "shipped" })
1080
+ });`,
1081
+ nextjs_ssr: `// app/orders/page.tsx (Server Component)
1082
+ async function getOrders() {
1083
+ const res = await fetch(
1084
+ \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/orders?limit=50\`,
1085
+ { headers: { "x-api-key": process.env.WHALE_API_KEY! }, next: { revalidate: 30 } }
1086
+ );
1087
+ return res.json();
1088
+ }
1089
+
1090
+ export default async function OrdersPage() {
1091
+ const { data: orders } = await getOrders();
1092
+ return (
1093
+ <table>
1094
+ <thead><tr><th>Order</th><th>Status</th><th>Total</th><th>Date</th></tr></thead>
1095
+ <tbody>
1096
+ {orders.map((o: any) => (
1097
+ <tr key={o.id}>
1098
+ <td><a href={\`/orders/\${o.id}\`}>{o.order_number}</a></td>
1099
+ <td>{o.status}</td>
1100
+ <td>\${o.total}</td>
1101
+ <td>{new Date(o.created_at).toLocaleDateString()}</td>
1102
+ </tr>
1103
+ ))}
1104
+ </tbody>
1105
+ </table>
1106
+ );
1107
+ }`,
1108
+ react_client: `// hooks/useOrders.ts
1109
+ import useSWR from "swr";
1110
+
1111
+ const fetcher = (url: string) => fetch(url).then(r => r.json());
1112
+
1113
+ export function useOrders() {
1114
+ // Fetch via your own API route (keeps API key server-side)
1115
+ const { data, error, isLoading } = useSWR("/api/orders", fetcher);
1116
+ return { orders: data?.data ?? [], error, isLoading };
1117
+ }`
1118
+ },
1119
+ customers: {
1120
+ raw_fetch: `// Search customers
1121
+ const { data: customers } = await fetch("${BASE}/v1/stores/${storeVar}/customers?search=john", {
1122
+ headers: { "x-api-key": "${keyVar}" }
1123
+ }).then(r => r.json());
1124
+
1125
+ // Create customer
1126
+ const customer = await fetch("${BASE}/v1/stores/${storeVar}/customers", {
1127
+ method: "POST",
1128
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1129
+ body: JSON.stringify({ first_name: "John", last_name: "Doe", email: "john@example.com" })
1130
+ }).then(r => r.json());`,
1131
+ nextjs_ssr: `// app/api/customers/route.ts
1132
+ import { NextRequest, NextResponse } from "next/server";
1133
+
1134
+ const headers = { "x-api-key": process.env.WHALE_API_KEY! };
1135
+ const base = \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}\`;
1136
+
1137
+ export async function GET(req: NextRequest) {
1138
+ const search = req.nextUrl.searchParams.get("q") || "";
1139
+ const res = await fetch(\`\${base}/customers?search=\${encodeURIComponent(search)}\`, { headers });
1140
+ return NextResponse.json(await res.json());
1141
+ }`,
1142
+ react_client: `// hooks/useCustomers.ts
1143
+ import useSWR from "swr";
1144
+
1145
+ export function useCustomers(search: string) {
1146
+ const { data, isLoading } = useSWR(
1147
+ search ? \`/api/customers?q=\${encodeURIComponent(search)}\` : null,
1148
+ (url) => fetch(url).then(r => r.json())
1149
+ );
1150
+ return { customers: data?.data ?? [], isLoading };
1151
+ }`
1152
+ },
1153
+ inventory: {
1154
+ raw_fetch: `// Get inventory summary
1155
+ const summary = await fetch("${BASE}/v1/stores/${storeVar}/inventory/summary", {
1156
+ headers: { "x-api-key": "${keyVar}" }
1157
+ }).then(r => r.json());
1158
+
1159
+ // Adjust stock
1160
+ await fetch("${BASE}/v1/stores/${storeVar}/inventory/adjust", {
1161
+ method: "POST",
1162
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1163
+ body: JSON.stringify({ product_id: "...", location_id: "...", adjustment: -5, reason: "Sold offline" })
1164
+ });`,
1165
+ nextjs_ssr: `// app/inventory/page.tsx
1166
+ async function getInventory() {
1167
+ const res = await fetch(
1168
+ \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/inventory/summary\`,
1169
+ { headers: { "x-api-key": process.env.WHALE_API_KEY! }, next: { revalidate: 60 } }
1170
+ );
1171
+ return res.json();
1172
+ }
1173
+
1174
+ export default async function InventoryPage() {
1175
+ const summary = await getInventory();
1176
+ return (
1177
+ <div>
1178
+ {summary.locations.map((loc: any) => (
1179
+ <div key={loc.id}>
1180
+ <h3>{loc.name}</h3>
1181
+ <p>{loc.total_products} products, {loc.total_units} units</p>
1182
+ </div>
1183
+ ))}
1184
+ </div>
1185
+ );
1186
+ }`,
1187
+ react_client: `// hooks/useInventory.ts
1188
+ import useSWR from "swr";
1189
+
1190
+ export function useInventorySummary() {
1191
+ const { data, isLoading } = useSWR("/api/inventory/summary", (url) => fetch(url).then(r => r.json()));
1192
+ return { summary: data, isLoading };
1193
+ }`
1194
+ },
1195
+ analytics: {
1196
+ raw_fetch: `// Sales analytics
1197
+ const sales = await fetch("${BASE}/v1/stores/${storeVar}/analytics/sales?period=last_30", {
1198
+ headers: { "x-api-key": "${keyVar}" }
1199
+ }).then(r => r.json());
1200
+
1201
+ // Daily breakdown
1202
+ const daily = await fetch("${BASE}/v1/stores/${storeVar}/analytics/sales/daily?period=last_7", {
1203
+ headers: { "x-api-key": "${keyVar}" }
1204
+ }).then(r => r.json());
1205
+
1206
+ // Product performance
1207
+ const topProducts = await fetch("${BASE}/v1/stores/${storeVar}/analytics/products?limit=10", {
1208
+ headers: { "x-api-key": "${keyVar}" }
1209
+ }).then(r => r.json());`,
1210
+ nextjs_ssr: `// app/dashboard/page.tsx
1211
+ async function getDashboard() {
1212
+ const base = \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/analytics\`;
1213
+ const headers = { "x-api-key": process.env.WHALE_API_KEY! };
1214
+ const opts = { headers, next: { revalidate: 300 } as any };
1215
+
1216
+ const [sales, daily, products] = await Promise.all([
1217
+ fetch(\`\${base}/sales?period=last_30\`, opts).then(r => r.json()),
1218
+ fetch(\`\${base}/sales/daily?period=last_7\`, opts).then(r => r.json()),
1219
+ fetch(\`\${base}/products?limit=5\`, opts).then(r => r.json()),
1220
+ ]);
1221
+
1222
+ return { sales, daily, products };
1223
+ }
1224
+
1225
+ export default async function DashboardPage() {
1226
+ const { sales, daily, products } = await getDashboard();
1227
+ return (
1228
+ <div>
1229
+ <h1>Dashboard</h1>
1230
+ <div className="grid grid-cols-3 gap-4">
1231
+ <div>Revenue: \${sales.total_revenue}</div>
1232
+ <div>Orders: {sales.total_orders}</div>
1233
+ <div>AOV: \${sales.average_order_value}</div>
1234
+ </div>
1235
+ </div>
1236
+ );
1237
+ }`,
1238
+ react_client: `// hooks/useAnalytics.ts
1239
+ import useSWR from "swr";
1240
+
1241
+ export function useSalesAnalytics(period = "last_30") {
1242
+ const { data, isLoading } = useSWR(
1243
+ \`/api/analytics/sales?period=\${period}\`,
1244
+ (url) => fetch(url).then(r => r.json())
1245
+ );
1246
+ return { sales: data, isLoading };
1247
+ }`
1248
+ },
1249
+ locations: {
1250
+ raw_fetch: `// List all locations
1251
+ const { data: locations } = await fetch("${BASE}/v1/stores/${storeVar}/locations", {
1252
+ headers: { "x-api-key": "${keyVar}" }
1253
+ }).then(r => r.json());`,
1254
+ nextjs_ssr: `// lib/api.ts — shared helper
1255
+ export async function getLocations() {
1256
+ const res = await fetch(
1257
+ \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/locations\`,
1258
+ { headers: { "x-api-key": process.env.WHALE_API_KEY! }, next: { revalidate: 3600 } }
1259
+ );
1260
+ return res.json().then(r => r.data);
1261
+ }`,
1262
+ react_client: `// hooks/useLocations.ts
1263
+ import useSWR from "swr";
1264
+
1265
+ export function useLocations() {
1266
+ const { data } = useSWR("/api/locations", (url) => fetch(url).then(r => r.json()));
1267
+ return data?.data ?? [];
1268
+ }`
1269
+ },
1270
+ storefront: {
1271
+ raw_fetch: `// Track page view event
1272
+ await fetch("${BASE}/v1/stores/${storeVar}/storefront/events", {
1273
+ method: "POST",
1274
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1275
+ body: JSON.stringify({
1276
+ session_id: sessionId,
1277
+ event_type: "page_view",
1278
+ event_data: { url: "/products/blue-dream", product_id: "..." }
1279
+ })
1280
+ });
1281
+
1282
+ // Send OTP for customer login
1283
+ await fetch("${BASE}/v1/stores/${storeVar}/storefront/auth/send-code", {
1284
+ method: "POST",
1285
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1286
+ body: JSON.stringify({ email: "customer@example.com" })
1287
+ });`,
1288
+ nextjs_ssr: `// app/api/auth/send-code/route.ts
1289
+ import { NextRequest, NextResponse } from "next/server";
1290
+
1291
+ export async function POST(req: NextRequest) {
1292
+ const { email } = await req.json();
1293
+ const res = await fetch(
1294
+ \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/storefront/auth/send-code\`,
1295
+ {
1296
+ method: "POST",
1297
+ headers: { "x-api-key": process.env.WHALE_API_KEY!, "Content-Type": "application/json" },
1298
+ body: JSON.stringify({ email }),
1299
+ }
1300
+ );
1301
+ return NextResponse.json(await res.json(), { status: res.status });
1302
+ }`,
1303
+ react_client: `// hooks/useAuth.ts
1304
+ import { useState } from "react";
1305
+
1306
+ export function useStorefrontAuth() {
1307
+ const [loading, setLoading] = useState(false);
1308
+
1309
+ const sendCode = async (email: string) => {
1310
+ setLoading(true);
1311
+ await fetch("/api/auth/send-code", {
1312
+ method: "POST",
1313
+ headers: { "Content-Type": "application/json" },
1314
+ body: JSON.stringify({ email }),
1315
+ });
1316
+ setLoading(false);
1317
+ };
1318
+
1319
+ const verifyCode = async (email: string, code: string) => {
1320
+ const res = await fetch("/api/auth/verify-code", {
1321
+ method: "POST",
1322
+ headers: { "Content-Type": "application/json" },
1323
+ body: JSON.stringify({ email, code }),
1324
+ });
1325
+ return res.json(); // { customer_id, session_token }
1326
+ };
1327
+
1328
+ return { sendCode, verifyCode, loading };
1329
+ }`
1330
+ },
1331
+ coa: {
1332
+ raw_fetch: `// List COAs
1333
+ const { data: coas } = await fetch("${BASE}/v1/stores/${storeVar}/coa?limit=50", {
1334
+ headers: { "x-api-key": "${keyVar}" }
1335
+ }).then(r => r.json());
1336
+
1337
+ // Verify by sample ID
1338
+ const verified = await fetch("${BASE}/v1/stores/${storeVar}/coa/verify?sample_id=LAB-2026-001", {
1339
+ headers: { "x-api-key": "${keyVar}" }
1340
+ }).then(r => r.json());
1341
+
1342
+ // Get embeddable COA data
1343
+ const embed = await fetch("${BASE}/v1/stores/${storeVar}/coa/\${coaId}/embed", {
1344
+ headers: { "x-api-key": "${keyVar}" }
1345
+ }).then(r => r.json());`,
1346
+ nextjs_ssr: `// app/products/[id]/coa/page.tsx
1347
+ async function getCOAEmbed(coaId: string) {
1348
+ const res = await fetch(
1349
+ \`${BASE}/v1/stores/\${process.env.WHALE_STORE_ID}/coa/\${coaId}/embed\`,
1350
+ { headers: { "x-api-key": process.env.WHALE_API_KEY! }, next: { revalidate: 3600 } }
1351
+ );
1352
+ return res.json();
1353
+ }
1354
+
1355
+ export default async function COAPage({ params }: { params: { id: string } }) {
1356
+ const { html, data } = await getCOAEmbed(params.id);
1357
+ return (
1358
+ <div>
1359
+ <h1>Certificate of Analysis — {data.product_name}</h1>
1360
+ <div dangerouslySetInnerHTML={{ __html: html }} />
1361
+ </div>
1362
+ );
1363
+ }`,
1364
+ react_client: `// components/COAViewer.tsx
1365
+ "use client";
1366
+ import { useEffect, useState } from "react";
1367
+
1368
+ export function COAViewer({ coaId }: { coaId: string }) {
1369
+ const [html, setHtml] = useState("");
1370
+
1371
+ useEffect(() => {
1372
+ fetch(\`/api/coa/\${coaId}/embed\`).then(r => r.json()).then(d => setHtml(d.html));
1373
+ }, [coaId]);
1374
+
1375
+ return <div dangerouslySetInnerHTML={{ __html: html }} />;
1376
+ }`
1377
+ },
1378
+ portal: {
1379
+ raw_fetch: `// B2B portal login
1380
+ await fetch("${BASE}/v1/stores/${storeVar}/portal/auth/send-code", {
1381
+ method: "POST",
1382
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1383
+ body: JSON.stringify({ email: "buyer@dispensary.com" })
1384
+ });
1385
+
1386
+ // Verify and get session
1387
+ const session = await fetch("${BASE}/v1/stores/${storeVar}/portal/auth/verify", {
1388
+ method: "POST",
1389
+ headers: { "x-api-key": "${keyVar}", "Content-Type": "application/json" },
1390
+ body: JSON.stringify({ email: "buyer@dispensary.com", code: "123456" })
1391
+ }).then(r => r.json());
1392
+
1393
+ // List documents with portal token
1394
+ const { data: docs } = await fetch("${BASE}/v1/stores/${storeVar}/portal/documents", {
1395
+ headers: { "x-api-key": "${keyVar}", "Authorization": "Bearer " + session.token }
1396
+ }).then(r => r.json());`,
1397
+ nextjs_ssr: `// app/portal/layout.tsx — server-side session check
1398
+ import { cookies } from "next/headers";
1399
+ import { redirect } from "next/navigation";
1400
+
1401
+ export default async function PortalLayout({ children }: { children: React.ReactNode }) {
1402
+ const token = cookies().get("portal_token")?.value;
1403
+ if (!token) redirect("/portal/login");
1404
+ return <div className="portal-layout">{children}</div>;
1405
+ }`,
1406
+ react_client: `// hooks/usePortal.ts
1407
+ import { useState } from "react";
1408
+
1409
+ export function usePortal() {
1410
+ const [token, setToken] = useState<string | null>(null);
1411
+
1412
+ const login = async (email: string, code: string) => {
1413
+ const res = await fetch("/api/portal/verify", {
1414
+ method: "POST",
1415
+ headers: { "Content-Type": "application/json" },
1416
+ body: JSON.stringify({ email, code }),
1417
+ });
1418
+ const data = await res.json();
1419
+ setToken(data.token);
1420
+ return data;
1421
+ };
1422
+
1423
+ const getDocuments = async () => {
1424
+ const res = await fetch("/api/portal/documents", {
1425
+ headers: { Authorization: \`Bearer \${token}\` },
1426
+ });
1427
+ return res.json();
1428
+ };
1429
+
1430
+ return { token, login, getDocuments };
1431
+ }`
1432
+ }
1433
+ };
1434
+ return templates[section] ?? null;
1435
+ }
1436
+
1437
+ // ---------------------------------------------------------------------------
1438
+ // Quick start guide
1439
+ // ---------------------------------------------------------------------------
1440
+
1441
+ const QUICK_START = {
1442
+ title: "WhaleTools API — Quick Start Guide",
1443
+ steps: [{
1444
+ step: 1,
1445
+ title: "Get your API key",
1446
+ description: "Generate an API key from the WhaleTools dashboard (Settings → API Keys) or use the api_keys MCP tool.",
1447
+ code: `// Via dashboard: Settings → API Keys → Generate
1448
+ // Or programmatically:
1449
+ // api_keys tool: { action: "generate", name: "My Website", scopes: ["read:products", "read:cart", "write:cart", "write:checkout"] }`
1450
+ }, {
1451
+ step: 2,
1452
+ title: "Set up environment variables",
1453
+ description: "Store your API key and store ID securely. Never expose the API key in client-side code.",
1454
+ code: `# .env.local (Next.js) or .env
1455
+ WHALE_API_KEY=wk_live_abc123...
1456
+ WHALE_STORE_ID=your-store-uuid`
1457
+ }, {
1458
+ step: 3,
1459
+ title: "Fetch products",
1460
+ description: "Make your first API call to list published products.",
1461
+ code: `const res = await fetch(
1462
+ \`https://whale-gateway.fly.dev/v1/stores/\${process.env.WHALE_STORE_ID}/products?status=published&limit=25\`,
1463
+ { headers: { "x-api-key": process.env.WHALE_API_KEY } }
1464
+ );
1465
+ const { data: products, has_more } = await res.json();
1466
+ console.log(\`Loaded \${products.length} products\`);`
1467
+ }, {
1468
+ step: 4,
1469
+ title: "Create a cart",
1470
+ description: "Start a shopping session by creating a cart.",
1471
+ code: `const cart = await fetch(
1472
+ \`https://whale-gateway.fly.dev/v1/stores/\${STORE_ID}/cart\`,
1473
+ {
1474
+ method: "POST",
1475
+ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
1476
+ body: JSON.stringify({})
1477
+ }
1478
+ ).then(r => r.json());
1479
+ console.log("Cart ID:", cart.id);`
1480
+ }, {
1481
+ step: 5,
1482
+ title: "Add items to cart",
1483
+ description: "Add products to the cart by product ID.",
1484
+ code: `await fetch(
1485
+ \`https://whale-gateway.fly.dev/v1/stores/\${STORE_ID}/cart/\${cart.id}/items\`,
1486
+ {
1487
+ method: "POST",
1488
+ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
1489
+ body: JSON.stringify({ product_id: products[0].id, quantity: 1 })
1490
+ }
1491
+ );`
1492
+ }, {
1493
+ step: 6,
1494
+ title: "Checkout",
1495
+ description: "Convert the cart into an order.",
1496
+ code: `const order = await fetch(
1497
+ \`https://whale-gateway.fly.dev/v1/stores/\${STORE_ID}/checkout\`,
1498
+ {
1499
+ method: "POST",
1500
+ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
1501
+ body: JSON.stringify({
1502
+ cart_id: cart.id,
1503
+ shipping_address: {
1504
+ street: "123 Main St",
1505
+ city: "Charlotte",
1506
+ state: "NC",
1507
+ zip: "28202"
1508
+ }
1509
+ })
1510
+ }
1511
+ ).then(r => r.json());
1512
+ console.log("Order created:", order.id, "Status:", order.status);`
1513
+ }],
1514
+ tips: ["Keep your API key server-side. Use Next.js Route Handlers or API routes as a proxy for client-side calls.", "Use cursor pagination (starting_after) instead of offset for consistent results.", "Set next: { revalidate: 60 } in Next.js fetch for automatic ISR (Incremental Static Regeneration).", "Idempotency-Key header prevents duplicate orders — always set it on checkout requests.", "All list endpoints return { object: 'list', data: [...], has_more: boolean }."]
1515
+ };
1516
+
1517
+ // ---------------------------------------------------------------------------
1518
+ // Main handler
1519
+ // ---------------------------------------------------------------------------
1520
+
1521
+ export async function handleApiDocs(_sb, args, _storeId) {
1522
+ const action = args.action;
1523
+ switch (action) {
1524
+ case "sections":
1525
+ {
1526
+ const sections = Object.entries(SECTIONS).map(([key, s]) => ({
1527
+ key,
1528
+ name: s.name,
1529
+ description: s.description,
1530
+ endpoint_count: s.endpoints.length
1531
+ }));
1532
+ return {
1533
+ success: true,
1534
+ data: {
1535
+ total_endpoints: sections.reduce((sum, s) => sum + s.endpoint_count, 0),
1536
+ sections,
1537
+ usage: 'Use api_docs with action "endpoints" and section "<key>" to see full endpoint details.'
1538
+ }
1539
+ };
1540
+ }
1541
+ case "endpoints":
1542
+ {
1543
+ const section = args.section;
1544
+ if (!section) {
1545
+ return {
1546
+ success: false,
1547
+ error: 'Missing required param "section". Use action "sections" to see available sections.'
1548
+ };
1549
+ }
1550
+ const s = SECTIONS[section];
1551
+ if (!s) {
1552
+ return {
1553
+ success: false,
1554
+ error: `Unknown section "${section}". Available: ${Object.keys(SECTIONS).join(", ")}`
1555
+ };
1556
+ }
1557
+ return {
1558
+ success: true,
1559
+ data: {
1560
+ section: s.name,
1561
+ description: s.description,
1562
+ base: s.base,
1563
+ endpoints: s.endpoints
1564
+ }
1565
+ };
1566
+ }
1567
+ case "auth":
1568
+ {
1569
+ return {
1570
+ success: true,
1571
+ data: AUTH_GUIDE
1572
+ };
1573
+ }
1574
+ case "examples":
1575
+ {
1576
+ const section = args.section;
1577
+ if (!section) {
1578
+ return {
1579
+ success: false,
1580
+ error: 'Missing required param "section". Use action "sections" to see available sections.'
1581
+ };
1582
+ }
1583
+ const examples = getExamples(section);
1584
+ if (!examples) {
1585
+ return {
1586
+ success: false,
1587
+ error: `No examples for section "${section}". Available: ${Object.keys(SECTIONS).join(", ")}`
1588
+ };
1589
+ }
1590
+ return {
1591
+ success: true,
1592
+ data: {
1593
+ section,
1594
+ examples,
1595
+ tip: "Always keep API keys server-side. Use Next.js Route Handlers or API routes as a proxy for client-side calls."
1596
+ }
1597
+ };
1598
+ }
1599
+ case "quick_start":
1600
+ {
1601
+ return {
1602
+ success: true,
1603
+ data: QUICK_START
1604
+ };
1605
+ }
1606
+ default:
1607
+ return {
1608
+ success: false,
1609
+ error: `Unknown api_docs action: "${action}". Available: sections, endpoints, auth, examples, quick_start`
1610
+ };
1611
+ }
1612
+ }
1613
+ //# sourceMappingURL=api-docs.js.map