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
@@ -5,794 +5,856 @@
5
5
  * All chalk instances are rebuilt on theme switch via rebuildMarkdownRenderer().
6
6
  * Uses marked + marked-terminal for markdown structure.
7
7
  */
8
+
8
9
  import { Marked } from "marked";
9
10
  import { markedTerminal } from "marked-terminal";
10
11
  import chalk from "chalk";
11
12
  import { colors } from "./Theme.js";
12
13
  import { highlightCode, setRebuildCallback } from "./theme-manager.js";
13
14
  import { diffWords } from "diff";
15
+
14
16
  // Note: chalk.level is auto-detected by supports-color.
15
17
  // Apple_Terminal → level 2 (256-color), iTerm.app v3+ → level 3 (24-bit).
16
18
  // Do NOT force level 3 — Terminal.app can't render 24-bit codes (shows gray).
19
+
17
20
  // ============================================================================
18
21
  // Palette factory — rebuilt on theme switch
19
22
  // ============================================================================
23
+
20
24
  function buildPalette() {
21
- return {
22
- systemBlue: chalk.hex(colors.brand),
23
- systemCyan: chalk.hex(colors.info),
24
- systemPink: chalk.hex(colors.pink),
25
- systemPurple: chalk.hex(colors.purple),
26
- systemIndigo: chalk.hex(colors.indigo),
27
- systemGreen: chalk.hex(colors.success),
28
- systemMint: chalk.hex(colors.mint),
29
- systemRed: chalk.hex(colors.error),
30
- systemOrange: chalk.hex(colors.warning),
31
- text: chalk.hex(colors.text),
32
- secondary: chalk.hex(colors.secondary),
33
- tertiary: chalk.hex(colors.tertiary),
34
- separator: chalk.hex(colors.separator),
35
- lavender: chalk.hex(colors.lavender),
36
- roseGold: chalk.hex(colors.roseGold),
37
- };
25
+ return {
26
+ systemBlue: chalk.hex(colors.brand),
27
+ systemCyan: chalk.hex(colors.info),
28
+ systemPink: chalk.hex(colors.pink),
29
+ systemPurple: chalk.hex(colors.purple),
30
+ systemIndigo: chalk.hex(colors.indigo),
31
+ systemGreen: chalk.hex(colors.success),
32
+ systemMint: chalk.hex(colors.mint),
33
+ systemRed: chalk.hex(colors.error),
34
+ systemOrange: chalk.hex(colors.warning),
35
+ text: chalk.hex(colors.text),
36
+ secondary: chalk.hex(colors.secondary),
37
+ tertiary: chalk.hex(colors.tertiary),
38
+ separator: chalk.hex(colors.separator),
39
+ lavender: chalk.hex(colors.lavender),
40
+ roseGold: chalk.hex(colors.roseGold)
41
+ };
38
42
  }
39
43
  let p = buildPalette();
44
+
40
45
  // ============================================================================
41
46
  // Terminal width helpers — single source of truth for layout widths
42
47
  // ============================================================================
43
- function termWidth() {
44
- return process.stdout.columns || 80;
48
+
49
+ /** Raw terminal width — use for elements at the outermost level (separators). */
50
+ export function termWidth() {
51
+ return process.stdout.columns || 80;
45
52
  }
46
- /** Width for top-level assistant text (accounts for MessageList marginLeft=2) */
53
+
54
+ /** Width for assistant message text (outer padding=2 + message marginLeft=2 = 4). */
47
55
  export function contentWidth() {
48
- return termWidth() - 2;
56
+ return termWidth() - 4;
49
57
  }
58
+
50
59
  /** Width for content nested inside tool results (MessageList=2 + ToolIndicator=2 + safety=2) */
51
60
  export function toolContentWidth() {
52
- return termWidth() - 6;
61
+ return termWidth() - 6;
53
62
  }
63
+
54
64
  // ============================================================================
55
65
  // OSC 8 hyperlinks — only in terminals that support them
56
66
  // ============================================================================
67
+
57
68
  /** Detect if terminal supports OSC 8 clickable hyperlinks */
58
69
  const supportsOsc8 = (() => {
59
- const tp = process.env.TERM_PROGRAM || "";
60
- if (/iterm|wezterm|kitty|hyper|warp|foot|alacritty/i.test(tp))
61
- return true;
62
- if (process.env.VTE_VERSION)
63
- return true; // GNOME Terminal, Tilix
64
- if (process.env.WT_SESSION)
65
- return true; // Windows Terminal
66
- if (process.env.KONSOLE_VERSION)
67
- return true; // Konsole
68
- // Apple Terminal.app does NOT support OSC 8
69
- return false;
70
+ const tp = process.env.TERM_PROGRAM || "";
71
+ if (/iterm|wezterm|kitty|hyper|warp|foot|alacritty/i.test(tp)) return true;
72
+ if (process.env.VTE_VERSION) return true; // GNOME Terminal, Tilix
73
+ if (process.env.WT_SESSION) return true; // Windows Terminal
74
+ if (process.env.KONSOLE_VERSION) return true; // Konsole
75
+ // Apple Terminal.app does NOT support OSC 8
76
+ return false;
70
77
  })();
71
78
  function hyperlink(url, text) {
72
- // mailto: → clean email address, no protocol prefix, no OSC 8
73
- if (url.startsWith("mailto:")) {
74
- const email = text || url.slice(7);
75
- return p.systemCyan(email);
76
- }
77
- // tel: → clean phone number
78
- if (url.startsWith("tel:")) {
79
- return p.systemCyan(text || url.slice(4));
80
- }
81
- const display = text || url;
82
- // OSC 8 clickable links — only where terminal supports them
83
- if (supportsOsc8) {
84
- return `\x1B]8;;${url}\x07${p.systemCyan.underline(display)}\x1B]8;;\x07`;
85
- }
86
- // Fallback: colored underlined text (no escape sequences)
87
- return p.systemCyan.underline(display);
79
+ // mailto: → clean email address, no protocol prefix, no OSC 8
80
+ if (url.startsWith("mailto:")) {
81
+ const email = text || url.slice(7);
82
+ return p.systemCyan(email);
83
+ }
84
+
85
+ // tel: → clean phone number
86
+ if (url.startsWith("tel:")) {
87
+ return p.systemCyan(text || url.slice(4));
88
+ }
89
+ const display = text || url;
90
+
91
+ // OSC 8 clickable links — only where terminal supports them
92
+ if (supportsOsc8) {
93
+ return `\x1B]8;;${url}\x07${p.systemCyan.underline(display)}\x1B]8;;\x07`;
94
+ }
95
+
96
+ // Fallback: colored underlined text (no escape sequences)
97
+ return p.systemCyan.underline(display);
88
98
  }
99
+
89
100
  // ============================================================================
90
101
  // Path helpers
91
102
  // ============================================================================
103
+
92
104
  /** Shorten a file path for code block headers */
93
105
  function shortenPathForHeader(fullPath, maxLen = 40) {
94
- let fp = fullPath;
95
- const cwd = process.cwd();
96
- const home = process.env.HOME || "";
97
- if (fp.startsWith(cwd + "/"))
98
- fp = fp.slice(cwd.length + 1);
99
- else if (fp.startsWith(cwd))
100
- fp = fp.slice(cwd.length);
101
- else if (home && fp.startsWith(home))
102
- fp = "~" + fp.slice(home.length);
103
- if (fp.length <= maxLen)
104
- return fp;
105
- const parts = fp.split("/");
106
- const file = parts.pop();
107
- if (file.length >= maxLen - 4)
108
- return "…/" + file.slice(-(maxLen - 4));
109
- const parent = parts.pop();
110
- return parent ? "…/" + parent + "/" + file : "…/" + file;
106
+ let fp = fullPath;
107
+ const cwd = process.cwd();
108
+ const home = process.env.HOME || "";
109
+ if (fp.startsWith(cwd + "/")) fp = fp.slice(cwd.length + 1);else if (fp.startsWith(cwd)) fp = fp.slice(cwd.length);else if (home && fp.startsWith(home)) fp = "~" + fp.slice(home.length);
110
+ if (fp.length <= maxLen) return fp;
111
+ const parts = fp.split("/");
112
+ const file = parts.pop();
113
+ if (file.length >= maxLen - 4) return "…/" + file.slice(-(maxLen - 4));
114
+ const parent = parts.pop();
115
+ return parent ? "…/" + parent + "/" + file : "…/" + file;
111
116
  }
117
+
112
118
  // ============================================================================
113
119
  // Financial coloring
114
120
  // ============================================================================
121
+
115
122
  function colorizeFinancials(str) {
116
- return str
117
- // NOTE: URL hyperlinking is handled by marked's GFM autolink + link/href handlers.
118
- // Do NOT add URL patterns here — it causes links to render 3-5x.
119
- // Negative dollar amounts → red (-$1,234.56) — require digit after $
120
- .replace(/(-\$\d[\d,]*\.?\d*)/g, (m) => p.systemRed(m))
121
- // Positive dollar amounts → green ($1,234.56) — require digit after $
122
- .replace(/((?:^|[^-])\$\d[\d,]*\.?\d*)/g, (m) => p.systemGreen(m))
123
- // Negative percentages → red
124
- .replace(/(-\d+\.?\d*%)/g, (m) => p.systemRed(m))
125
- // Positive percentages → cyan
126
- .replace(/((?:^|[^-])\d+\.?\d*%)/g, (m) => p.systemCyan(m))
127
- // Explicit positive → green
128
- .replace(/(\+\$?[\d,]+\.?\d*)/g, (m) => p.systemGreen(m))
129
- // Financial-specific words → green (no generic words like running/ready/started)
130
- .replace(/\b(profit|revenue|gain|in stock|available)\b/gi, (m) => p.systemGreen(m))
131
- // Financial/status negatives → red
132
- .replace(/\b(loss|deduction|deficit|expense|out of stock|low stock|overdue|expired|cancelled|failed|error|crashed|EADDRINUSE|ENOENT)\b/gi, (m) => p.systemRed(m));
123
+ return str
124
+ // NOTE: URL hyperlinking is handled by marked's GFM autolink + link/href handlers.
125
+ // Do NOT add URL patterns here — it causes links to render 3-5x.
126
+ // Negative dollar amounts → red (-$1,234.56) — require digit after $
127
+ .replace(/(-\$\d[\d,]*\.?\d*)/g, m => p.systemRed(m))
128
+ // Positive dollar amounts → green ($1,234.56) — require digit after $
129
+ .replace(/((?:^|[^-])\$\d[\d,]*\.?\d*)/g, m => p.systemGreen(m))
130
+ // Negative percentages → red
131
+ .replace(/(-\d+\.?\d*%)/g, m => p.systemRed(m))
132
+ // Positive percentages → cyan
133
+ .replace(/((?:^|[^-])\d+\.?\d*%)/g, m => p.systemCyan(m))
134
+ // Explicit positive → green
135
+ .replace(/(\+\$?[\d,]+\.?\d*)/g, m => p.systemGreen(m))
136
+ // Financial-specific words → green (no generic words like running/ready/started)
137
+ .replace(/\b(profit|revenue|gain|in stock|available)\b/gi, m => p.systemGreen(m))
138
+ // Financial/status negatives → red
139
+ .replace(/\b(loss|deduction|deficit|expense|out of stock|low stock|overdue|expired|cancelled|failed|error|crashed|EADDRINUSE|ENOENT)\b/gi, m => p.systemRed(m));
133
140
  }
141
+
134
142
  // ============================================================================
135
143
  // Markdown renderer factory — rebuilt on theme switch
136
144
  // ============================================================================
145
+
137
146
  function buildMarkedInstance() {
138
- const md = new Marked();
139
- md.use(markedTerminal({
140
- // Headings — bold blue
141
- firstHeading: p.systemBlue.bold,
142
- heading: p.systemBlue.bold,
143
- // Inline
144
- codespan: p.systemPink,
145
- strong: p.text.bold,
146
- em: p.lavender.italic,
147
- // Blocks
148
- blockquote: p.secondary.italic,
149
- paragraph: (body) => colorizeFinancials(body),
150
- hr: () => p.separator("─".repeat(50)),
151
- // Links — OSC 8 clickable (single source of truth for URL rendering)
152
- // NOTE: Only use `link` handler, NOT `href` — having both causes double-hyperlinking
153
- link: (href, _title, text) => hyperlink(href, text !== href ? text : undefined),
154
- // Lists — purple bullets, financial-aware
155
- list: (body, ordered) => {
156
- if (ordered) {
157
- let n = 0;
158
- return body.replace(/^\* /gm, () => {
159
- n++;
160
- return `${p.systemIndigo(String(n) + ".")} `;
161
- });
147
+ const md = new Marked();
148
+ md.use(markedTerminal({
149
+ // Headings — bold blue
150
+ firstHeading: p.systemBlue.bold,
151
+ heading: p.systemBlue.bold,
152
+ // Inline
153
+ codespan: p.systemPink,
154
+ strong: p.text.bold,
155
+ em: p.lavender.italic,
156
+ // Blocks
157
+ blockquote: p.secondary.italic,
158
+ paragraph: body => colorizeFinancials(body),
159
+ hr: () => p.separator("─".repeat(50)),
160
+ // Links — OSC 8 clickable (single source of truth for URL rendering)
161
+ // NOTE: Only use `link` handler, NOT `href` — having both causes double-hyperlinking
162
+ link: (href, _title, text) => hyperlink(href, text !== href ? text : undefined),
163
+ // Lists — purple bullets, financial-aware
164
+ list: (body, ordered) => {
165
+ if (ordered) {
166
+ let n = 0;
167
+ return body.replace(/^\* /gm, () => {
168
+ n++;
169
+ return `${p.systemIndigo(String(n) + ".")} `;
170
+ });
171
+ }
172
+ return body.replace(/^\* /gm, `${p.systemPurple("●")} `);
173
+ },
174
+ listitem: itemText => {
175
+ return colorizeFinancials(itemText);
176
+ },
177
+ // Layout — adapt to terminal width
178
+ reflowText: false,
179
+ showSectionPrefix: false,
180
+ width: Math.min(120, contentWidth()),
181
+ tab: 2
182
+ }));
183
+
184
+ // Register chart + table + code block extensions
185
+ md.use({
186
+ renderer: {
187
+ code(token) {
188
+ const rawLang = token.lang || "";
189
+ const code = token.text;
190
+
191
+ // Parse lang:subtitle (e.g. "typescript:src/foo.ts")
192
+ const colonIdx = rawLang.indexOf(":");
193
+ const lang = colonIdx > 0 ? rawLang.slice(0, colonIdx) : rawLang;
194
+ const subtitle = colonIdx > 0 ? rawLang.slice(colonIdx + 1) : "";
195
+ if (lang === "chart" || lang === "bar") {
196
+ return renderBarChart(code);
197
+ }
198
+ if (lang === "diff") {
199
+ return renderDiff(code);
200
+ }
201
+ {
202
+ // Command output mode: bash without subtitle = run_command output
203
+ // → no line numbers, wider content area, clean indent
204
+ const isCommandOutput = (lang === "bash" || lang === "terminal") && !subtitle;
205
+ const highlightLang = lang === "terminal" ? "bash" : lang;
206
+
207
+ // Build header: ── lang ── subtitle ──────
208
+ const cw = contentWidth();
209
+ const headerWidth = Math.max(20, cw - 6);
210
+ const displayLang = isCommandOutput ? "bash" : lang;
211
+ let header;
212
+ if (displayLang && subtitle) {
213
+ const shortSub = shortenPathForHeader(subtitle, headerWidth - displayLang.length - 10);
214
+ const pad = Math.max(2, headerWidth - displayLang.length - shortSub.length - 6);
215
+ header = p.separator(" ── ") + p.tertiary(displayLang) + p.separator(" ── ") + p.secondary(shortSub) + p.separator(` ${"─".repeat(pad)}`);
216
+ } else if (displayLang) {
217
+ const pad = Math.max(2, headerWidth - displayLang.length - 3);
218
+ header = p.separator(" ── ") + p.tertiary(displayLang) + p.separator(` ${"─".repeat(pad)}`);
219
+ } else {
220
+ header = p.separator(" ──" + "─".repeat(headerWidth - 2));
221
+ }
222
+
223
+ // Calculate max line width to prevent wrapping
224
+ const lineCount = code.split("\n").length;
225
+ const gutterW = isCommandOutput ? 0 : String(lineCount).length;
226
+ const gutterOverhead = isCommandOutput ? 4 : 2 + gutterW + 3; // " " or " 123 │ "
227
+ const maxLineWidth = Math.max(20, cw - gutterOverhead - 2);
228
+
229
+ // Pre-truncate lines BEFORE highlighting (avoids cutting ANSI codes)
230
+ const truncatedCode = code.split("\n").map(line => {
231
+ if (line.length > maxLineWidth) {
232
+ return line.slice(0, maxLineWidth - 1) + "…";
162
233
  }
163
- return body.replace(/^\* /gm, `${p.systemPurple("●")} `);
164
- },
165
- listitem: (itemText) => {
166
- return colorizeFinancials(itemText);
167
- },
168
- // Layout adapt to terminal width
169
- reflowText: false,
170
- showSectionPrefix: false,
171
- width: Math.min(120, contentWidth()),
172
- tab: 2,
173
- }));
174
- // Register chart + table + code block extensions
175
- md.use({
176
- renderer: {
177
- code(token) {
178
- const rawLang = token.lang || "";
179
- const code = token.text;
180
- // Parse lang:subtitle (e.g. "typescript:src/foo.ts")
181
- const colonIdx = rawLang.indexOf(":");
182
- const lang = colonIdx > 0 ? rawLang.slice(0, colonIdx) : rawLang;
183
- const subtitle = colonIdx > 0 ? rawLang.slice(colonIdx + 1) : "";
184
- if (lang === "chart" || lang === "bar") {
185
- return renderBarChart(code);
186
- }
187
- if (lang === "diff") {
188
- return renderDiff(code);
189
- }
190
- {
191
- // Command output mode: bash without subtitle = run_command output
192
- // → no line numbers, wider content area, clean indent
193
- const isCommandOutput = (lang === "bash" || lang === "terminal") && !subtitle;
194
- const highlightLang = lang === "terminal" ? "bash" : lang;
195
- // Build header: ── lang ── subtitle ──────
196
- const cw = contentWidth();
197
- const headerWidth = Math.max(20, cw - 6);
198
- const displayLang = isCommandOutput ? "bash" : lang;
199
- let header;
200
- if (displayLang && subtitle) {
201
- const shortSub = shortenPathForHeader(subtitle, headerWidth - displayLang.length - 10);
202
- const pad = Math.max(2, headerWidth - displayLang.length - shortSub.length - 6);
203
- header = p.separator(" ── ") + p.tertiary(displayLang) + p.separator(" ── ") + p.secondary(shortSub) + p.separator(` ${"─".repeat(pad)}`);
204
- }
205
- else if (displayLang) {
206
- const pad = Math.max(2, headerWidth - displayLang.length - 3);
207
- header = p.separator(" ── ") + p.tertiary(displayLang) + p.separator(` ${"─".repeat(pad)}`);
208
- }
209
- else {
210
- header = p.separator(" ──" + "─".repeat(headerWidth - 2));
211
- }
212
- // Calculate max line width to prevent wrapping
213
- const lineCount = code.split("\n").length;
214
- const gutterW = isCommandOutput ? 0 : String(lineCount).length;
215
- const gutterOverhead = isCommandOutput ? 4 : (2 + gutterW + 3); // " " or " 123 │ "
216
- const maxLineWidth = Math.max(20, cw - gutterOverhead - 2);
217
- // Pre-truncate lines BEFORE highlighting (avoids cutting ANSI codes)
218
- const truncatedCode = code.split("\n").map((line) => {
219
- if (line.length > maxLineWidth) {
220
- return line.slice(0, maxLineWidth - 1) + "…";
221
- }
222
- return line;
223
- }).join("\n");
224
- // Highlight with shiki
225
- const highlighted = highlightLang
226
- ? highlightCode(truncatedCode, highlightLang)
227
- : truncatedCode;
228
- const hLines = highlighted.split("\n");
229
- if (isCommandOutput) {
230
- // Command output: no line numbers, 4-space indent
231
- const body = hLines.map(l => " " + l).join("\n");
232
- return "\n" + header + "\n" + body + "\n";
233
- }
234
- else {
235
- // Code with line numbers + gutter
236
- const numbered = hLines.map((l, i) => {
237
- const num = p.tertiary(String(i + 1).padStart(gutterW));
238
- return " " + num + p.separator(" │ ") + l;
239
- }).join("\n");
240
- return "\n" + header + "\n" + numbered + "\n";
241
- }
242
- }
243
- },
244
- table(token) {
245
- return renderTable(token);
246
- },
247
- },
248
- });
249
- return md;
234
+ return line;
235
+ }).join("\n");
236
+
237
+ // Highlight with shiki
238
+ const highlighted = highlightLang ? highlightCode(truncatedCode, highlightLang) : truncatedCode;
239
+ const hLines = highlighted.split("\n");
240
+ if (isCommandOutput) {
241
+ // Command output: no line numbers, 4-space indent
242
+ const body = hLines.map(l => " " + l).join("\n");
243
+ return "\n" + header + "\n" + body + "\n";
244
+ } else {
245
+ // Code with line numbers + gutter
246
+ const numbered = hLines.map((l, i) => {
247
+ const num = p.tertiary(String(i + 1).padStart(gutterW));
248
+ return " " + num + p.separator(" │ ") + l;
249
+ }).join("\n");
250
+ return "\n" + header + "\n" + numbered + "\n";
251
+ }
252
+ }
253
+ },
254
+ table(token) {
255
+ return renderTable(token);
256
+ }
257
+ }
258
+ });
259
+ return md;
250
260
  }
251
261
  let md = buildMarkedInstance();
262
+
252
263
  // ============================================================================
253
264
  // Diff renderer — background colors + word-level diff (Claude Code parity)
254
265
  // ============================================================================
266
+
255
267
  function buildDiffStyles() {
256
- return {
257
- diffAddedBg: chalk.bgHex(colors.diffAddedBg).white,
258
- diffRemovedBg: chalk.bgHex(colors.diffRemovedBg).white,
259
- diffWordAdded: chalk.bgHex(colors.diffWordAdded).whiteBright.bold,
260
- diffWordRemoved: chalk.bgHex(colors.diffWordRemoved).whiteBright.bold,
261
- };
268
+ return {
269
+ diffAddedBg: chalk.bgHex(colors.diffAddedBg).white,
270
+ diffRemovedBg: chalk.bgHex(colors.diffRemovedBg).white,
271
+ diffWordAdded: chalk.bgHex(colors.diffWordAdded).whiteBright.bold,
272
+ diffWordRemoved: chalk.bgHex(colors.diffWordRemoved).whiteBright.bold
273
+ };
262
274
  }
263
275
  let d = buildDiffStyles();
276
+
264
277
  /** Compute word-level diff between two lines using the `diff` library. */
265
278
  function wordDiff(oldLine, newLine) {
266
- const changes = diffWords(oldLine, newLine);
267
- const oldSegs = [];
268
- const newSegs = [];
269
- for (const change of changes) {
270
- if (change.added) {
271
- newSegs.push({ text: change.value, changed: true });
272
- }
273
- else if (change.removed) {
274
- oldSegs.push({ text: change.value, changed: true });
275
- }
276
- else {
277
- oldSegs.push({ text: change.value, changed: false });
278
- newSegs.push({ text: change.value, changed: false });
279
- }
280
- }
281
- // If >60% of either line changed, fall back to full-line highlight
282
- const oldChanged = oldSegs.filter(s => s.changed).reduce((n, s) => n + s.text.length, 0);
283
- const newChanged = newSegs.filter(s => s.changed).reduce((n, s) => n + s.text.length, 0);
284
- if ((oldLine.length > 0 && oldChanged / oldLine.length > 0.6) ||
285
- (newLine.length > 0 && newChanged / newLine.length > 0.6)) {
286
- return { old: [{ text: oldLine, changed: true }], new: [{ text: newLine, changed: true }] };
287
- }
288
- return { old: oldSegs, new: newSegs };
279
+ const changes = diffWords(oldLine, newLine);
280
+ const oldSegs = [];
281
+ const newSegs = [];
282
+ for (const change of changes) {
283
+ if (change.added) {
284
+ newSegs.push({
285
+ text: change.value,
286
+ changed: true
287
+ });
288
+ } else if (change.removed) {
289
+ oldSegs.push({
290
+ text: change.value,
291
+ changed: true
292
+ });
293
+ } else {
294
+ oldSegs.push({
295
+ text: change.value,
296
+ changed: false
297
+ });
298
+ newSegs.push({
299
+ text: change.value,
300
+ changed: false
301
+ });
302
+ }
303
+ }
304
+
305
+ // If >60% of either line changed, fall back to full-line highlight
306
+ const oldChanged = oldSegs.filter(s => s.changed).reduce((n, s) => n + s.text.length, 0);
307
+ const newChanged = newSegs.filter(s => s.changed).reduce((n, s) => n + s.text.length, 0);
308
+ if (oldLine.length > 0 && oldChanged / oldLine.length > 0.6 || newLine.length > 0 && newChanged / newLine.length > 0.6) {
309
+ return {
310
+ old: [{
311
+ text: oldLine,
312
+ changed: true
313
+ }],
314
+ new: [{
315
+ text: newLine,
316
+ changed: true
317
+ }]
318
+ };
319
+ }
320
+ return {
321
+ old: oldSegs,
322
+ new: newSegs
323
+ };
289
324
  }
325
+
290
326
  /** Render segments with word-level highlighting */
291
327
  function renderSegments(segs, wordStyle, lineStyle) {
292
- return segs.map(s => s.changed ? wordStyle(s.text) : lineStyle(s.text)).join("");
328
+ return segs.map(s => s.changed ? wordStyle(s.text) : lineStyle(s.text)).join("");
293
329
  }
294
330
  function renderDiff(code) {
295
- const lines = code.split("\n");
296
- const tw = toolContentWidth();
297
- const segments = [];
298
- let oldLineNo = 1, newLineNo = 1;
299
- let seenDiff = false;
300
- for (const line of lines) {
301
- // Skip file headers (--- a/file, +++ b/file)
302
- if (line.startsWith("---") || line.startsWith("+++"))
303
- continue;
304
- // Hunk header extract line numbers
305
- const hunkMatch = line.match(/^@@\s*-(\d+)(?:,\d+)?\s*\+(\d+)(?:,\d+)?\s*@@/);
306
- if (hunkMatch) {
307
- oldLineNo = parseInt(hunkMatch[1]);
308
- newLineNo = parseInt(hunkMatch[2]);
309
- seenDiff = true;
310
- continue;
311
- }
312
- // Skip non-diff header lines (e.g., "File edited:", "Applied N edits")
313
- if (!seenDiff && !line.startsWith("-") && !line.startsWith("+") && !line.startsWith(" ")) {
314
- continue;
315
- }
316
- seenDiff = true;
317
- if (line.startsWith("-")) {
318
- segments.push({ type: "remove", content: line.slice(1), lineNo: oldLineNo });
319
- oldLineNo++;
320
- }
321
- else if (line.startsWith("+")) {
322
- segments.push({ type: "add", content: line.slice(1), lineNo: newLineNo });
323
- newLineNo++;
324
- }
325
- else {
326
- const content = line.startsWith(" ") ? line.slice(1) : line;
327
- segments.push({ type: "context", content, lineNo: newLineNo });
328
- oldLineNo++;
329
- newLineNo++;
330
- }
331
- }
332
- if (segments.length === 0)
333
- return code; // fallback
334
- // Gutter width from max line number
335
- const maxLineNo = segments.reduce((max, s) => Math.max(max, s.lineNo), 0);
336
- const gutterW = Math.max(3, String(maxLineNo).length);
337
- const out = [];
338
- let i = 0;
339
- while (i < segments.length) {
340
- const seg = segments[i];
341
- if (seg.type === "remove") {
342
- // Collect consecutive removes
343
- const removes = [];
344
- while (i < segments.length && segments[i].type === "remove") {
345
- removes.push(segments[i]);
346
- i++;
347
- }
348
- // Collect consecutive adds
349
- const adds = [];
350
- while (i < segments.length && segments[i].type === "add") {
351
- adds.push(segments[i]);
352
- i++;
353
- }
354
- // Pair for word-level diff
355
- const pairCount = Math.min(removes.length, adds.length);
356
- for (let j = 0; j < removes.length; j++) {
357
- const r = removes[j];
358
- const rPrefix = `${String(r.lineNo).padStart(gutterW)} - `;
359
- if (j < pairCount) {
360
- const a = adds[j];
361
- const aPrefix = `${String(a.lineNo).padStart(gutterW)} + `;
362
- const wd = wordDiff(r.content, a.content);
363
- // Removed line with word highlights
364
- const rPad = Math.max(0, tw - rPrefix.length - r.content.length);
365
- out.push(d.diffRemovedBg(rPrefix) + renderSegments(wd.old, d.diffWordRemoved, d.diffRemovedBg) + d.diffRemovedBg(" ".repeat(rPad)));
366
- // Added line with word highlights
367
- const aPad = Math.max(0, tw - aPrefix.length - a.content.length);
368
- out.push(d.diffAddedBg(aPrefix) + renderSegments(wd.new, d.diffWordAdded, d.diffAddedBg) + d.diffAddedBg(" ".repeat(aPad)));
369
- }
370
- else {
371
- // Unpaired remove
372
- const raw = rPrefix + r.content;
373
- const pad = Math.max(0, tw - raw.length);
374
- out.push(d.diffRemovedBg(raw + " ".repeat(pad)));
375
- }
376
- }
377
- // Unpaired adds
378
- for (let j = pairCount; j < adds.length; j++) {
379
- const a = adds[j];
380
- const prefix = `${String(a.lineNo).padStart(gutterW)} + `;
381
- const raw = prefix + a.content;
382
- const pad = Math.max(0, tw - raw.length);
383
- out.push(d.diffAddedBg(raw + " ".repeat(pad)));
384
- }
385
- continue;
386
- }
387
- if (seg.type === "add") {
388
- // Standalone add (no preceding remove)
389
- const prefix = `${String(seg.lineNo).padStart(gutterW)} + `;
390
- const raw = prefix + seg.content;
391
- const pad = Math.max(0, tw - raw.length);
392
- out.push(d.diffAddedBg(raw + " ".repeat(pad)));
393
- i++;
394
- continue;
395
- }
396
- // Context line — dim line number, plain content, no background
397
- const prefix = p.tertiary(`${String(seg.lineNo).padStart(gutterW)} `);
398
- out.push(prefix + seg.content);
331
+ const lines = code.split("\n");
332
+ const tw = toolContentWidth();
333
+
334
+ // Parse into segments from unified diff format
335
+
336
+ const segments = [];
337
+ let oldLineNo = 1,
338
+ newLineNo = 1;
339
+ let seenDiff = false;
340
+ for (const line of lines) {
341
+ // Skip file headers (--- a/file, +++ b/file)
342
+ if (line.startsWith("---") || line.startsWith("+++")) continue;
343
+
344
+ // Hunk header — extract line numbers
345
+ const hunkMatch = line.match(/^@@\s*-(\d+)(?:,\d+)?\s*\+(\d+)(?:,\d+)?\s*@@/);
346
+ if (hunkMatch) {
347
+ oldLineNo = parseInt(hunkMatch[1]);
348
+ newLineNo = parseInt(hunkMatch[2]);
349
+ seenDiff = true;
350
+ continue;
351
+ }
352
+
353
+ // Skip non-diff header lines (e.g., "File edited:", "Applied N edits")
354
+ if (!seenDiff && !line.startsWith("-") && !line.startsWith("+") && !line.startsWith(" ")) {
355
+ continue;
356
+ }
357
+ seenDiff = true;
358
+ if (line.startsWith("-")) {
359
+ segments.push({
360
+ type: "remove",
361
+ content: line.slice(1),
362
+ lineNo: oldLineNo
363
+ });
364
+ oldLineNo++;
365
+ } else if (line.startsWith("+")) {
366
+ segments.push({
367
+ type: "add",
368
+ content: line.slice(1),
369
+ lineNo: newLineNo
370
+ });
371
+ newLineNo++;
372
+ } else {
373
+ const content = line.startsWith(" ") ? line.slice(1) : line;
374
+ segments.push({
375
+ type: "context",
376
+ content,
377
+ lineNo: newLineNo
378
+ });
379
+ oldLineNo++;
380
+ newLineNo++;
381
+ }
382
+ }
383
+ if (segments.length === 0) return code; // fallback
384
+
385
+ // Gutter width from max line number
386
+ const maxLineNo = segments.reduce((max, s) => Math.max(max, s.lineNo), 0);
387
+ const gutterW = Math.max(3, String(maxLineNo).length);
388
+ const out = [];
389
+ let i = 0;
390
+ while (i < segments.length) {
391
+ const seg = segments[i];
392
+ if (seg.type === "remove") {
393
+ // Collect consecutive removes
394
+ const removes = [];
395
+ while (i < segments.length && segments[i].type === "remove") {
396
+ removes.push(segments[i]);
399
397
  i++;
400
- }
401
- return out.join("\n") + "\n";
398
+ }
399
+ // Collect consecutive adds
400
+ const adds = [];
401
+ while (i < segments.length && segments[i].type === "add") {
402
+ adds.push(segments[i]);
403
+ i++;
404
+ }
405
+
406
+ // Pair for word-level diff
407
+ const pairCount = Math.min(removes.length, adds.length);
408
+ for (let j = 0; j < removes.length; j++) {
409
+ const r = removes[j];
410
+ const rPrefix = `${String(r.lineNo).padStart(gutterW)} - `;
411
+ if (j < pairCount) {
412
+ const a = adds[j];
413
+ const aPrefix = `${String(a.lineNo).padStart(gutterW)} + `;
414
+ const wd = wordDiff(r.content, a.content);
415
+
416
+ // Removed line with word highlights
417
+ const rPad = Math.max(0, tw - rPrefix.length - r.content.length);
418
+ out.push(d.diffRemovedBg(rPrefix) + renderSegments(wd.old, d.diffWordRemoved, d.diffRemovedBg) + d.diffRemovedBg(" ".repeat(rPad)));
419
+
420
+ // Added line with word highlights
421
+ const aPad = Math.max(0, tw - aPrefix.length - a.content.length);
422
+ out.push(d.diffAddedBg(aPrefix) + renderSegments(wd.new, d.diffWordAdded, d.diffAddedBg) + d.diffAddedBg(" ".repeat(aPad)));
423
+ } else {
424
+ // Unpaired remove
425
+ const raw = rPrefix + r.content;
426
+ const pad = Math.max(0, tw - raw.length);
427
+ out.push(d.diffRemovedBg(raw + " ".repeat(pad)));
428
+ }
429
+ }
430
+
431
+ // Unpaired adds
432
+ for (let j = pairCount; j < adds.length; j++) {
433
+ const a = adds[j];
434
+ const prefix = `${String(a.lineNo).padStart(gutterW)} + `;
435
+ const raw = prefix + a.content;
436
+ const pad = Math.max(0, tw - raw.length);
437
+ out.push(d.diffAddedBg(raw + " ".repeat(pad)));
438
+ }
439
+ continue;
440
+ }
441
+ if (seg.type === "add") {
442
+ // Standalone add (no preceding remove)
443
+ const prefix = `${String(seg.lineNo).padStart(gutterW)} + `;
444
+ const raw = prefix + seg.content;
445
+ const pad = Math.max(0, tw - raw.length);
446
+ out.push(d.diffAddedBg(raw + " ".repeat(pad)));
447
+ i++;
448
+ continue;
449
+ }
450
+
451
+ // Context line — dim line number, plain content, no background
452
+ const prefix = p.tertiary(`${String(seg.lineNo).padStart(gutterW)} `);
453
+ out.push(prefix + seg.content);
454
+ i++;
455
+ }
456
+ return out.join("\n") + "\n";
402
457
  }
458
+
403
459
  // ============================================================================
404
460
  // Bar chart renderer — ```chart code blocks
405
461
  // ============================================================================
462
+
406
463
  function buildBarGradient() {
407
- return [
408
- chalk.hex(colors.purple),
409
- chalk.hex(colors.indigo),
410
- chalk.hex(colors.brand),
411
- chalk.hex(colors.info),
412
- chalk.hex(colors.teal),
413
- chalk.hex(colors.success),
414
- chalk.hex(colors.warning),
415
- chalk.hex(colors.pink),
416
- ];
464
+ return [chalk.hex(colors.purple), chalk.hex(colors.indigo), chalk.hex(colors.brand), chalk.hex(colors.info), chalk.hex(colors.teal), chalk.hex(colors.success), chalk.hex(colors.warning), chalk.hex(colors.pink)];
417
465
  }
418
466
  let barGradient = buildBarGradient();
419
467
  function renderBarChart(code) {
420
- const lines = code.trim().split("\n").filter(l => l.trim());
421
- // Optional title — first line without "label: number" pattern
422
- let title = "";
423
- let dataLines = lines;
424
- if (lines.length > 1 && !/:\s*[$\-+]?[\d,]+/.test(lines[0])) {
425
- title = lines[0].trim();
426
- dataLines = lines.slice(1);
427
- }
428
- // Parse "Label: $1,234.56" or "Label: 42%" or "Label: 1000"
429
- const entries = [];
430
- for (const line of dataLines) {
431
- const m = line.match(/^(.+?):\s*([+\-]?\$?[\d,]+\.?\d*%?)\s*$/);
432
- if (!m)
433
- continue;
434
- const label = m[1].trim();
435
- const raw = m[2].trim();
436
- const value = Math.abs(parseFloat(raw.replace(/[$,%]/g, "")));
437
- if (!isNaN(value))
438
- entries.push({ label, value, raw });
439
- }
440
- if (entries.length === 0)
441
- return code;
442
- const maxVal = Math.max(...entries.map(e => e.value));
443
- const maxRaw = Math.max(...entries.map(e => e.raw.length));
444
- const cw = contentWidth();
445
- // Responsive label width truncate labels to fit
446
- const idealLabelW = Math.max(...entries.map(e => e.label.length));
447
- // Fixed overhead: indent(2) + gap(2) + gap(2) + value(maxRaw) + safety(2)
448
- const fixedOverhead = 2 + 2 + 2 + maxRaw + 2;
449
- const spaceForLabelAndBar = cw - fixedOverhead;
450
- // Allocate: label gets up to half, bar gets the rest (min 4)
451
- const maxLabelW = Math.min(idealLabelW, Math.max(6, Math.floor(spaceForLabelAndBar * 0.4)));
452
- const barWidth = Math.max(4, spaceForLabelAndBar - maxLabelW);
453
- // If even 4-char bars don't fit, fall back to compact list (no bars)
454
- const compact = spaceForLabelAndBar < 12;
455
- const out = [];
456
- if (title) {
457
- const displayTitle = title.length > cw - 4 ? title.slice(0, cw - 5) + "…" : title;
458
- out.push(` ${p.systemBlue.bold(displayTitle)}`);
459
- out.push("");
460
- }
461
- function colorVal(raw) {
462
- return raw.includes("$") ? p.systemGreen(raw)
463
- : raw.includes("%") ? p.systemCyan(raw)
464
- : p.systemMint(raw);
465
- }
466
- if (compact) {
467
- // Compact mode: just "label value" with color dot
468
- for (let i = 0; i < entries.length; i++) {
469
- const e = entries[i];
470
- const color = barGradient[i % barGradient.length];
471
- const labelStr = e.label.length > cw - maxRaw - 8
472
- ? e.label.slice(0, cw - maxRaw - 9) + "…"
473
- : e.label;
474
- out.push(` ${color("●")} ${p.secondary(labelStr)} ${colorVal(e.raw)}`);
475
- }
476
- }
477
- else {
478
- for (let i = 0; i < entries.length; i++) {
479
- const e = entries[i];
480
- const ratio = maxVal > 0 ? e.value / maxVal : 0;
481
- const filled = Math.round(ratio * barWidth);
482
- const color = barGradient[i % barGradient.length];
483
- const labelStr = e.label.length > maxLabelW
484
- ? e.label.slice(0, maxLabelW - 1) + "…"
485
- : e.label;
486
- const label = p.secondary(labelStr.padStart(maxLabelW));
487
- const bar = color("█".repeat(filled)) + chalk.hex("#2C2C2E")("░".repeat(barWidth - filled));
488
- const val = colorVal(e.raw.padStart(maxRaw));
489
- out.push(` ${label} ${bar} ${val}`);
490
- }
491
- }
492
- return "\n" + out.join("\n") + "\n";
468
+ const lines = code.trim().split("\n").filter(l => l.trim());
469
+
470
+ // Optional title first line without "label: number" pattern
471
+ let title = "";
472
+ let dataLines = lines;
473
+ if (lines.length > 1 && !/:\s*[$\-+]?[\d,]+/.test(lines[0])) {
474
+ title = lines[0].trim();
475
+ dataLines = lines.slice(1);
476
+ }
477
+
478
+ // Parse "Label: $1,234.56" or "Label: 42%" or "Label: 1000"
479
+ const entries = [];
480
+ for (const line of dataLines) {
481
+ const m = line.match(/^(.+?):\s*([+\-]?\$?[\d,]+\.?\d*%?)\s*$/);
482
+ if (!m) continue;
483
+ const label = m[1].trim();
484
+ const raw = m[2].trim();
485
+ const value = Math.abs(parseFloat(raw.replace(/[$,%]/g, "")));
486
+ if (!isNaN(value)) entries.push({
487
+ label,
488
+ value,
489
+ raw
490
+ });
491
+ }
492
+ if (entries.length === 0) return code;
493
+ const maxVal = Math.max(...entries.map(e => e.value));
494
+ const maxRaw = Math.max(...entries.map(e => e.raw.length));
495
+ const cw = contentWidth();
496
+
497
+ // Responsive label width truncate labels to fit
498
+ const idealLabelW = Math.max(...entries.map(e => e.label.length));
499
+ // Fixed overhead: indent(2) + gap(2) + gap(2) + value(maxRaw) + safety(2)
500
+ const fixedOverhead = 2 + 2 + 2 + maxRaw + 2;
501
+ const spaceForLabelAndBar = cw - fixedOverhead;
502
+
503
+ // Allocate: label gets up to half, bar gets the rest (min 4)
504
+ const maxLabelW = Math.min(idealLabelW, Math.max(6, Math.floor(spaceForLabelAndBar * 0.4)));
505
+ const barWidth = Math.max(4, spaceForLabelAndBar - maxLabelW);
506
+
507
+ // If even 4-char bars don't fit, fall back to compact list (no bars)
508
+ const compact = spaceForLabelAndBar < 12;
509
+ const out = [];
510
+ if (title) {
511
+ const displayTitle = title.length > cw - 4 ? title.slice(0, cw - 5) + "…" : title;
512
+ out.push(` ${p.systemBlue.bold(displayTitle)}`);
513
+ out.push("");
514
+ }
515
+ function colorVal(raw) {
516
+ return raw.includes("$") ? p.systemGreen(raw) : raw.includes("%") ? p.systemCyan(raw) : p.systemMint(raw);
517
+ }
518
+ if (compact) {
519
+ // Compact mode: just "label value" with color dot
520
+ for (let i = 0; i < entries.length; i++) {
521
+ const e = entries[i];
522
+ const color = barGradient[i % barGradient.length];
523
+ const labelStr = e.label.length > cw - maxRaw - 8 ? e.label.slice(0, cw - maxRaw - 9) + "…" : e.label;
524
+ out.push(` ${color("●")} ${p.secondary(labelStr)} ${colorVal(e.raw)}`);
525
+ }
526
+ } else {
527
+ for (let i = 0; i < entries.length; i++) {
528
+ const e = entries[i];
529
+ const ratio = maxVal > 0 ? e.value / maxVal : 0;
530
+ const filled = Math.round(ratio * barWidth);
531
+ const color = barGradient[i % barGradient.length];
532
+ const labelStr = e.label.length > maxLabelW ? e.label.slice(0, maxLabelW - 1) + "…" : e.label;
533
+ const label = p.secondary(labelStr.padStart(maxLabelW));
534
+ const bar = color("█".repeat(filled)) + chalk.hex("#2C2C2E")("░".repeat(barWidth - filled));
535
+ const val = colorVal(e.raw.padStart(maxRaw));
536
+ out.push(` ${label} ${bar} ${val}`);
537
+ }
538
+ }
539
+ return "\n" + out.join("\n") + "\n";
493
540
  }
541
+
542
+ // ============================================================================
543
+ // Table renderer — polished TUI tables with theme-aware styling
544
+ // ============================================================================
545
+
546
+ // Row tone detection for background tinting
547
+
494
548
  function getRowTone(cells) {
495
- for (const cell of cells) {
496
- const t = cell.trim();
497
- if (/^-\$[\d,]+/.test(t) || /^-\d+\.?\d*%/.test(t))
498
- return "negative";
499
- if (/^\+\d/.test(t) || /^\+\$/.test(t))
500
- return "positive";
501
- if (/^`?[✕✗]/.test(t) || /cancelled|failed|rejected|error|out of stock|low stock/i.test(t))
502
- return "negative";
503
- if (/^`?[✓●]/.test(t) || /completed|received|approved|active|success|paid|published/i.test(t))
504
- return "positive";
505
- }
506
- return "neutral";
549
+ for (const cell of cells) {
550
+ const t = cell.trim();
551
+ if (/^-\$[\d,]+/.test(t) || /^-\d+\.?\d*%/.test(t)) return "negative";
552
+ if (/^\+\d/.test(t) || /^\+\$/.test(t)) return "positive";
553
+ if (/^`?[✕✗]/.test(t) || /cancelled|failed|rejected|error|out of stock|low stock/i.test(t)) return "negative";
554
+ if (/^`?[✓●]/.test(t) || /completed|received|approved|active|success|paid|published/i.test(t)) return "positive";
555
+ }
556
+ return "neutral";
507
557
  }
558
+
508
559
  /** Detect if a column is numeric (for right-alignment) */
509
560
  function isNumericColumn(rows, colIndex) {
510
- let numericCount = 0;
511
- let total = 0;
512
- for (const row of rows) {
513
- const val = (row[colIndex] || "").trim();
514
- if (!val)
515
- continue;
516
- total++;
517
- if (/^[+\-]?\$?[\d,]+\.?\d*%?$/.test(val))
518
- numericCount++;
519
- }
520
- return total > 0 && numericCount / total > 0.5;
561
+ let numericCount = 0;
562
+ let total = 0;
563
+ for (const row of rows) {
564
+ const val = (row[colIndex] || "").trim();
565
+ if (!val) continue;
566
+ total++;
567
+ if (/^[+\-]?\$?[\d,]+\.?\d*%?$/.test(val)) numericCount++;
568
+ }
569
+ return total > 0 && numericCount / total > 0.5;
521
570
  }
571
+
522
572
  /** Blend two hex colors by ratio (0 = colorA, 1 = colorB) */
523
573
  function blendHex(a, b, ratio) {
524
- const parse = (h) => {
525
- const c = h.replace("#", "");
526
- return [parseInt(c.slice(0, 2), 16), parseInt(c.slice(2, 4), 16), parseInt(c.slice(4, 6), 16)];
527
- };
528
- const [ar, ag, ab] = parse(a);
529
- const [br, bg, bb] = parse(b);
530
- const r = Math.round(ar + (br - ar) * ratio);
531
- const g = Math.round(ag + (bg - ag) * ratio);
532
- const bv = Math.round(ab + (bb - ab) * ratio);
533
- return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${bv.toString(16).padStart(2, "0")}`;
574
+ const parse = h => {
575
+ const c = h.replace("#", "");
576
+ return [parseInt(c.slice(0, 2), 16), parseInt(c.slice(2, 4), 16), parseInt(c.slice(4, 6), 16)];
577
+ };
578
+ const [ar, ag, ab] = parse(a);
579
+ const [br, bg, bb] = parse(b);
580
+ const r = Math.round(ar + (br - ar) * ratio);
581
+ const g = Math.round(ag + (bg - ag) * ratio);
582
+ const bv = Math.round(ab + (bb - ab) * ratio);
583
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${bv.toString(16).padStart(2, "0")}`;
534
584
  }
535
585
  function colorizeCell(val, isHeader) {
536
- const trimmed = val.trim();
537
- if (!trimmed)
538
- return p.text("");
539
- if (isHeader)
540
- return p.systemBlue.bold(trimmed);
541
- // Badge format: `✓ status` or `◆ status` or `○ status` or `✕ status`
542
- const badgeMatch = trimmed.match(/^`([✓●◆○✕◦])\s+(.+)`$/);
543
- if (badgeMatch) {
544
- const [, icon, label] = badgeMatch;
545
- if (icon === "" || icon === "●")
546
- return p.systemGreen(`${icon} ${label}`);
547
- if (icon === "")
548
- return p.systemCyan(`${icon} ${label}`);
549
- if (icon === "○")
550
- return p.systemOrange(`${icon} ${label}`);
551
- if (icon === "✕")
552
- return p.systemRed(`${icon} ${label}`);
553
- return p.secondary(`${icon} ${label}`);
554
- }
555
- // Inline code (UUID, SKU, transfer number)
556
- if (trimmed.startsWith("`") && trimmed.endsWith("`")) {
557
- return p.systemPurple(trimmed.slice(1, -1));
558
- }
559
- // Bold text
560
- if (trimmed.startsWith("**") && trimmed.endsWith("**")) {
561
- return p.text.bold(trimmed.slice(2, -2));
562
- }
563
- // Negative values → red
564
- if (/^-\$?[\d,]+\.?\d*$/.test(trimmed) || /^-\d+\.?\d*%$/.test(trimmed)) {
565
- return p.systemRed(trimmed);
566
- }
567
- // Positive financial → green
568
- if (/^\+?\$[\d,]+\.?\d*$/.test(trimmed) || /^\$[\d,]+\.?\d*$/.test(trimmed)) {
569
- return p.systemGreen(trimmed);
570
- }
571
- // Percentages → cyan
572
- if (/^\d+\.?\d*%$/.test(trimmed)) {
573
- return p.systemCyan(trimmed);
574
- }
575
- // Plain numbers → mint
576
- if (/^[\d,]+\.?\d*$/.test(trimmed)) {
577
- return p.systemMint(trimmed);
578
- }
579
- // Status words
580
- if (/^(active|success|complete|approved|in stock|available)/i.test(trimmed)) {
581
- return p.systemGreen(trimmed);
582
- }
583
- if (/^(inactive|error|failed|cancelled|out of stock|low|overdue|expired)/i.test(trimmed)) {
584
- return p.systemRed(trimmed);
585
- }
586
- if (/^(pending|draft|processing)/i.test(trimmed)) {
587
- return p.systemOrange(trimmed);
588
- }
589
- return p.text(trimmed);
586
+ const trimmed = val.trim();
587
+ if (!trimmed) return p.text("");
588
+ if (isHeader) return p.systemBlue.bold(trimmed);
589
+
590
+ // Badge format: `✓ status` or `◆ status` or `○ status` or `✕ status`
591
+ const badgeMatch = trimmed.match(/^`([✓●◆○✕◦])\s+(.+)`$/);
592
+ if (badgeMatch) {
593
+ const [, icon, label] = badgeMatch;
594
+ if (icon === "✓" || icon === "●") return p.systemGreen(`${icon} ${label}`);
595
+ if (icon === "") return p.systemCyan(`${icon} ${label}`);
596
+ if (icon === "○") return p.systemOrange(`${icon} ${label}`);
597
+ if (icon === "") return p.systemRed(`${icon} ${label}`);
598
+ return p.secondary(`${icon} ${label}`);
599
+ }
600
+
601
+ // Inline code (UUID, SKU, transfer number)
602
+ if (trimmed.startsWith("`") && trimmed.endsWith("`")) {
603
+ return p.systemPurple(trimmed.slice(1, -1));
604
+ }
605
+
606
+ // Bold text
607
+ if (trimmed.startsWith("**") && trimmed.endsWith("**")) {
608
+ return p.text.bold(trimmed.slice(2, -2));
609
+ }
610
+
611
+ // Negative values → red
612
+ if (/^-\$?[\d,]+\.?\d*$/.test(trimmed) || /^-\d+\.?\d*%$/.test(trimmed)) {
613
+ return p.systemRed(trimmed);
614
+ }
615
+ // Positive financial → green
616
+ if (/^\+?\$[\d,]+\.?\d*$/.test(trimmed) || /^\$[\d,]+\.?\d*$/.test(trimmed)) {
617
+ return p.systemGreen(trimmed);
618
+ }
619
+ // Percentages → cyan
620
+ if (/^\d+\.?\d*%$/.test(trimmed)) {
621
+ return p.systemCyan(trimmed);
622
+ }
623
+ // Plain numbers → mint
624
+ if (/^[\d,]+\.?\d*$/.test(trimmed)) {
625
+ return p.systemMint(trimmed);
626
+ }
627
+ // Status words
628
+ if (/^(active|success|complete|approved|in stock|available)/i.test(trimmed)) {
629
+ return p.systemGreen(trimmed);
630
+ }
631
+ if (/^(inactive|error|failed|cancelled|out of stock|low|overdue|expired)/i.test(trimmed)) {
632
+ return p.systemRed(trimmed);
633
+ }
634
+ if (/^(pending|draft|processing)/i.test(trimmed)) {
635
+ return p.systemOrange(trimmed);
636
+ }
637
+ return p.text(trimmed);
590
638
  }
591
639
  function renderTable(token) {
592
- function getCellText(cell) {
593
- if (!cell)
594
- return "";
595
- if (typeof cell === "string")
596
- return cell;
597
- if (cell.text !== undefined)
598
- return String(cell.text);
599
- if (cell.tokens) {
600
- return cell.tokens.map((t) => t.raw || t.text || "").join("");
601
- }
602
- return String(cell);
603
- }
604
- const headers = (token.header || []).map((h) => getCellText(h));
605
- const rows = (token.rows || []).map((row) => row.map((cell) => getCellText(cell)));
606
- if (headers.length === 0)
607
- return "";
608
- const cw = contentWidth();
609
- const N = headers.length;
610
- // ── Check if box table can fit ──
611
- // Minimum box table width: indent(2) + borders(N+1) + N * (minCol + 2 padding)
612
- const MIN_COL = 3;
613
- const minBoxWidth = 2 + (N + 1) + N * (MIN_COL + 2);
614
- if (minBoxWidth > cw) {
615
- // ── Card layout — graceful fallback for narrow terminals ──
616
- return renderTableCards(headers, rows, cw);
617
- }
618
- // ── Box table layout ──
619
- const overhead = 2 + 1 + (N - 1) + 1 + (N * 2);
620
- const availableForContent = cw - overhead;
621
- const minCol = cw < 70 ? MIN_COL : cw < 90 ? 5 : 6;
622
- const maxPerCol = Math.max(minCol, Math.floor(availableForContent / N));
623
- // Detect numeric columns for right-alignment
624
- const numericCols = headers.map((_, i) => isNumericColumn(rows, i));
625
- // Size columns: fit content up to maxPerCol, respect minCol
626
- const colWidths = headers.map((h, i) => {
627
- const dataMax = rows.reduce((max, row) => Math.max(max, (row[i] || "").length), 0);
628
- return Math.min(maxPerCol, Math.max(minCol, h.length, dataMax) + 2);
629
- });
630
- // Double-check total width won't overflow (defensive)
631
- const totalWidth = 2 + 1 + colWidths.reduce((s, w) => s + w + 2, 0) + (N - 1) + 1;
632
- if (totalWidth > cw) {
633
- // Shrink largest columns until we fit
634
- let excess = totalWidth - cw;
635
- while (excess > 0) {
636
- const maxIdx = colWidths.indexOf(Math.max(...colWidths));
637
- if (colWidths[maxIdx] <= MIN_COL)
638
- break; // can't shrink further
639
- colWidths[maxIdx]--;
640
- excess--;
641
- }
642
- }
643
- // ── Colors ──
644
- const borderColor = blendHex(colors.separator, colors.brand, 0.25);
645
- const border = chalk.hex(borderColor);
646
- const headerBg = chalk.bgHex(blendHex(colors.panel, colors.brand, 0.15));
647
- const evenRowBg = chalk.bgHex(blendHex(colors.panel, colors.text, 0.04));
648
- const oddRowBg = chalk.bgHex(colors.panel);
649
- const positiveBg = chalk.bgHex(blendHex(colors.panel, colors.success, 0.12));
650
- const negativeBg = chalk.bgHex(blendHex(colors.panel, colors.error, 0.12));
651
- const out = [];
652
- // Top border
653
- out.push(border(" ╭" + colWidths.map((w) => "─".repeat(w + 2)).join("┬") + "╮"));
654
- // Header row
655
- const hdrCells = headers.map((h, i) => {
656
- const display = h.length > colWidths[i] ? h.slice(0, colWidths[i] - 1) + "…" : h;
657
- const padded = numericCols[i] ? display.padStart(colWidths[i]) : display.padEnd(colWidths[i]);
658
- return headerBg(" " + chalk.hex(colors.brand).bold(padded) + " ");
640
+ function getCellText(cell) {
641
+ if (!cell) return "";
642
+ if (typeof cell === "string") return cell;
643
+ if (cell.text !== undefined) return String(cell.text);
644
+ if (cell.tokens) {
645
+ return cell.tokens.map(t => t.raw || t.text || "").join("");
646
+ }
647
+ return String(cell);
648
+ }
649
+ const headers = (token.header || []).map(h => getCellText(h));
650
+ const rows = (token.rows || []).map(row => row.map(cell => getCellText(cell)));
651
+ if (headers.length === 0) return "";
652
+ const cw = contentWidth();
653
+ const N = headers.length;
654
+
655
+ // ── Check if box table can fit ──
656
+ // Minimum box table width: indent(2) + borders(N+1) + N * (minCol + 2 padding)
657
+ const MIN_COL = 3;
658
+ const minBoxWidth = 2 + (N + 1) + N * (MIN_COL + 2);
659
+ if (minBoxWidth > cw) {
660
+ // ── Card layout — graceful fallback for narrow terminals ──
661
+ return renderTableCards(headers, rows, cw);
662
+ }
663
+
664
+ // ── Box table layout ──
665
+ const overhead = 2 + 1 + (N - 1) + 1 + N * 2;
666
+ const availableForContent = cw - overhead;
667
+ const minCol = cw < 70 ? MIN_COL : cw < 90 ? 5 : 6;
668
+ const maxPerCol = Math.max(minCol, Math.floor(availableForContent / N));
669
+
670
+ // Detect numeric columns for right-alignment
671
+ const numericCols = headers.map((_, i) => isNumericColumn(rows, i));
672
+
673
+ // Size columns: fit content up to maxPerCol, respect minCol
674
+ const colWidths = headers.map((h, i) => {
675
+ const dataMax = rows.reduce((max, row) => Math.max(max, (row[i] || "").length), 0);
676
+ return Math.min(maxPerCol, Math.max(minCol, h.length, dataMax) + 2);
677
+ });
678
+
679
+ // Double-check total width won't overflow (defensive)
680
+ const totalWidth = 2 + 1 + colWidths.reduce((s, w) => s + w + 2, 0) + (N - 1) + 1;
681
+ if (totalWidth > cw) {
682
+ // Shrink largest columns until we fit
683
+ let excess = totalWidth - cw;
684
+ while (excess > 0) {
685
+ const maxIdx = colWidths.indexOf(Math.max(...colWidths));
686
+ if (colWidths[maxIdx] <= MIN_COL) break; // can't shrink further
687
+ colWidths[maxIdx]--;
688
+ excess--;
689
+ }
690
+ }
691
+
692
+ // ── Colors ──
693
+ const borderColor = blendHex(colors.separator, colors.brand, 0.25);
694
+ const border = chalk.hex(borderColor);
695
+ const headerBg = chalk.bgHex(blendHex(colors.panel, colors.brand, 0.15));
696
+ const evenRowBg = chalk.bgHex(blendHex(colors.panel, colors.text, 0.04));
697
+ const oddRowBg = chalk.bgHex(colors.panel);
698
+ const positiveBg = chalk.bgHex(blendHex(colors.panel, colors.success, 0.12));
699
+ const negativeBg = chalk.bgHex(blendHex(colors.panel, colors.error, 0.12));
700
+ const out = [];
701
+
702
+ // Top border
703
+ out.push(border(" ╭" + colWidths.map(w => "─".repeat(w + 2)).join("┬") + "╮"));
704
+
705
+ // Header row
706
+ const hdrCells = headers.map((h, i) => {
707
+ const display = h.length > colWidths[i] ? h.slice(0, colWidths[i] - 1) + "…" : h;
708
+ const padded = numericCols[i] ? display.padStart(colWidths[i]) : display.padEnd(colWidths[i]);
709
+ return headerBg(" " + chalk.hex(colors.brand).bold(padded) + " ");
710
+ }).join(border("│"));
711
+ out.push(border(" │") + hdrCells + border("│"));
712
+
713
+ // Header divider
714
+ out.push(border(" ├" + colWidths.map(w => "━".repeat(w + 2)).join("┿") + "┤"));
715
+
716
+ // Data rows
717
+ for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
718
+ const row = rows[rowIdx];
719
+ const tone = getRowTone(row);
720
+ const rowBg = tone === "positive" ? positiveBg : tone === "negative" ? negativeBg : rowIdx % 2 === 0 ? evenRowBg : oddRowBg;
721
+ const cells = headers.map((_, i) => {
722
+ const raw = row[i] || "";
723
+ const display = raw.length > colWidths[i] ? raw.slice(0, colWidths[i] - 1) + "…" : raw;
724
+ const colored = colorizeCell(display, false);
725
+ const extraPad = Math.max(0, colWidths[i] - display.length);
726
+ if (numericCols[i]) {
727
+ return rowBg(" ".repeat(extraPad) + " " + colored + " ");
728
+ }
729
+ return rowBg(" " + colored + " ".repeat(extraPad) + " ");
659
730
  }).join(border("│"));
660
- out.push(border(" │") + hdrCells + border("│"));
661
- // Header divider
662
- out.push(border(" ├" + colWidths.map((w) => "━".repeat(w + 2)).join("┿") + "┤"));
663
- // Data rows
664
- for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
665
- const row = rows[rowIdx];
666
- const tone = getRowTone(row);
667
- const rowBg = tone === "positive" ? positiveBg
668
- : tone === "negative" ? negativeBg
669
- : rowIdx % 2 === 0 ? evenRowBg : oddRowBg;
670
- const cells = headers.map((_, i) => {
671
- const raw = row[i] || "";
672
- const display = raw.length > colWidths[i] ? raw.slice(0, colWidths[i] - 1) + "…" : raw;
673
- const colored = colorizeCell(display, false);
674
- const extraPad = Math.max(0, colWidths[i] - display.length);
675
- if (numericCols[i]) {
676
- return rowBg(" ".repeat(extraPad) + " " + colored + " ");
677
- }
678
- return rowBg(" " + colored + " ".repeat(extraPad) + " ");
679
- }).join(border("│"));
680
- out.push(border(" │") + cells + border("│"));
681
- }
682
- // Bottom border
683
- out.push(border(" ╰" + colWidths.map((w) => "─".repeat(w + 2)).join("┴") + "╯"));
684
- return "\n" + out.join("\n") + "\n";
731
+ out.push(border(" │") + cells + border("│"));
732
+ }
733
+
734
+ // Bottom border
735
+ out.push(border(" ╰" + colWidths.map(w => "─".repeat(w + 2)).join("┴") + "╯"));
736
+ return "\n" + out.join("\n") + "\n";
685
737
  }
738
+
686
739
  /** Card layout fallback — renders each row as a key: value block. Never overflows. */
687
740
  function renderTableCards(headers, rows, cw) {
688
- const border = chalk.hex(blendHex(colors.separator, colors.brand, 0.25));
689
- const out = [];
690
- const innerW = Math.max(8, cw - 6); // indent(2) + border(2) + padding(2)
691
- const divider = border(" " + "─".repeat(innerW + 2));
692
- // Find longest header for label alignment
693
- const maxHdrLen = Math.min(Math.max(...headers.map(h => h.length)), Math.floor(innerW * 0.4));
694
- out.push(divider);
695
- for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
696
- const row = rows[rowIdx];
697
- if (rowIdx > 0)
698
- out.push(divider);
699
- for (let i = 0; i < headers.length; i++) {
700
- const hdr = headers[i].length > maxHdrLen
701
- ? headers[i].slice(0, maxHdrLen - 1) + ""
702
- : headers[i];
703
- const val = row[i] || "";
704
- const maxValLen = innerW - maxHdrLen - 3; // " label value"
705
- const displayVal = val.length > maxValLen
706
- ? val.slice(0, maxValLen - 1) + "…"
707
- : val;
708
- const labelStr = p.tertiary(hdr.padEnd(maxHdrLen));
709
- const valStr = colorizeCell(displayVal, false);
710
- out.push(` ${labelStr} ${valStr}`);
711
- }
712
- }
713
- out.push(divider);
714
- return "\n" + out.join("\n") + "\n";
741
+ const border = chalk.hex(blendHex(colors.separator, colors.brand, 0.25));
742
+ const out = [];
743
+ const innerW = Math.max(8, cw - 6); // indent(2) + border(2) + padding(2)
744
+ const divider = border(" " + "─".repeat(innerW + 2));
745
+
746
+ // Find longest header for label alignment
747
+ const maxHdrLen = Math.min(Math.max(...headers.map(h => h.length)), Math.floor(innerW * 0.4));
748
+ out.push(divider);
749
+ for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
750
+ const row = rows[rowIdx];
751
+ if (rowIdx > 0) out.push(divider);
752
+ for (let i = 0; i < headers.length; i++) {
753
+ const hdr = headers[i].length > maxHdrLen ? headers[i].slice(0, maxHdrLen - 1) + "…" : headers[i];
754
+ const val = row[i] || "";
755
+ const maxValLen = innerW - maxHdrLen - 3; // " label value"
756
+ const displayVal = val.length > maxValLen ? val.slice(0, maxValLen - 1) + "" : val;
757
+ const labelStr = p.tertiary(hdr.padEnd(maxHdrLen));
758
+ const valStr = colorizeCell(displayVal, false);
759
+ out.push(` ${labelStr} ${valStr}`);
760
+ }
761
+ }
762
+ out.push(divider);
763
+ return "\n" + out.join("\n") + "\n";
715
764
  }
765
+
716
766
  // ============================================================================
717
767
  // Rebuild — called on theme switch to refresh all chalk instances
718
768
  // ============================================================================
769
+
719
770
  export function rebuildMarkdownRenderer() {
720
- p = buildPalette();
721
- d = buildDiffStyles();
722
- barGradient = buildBarGradient();
723
- md = buildMarkedInstance();
771
+ p = buildPalette();
772
+ d = buildDiffStyles();
773
+ barGradient = buildBarGradient();
774
+ md = buildMarkedInstance();
724
775
  }
776
+
725
777
  // Register rebuild callback with theme manager
726
778
  setRebuildCallback(rebuildMarkdownRenderer);
779
+
727
780
  // ============================================================================
728
781
  // Streaming fence closure — state-tracking approach
729
782
  // ============================================================================
783
+
730
784
  /** Extract text outside fenced code blocks */
731
785
  function getNonFencedText(input) {
732
- const lines = input.split("\n");
733
- const parts = [];
734
- let inFence = false;
735
- for (const line of lines) {
736
- if (line.trimStart().startsWith("```")) {
737
- inFence = !inFence;
738
- continue;
739
- }
740
- if (!inFence)
741
- parts.push(line);
742
- }
743
- return parts.join("\n");
786
+ const lines = input.split("\n");
787
+ const parts = [];
788
+ let inFence = false;
789
+ for (const line of lines) {
790
+ if (line.trimStart().startsWith("```")) {
791
+ inFence = !inFence;
792
+ continue;
793
+ }
794
+ if (!inFence) parts.push(line);
795
+ }
796
+ return parts.join("\n");
744
797
  }
798
+
745
799
  /** Strip complete inline code spans from text */
746
800
  function getNonCodeText(t) {
747
- return t.replace(/``[^`]*``/g, "").replace(/`[^`\n]*`/g, "");
801
+ return t.replace(/``[^`]*``/g, "").replace(/`[^`\n]*`/g, "");
748
802
  }
803
+
749
804
  /**
750
805
  * Close incomplete markdown fences for safe streaming rendering.
751
806
  * State-tracking approach: handles nested fences, escaped markers, double-backtick spans.
752
807
  */
753
808
  export function closeIncompleteFences(input) {
754
- let result = input;
755
- // 1. Code fences — walk lines, track open/close state
756
- let inFence = false;
757
- for (const line of result.split("\n")) {
758
- const trimmed = line.trimStart();
759
- if (trimmed.startsWith("```")) {
760
- inFence = !inFence;
761
- }
762
- }
763
- if (inFence) {
764
- result += "\n```";
765
- }
766
- // 2. For inline markers, only examine text OUTSIDE fenced code blocks
767
- const outside = getNonFencedText(result);
768
- // 3. Inline backticks remove escaped, remove complete spans, count remainder
769
- let forBacktick = outside.replace(/\\`/g, "");
770
- forBacktick = forBacktick.replace(/``[^`]*``/g, ""); // double-backtick spans
771
- forBacktick = forBacktick.replace(/`[^`\n]*`/g, ""); // single-backtick spans
772
- const unmatched = (forBacktick.match(/`/g) || []).length;
773
- if (unmatched % 2 !== 0) {
774
- result += "`";
775
- }
776
- // 4. Bold count ** in non-code text
777
- const forBold = getNonCodeText(outside);
778
- const boldCount = (forBold.match(/\*\*/g) || []).length;
779
- if (boldCount % 2 !== 0) {
780
- result += "**";
781
- }
782
- // 5. Italic — count standalone * (not part of **) with escape awareness
783
- const forItalic = forBold.replace(/\*\*/g, "");
784
- const italicCount = (forItalic.match(/(?<!\\)\*/g) || []).length;
785
- if (italicCount % 2 !== 0) {
786
- result += "*";
787
- }
788
- return result;
809
+ let result = input;
810
+
811
+ // 1. Code fences — walk lines, track open/close state
812
+ let inFence = false;
813
+ for (const line of result.split("\n")) {
814
+ const trimmed = line.trimStart();
815
+ if (trimmed.startsWith("```")) {
816
+ inFence = !inFence;
817
+ }
818
+ }
819
+ if (inFence) {
820
+ result += "\n```";
821
+ }
822
+
823
+ // 2. For inline markers, only examine text OUTSIDE fenced code blocks
824
+ const outside = getNonFencedText(result);
825
+
826
+ // 3. Inline backticks — remove escaped, remove complete spans, count remainder
827
+ let forBacktick = outside.replace(/\\`/g, "");
828
+ forBacktick = forBacktick.replace(/``[^`]*``/g, ""); // double-backtick spans
829
+ forBacktick = forBacktick.replace(/`[^`\n]*`/g, ""); // single-backtick spans
830
+ const unmatched = (forBacktick.match(/`/g) || []).length;
831
+ if (unmatched % 2 !== 0) {
832
+ result += "`";
833
+ }
834
+
835
+ // 4. Bold — count ** in non-code text
836
+ const forBold = getNonCodeText(outside);
837
+ const boldCount = (forBold.match(/\*\*/g) || []).length;
838
+ if (boldCount % 2 !== 0) {
839
+ result += "**";
840
+ }
841
+
842
+ // 5. Italic — count standalone * (not part of **) with escape awareness
843
+ const forItalic = forBold.replace(/\*\*/g, "");
844
+ const italicCount = (forItalic.match(/(?<!\\)\*/g) || []).length;
845
+ if (italicCount % 2 !== 0) {
846
+ result += "*";
847
+ }
848
+ return result;
789
849
  }
850
+
790
851
  /**
791
852
  * Render markdown to ANSI-styled terminal string.
792
853
  * Optionally applies streaming-safe fence closing.
793
854
  */
794
855
  export function renderMarkdown(input, streaming = false) {
795
- const safe = streaming ? closeIncompleteFences(input) : input;
796
- const result = md.parse(safe);
797
- return result.replace(/\n+$/, "");
856
+ const safe = streaming ? closeIncompleteFences(input) : input;
857
+ const result = md.parse(safe);
858
+ return result.replace(/\n+$/, "");
798
859
  }
860
+ //# sourceMappingURL=markdown.js.map