@amodalai/amodal 0.1.2

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 (511) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +42 -0
  4. package/dist/src/auth/index.d.ts +13 -0
  5. package/dist/src/auth/index.d.ts.map +1 -0
  6. package/dist/src/auth/index.js +10 -0
  7. package/dist/src/auth/index.js.map +1 -0
  8. package/dist/src/auth/oauth2.d.ts +51 -0
  9. package/dist/src/auth/oauth2.d.ts.map +1 -0
  10. package/dist/src/auth/oauth2.js +196 -0
  11. package/dist/src/auth/oauth2.js.map +1 -0
  12. package/dist/src/auth/prompt.d.ts +21 -0
  13. package/dist/src/auth/prompt.d.ts.map +1 -0
  14. package/dist/src/auth/prompt.js +81 -0
  15. package/dist/src/auth/prompt.js.map +1 -0
  16. package/dist/src/auth/test-connection.d.ts +27 -0
  17. package/dist/src/auth/test-connection.d.ts.map +1 -0
  18. package/dist/src/auth/test-connection.js +153 -0
  19. package/dist/src/auth/test-connection.js.map +1 -0
  20. package/dist/src/auth/types.d.ts +32 -0
  21. package/dist/src/auth/types.d.ts.map +1 -0
  22. package/dist/src/auth/types.js +7 -0
  23. package/dist/src/auth/types.js.map +1 -0
  24. package/dist/src/commands/audit.d.ts +18 -0
  25. package/dist/src/commands/audit.d.ts.map +1 -0
  26. package/dist/src/commands/audit.js +86 -0
  27. package/dist/src/commands/audit.js.map +1 -0
  28. package/dist/src/commands/automations.d.ts +28 -0
  29. package/dist/src/commands/automations.d.ts.map +1 -0
  30. package/dist/src/commands/automations.js +179 -0
  31. package/dist/src/commands/automations.js.map +1 -0
  32. package/dist/src/commands/build-manifest-types.d.ts +33 -0
  33. package/dist/src/commands/build-manifest-types.d.ts.map +1 -0
  34. package/dist/src/commands/build-manifest-types.js +30 -0
  35. package/dist/src/commands/build-manifest-types.js.map +1 -0
  36. package/dist/src/commands/build-tools.d.ts +33 -0
  37. package/dist/src/commands/build-tools.d.ts.map +1 -0
  38. package/dist/src/commands/build-tools.js +237 -0
  39. package/dist/src/commands/build-tools.js.map +1 -0
  40. package/dist/src/commands/build.d.ts +23 -0
  41. package/dist/src/commands/build.d.ts.map +1 -0
  42. package/dist/src/commands/build.js +120 -0
  43. package/dist/src/commands/build.js.map +1 -0
  44. package/dist/src/commands/chat.d.ts +26 -0
  45. package/dist/src/commands/chat.d.ts.map +1 -0
  46. package/dist/src/commands/chat.js +123 -0
  47. package/dist/src/commands/chat.js.map +1 -0
  48. package/dist/src/commands/connect.d.ts +18 -0
  49. package/dist/src/commands/connect.d.ts.map +1 -0
  50. package/dist/src/commands/connect.js +198 -0
  51. package/dist/src/commands/connect.js.map +1 -0
  52. package/dist/src/commands/deploy.d.ts +20 -0
  53. package/dist/src/commands/deploy.d.ts.map +1 -0
  54. package/dist/src/commands/deploy.js +137 -0
  55. package/dist/src/commands/deploy.js.map +1 -0
  56. package/dist/src/commands/deployments.d.ts +17 -0
  57. package/dist/src/commands/deployments.d.ts.map +1 -0
  58. package/dist/src/commands/deployments.js +77 -0
  59. package/dist/src/commands/deployments.js.map +1 -0
  60. package/dist/src/commands/dev.d.ts +17 -0
  61. package/dist/src/commands/dev.d.ts.map +1 -0
  62. package/dist/src/commands/dev.js +109 -0
  63. package/dist/src/commands/dev.js.map +1 -0
  64. package/dist/src/commands/diff.d.ts +19 -0
  65. package/dist/src/commands/diff.d.ts.map +1 -0
  66. package/dist/src/commands/diff.js +120 -0
  67. package/dist/src/commands/diff.js.map +1 -0
  68. package/dist/src/commands/docker.d.ts +21 -0
  69. package/dist/src/commands/docker.d.ts.map +1 -0
  70. package/dist/src/commands/docker.js +215 -0
  71. package/dist/src/commands/docker.js.map +1 -0
  72. package/dist/src/commands/eval.d.ts +20 -0
  73. package/dist/src/commands/eval.d.ts.map +1 -0
  74. package/dist/src/commands/eval.js +236 -0
  75. package/dist/src/commands/eval.js.map +1 -0
  76. package/dist/src/commands/experiment.d.ts +21 -0
  77. package/dist/src/commands/experiment.d.ts.map +1 -0
  78. package/dist/src/commands/experiment.js +133 -0
  79. package/dist/src/commands/experiment.js.map +1 -0
  80. package/dist/src/commands/index.d.ts +10 -0
  81. package/dist/src/commands/index.d.ts.map +1 -0
  82. package/dist/src/commands/index.js +75 -0
  83. package/dist/src/commands/index.js.map +1 -0
  84. package/dist/src/commands/init.d.ts +17 -0
  85. package/dist/src/commands/init.d.ts.map +1 -0
  86. package/dist/src/commands/init.js +73 -0
  87. package/dist/src/commands/init.js.map +1 -0
  88. package/dist/src/commands/inspect.d.ts +22 -0
  89. package/dist/src/commands/inspect.d.ts.map +1 -0
  90. package/dist/src/commands/inspect.js +131 -0
  91. package/dist/src/commands/inspect.js.map +1 -0
  92. package/dist/src/commands/install-pkg.d.ts +29 -0
  93. package/dist/src/commands/install-pkg.d.ts.map +1 -0
  94. package/dist/src/commands/install-pkg.js +202 -0
  95. package/dist/src/commands/install-pkg.js.map +1 -0
  96. package/dist/src/commands/link.d.ts +32 -0
  97. package/dist/src/commands/link.d.ts.map +1 -0
  98. package/dist/src/commands/link.js +227 -0
  99. package/dist/src/commands/link.js.map +1 -0
  100. package/dist/src/commands/list.d.ts +19 -0
  101. package/dist/src/commands/list.d.ts.map +1 -0
  102. package/dist/src/commands/list.js +78 -0
  103. package/dist/src/commands/list.js.map +1 -0
  104. package/dist/src/commands/login.d.ts +31 -0
  105. package/dist/src/commands/login.d.ts.map +1 -0
  106. package/dist/src/commands/login.js +205 -0
  107. package/dist/src/commands/login.js.map +1 -0
  108. package/dist/src/commands/promote.d.ts +16 -0
  109. package/dist/src/commands/promote.d.ts.map +1 -0
  110. package/dist/src/commands/promote.js +55 -0
  111. package/dist/src/commands/promote.js.map +1 -0
  112. package/dist/src/commands/publish.d.ts +18 -0
  113. package/dist/src/commands/publish.d.ts.map +1 -0
  114. package/dist/src/commands/publish.js +122 -0
  115. package/dist/src/commands/publish.js.map +1 -0
  116. package/dist/src/commands/rollback.d.ts +17 -0
  117. package/dist/src/commands/rollback.d.ts.map +1 -0
  118. package/dist/src/commands/rollback.js +62 -0
  119. package/dist/src/commands/rollback.js.map +1 -0
  120. package/dist/src/commands/search.d.ts +20 -0
  121. package/dist/src/commands/search.d.ts.map +1 -0
  122. package/dist/src/commands/search.js +133 -0
  123. package/dist/src/commands/search.js.map +1 -0
  124. package/dist/src/commands/secrets.d.ts +20 -0
  125. package/dist/src/commands/secrets.d.ts.map +1 -0
  126. package/dist/src/commands/secrets.js +137 -0
  127. package/dist/src/commands/secrets.js.map +1 -0
  128. package/dist/src/commands/serve.d.ts +23 -0
  129. package/dist/src/commands/serve.d.ts.map +1 -0
  130. package/dist/src/commands/serve.js +144 -0
  131. package/dist/src/commands/serve.js.map +1 -0
  132. package/dist/src/commands/status.d.ts +16 -0
  133. package/dist/src/commands/status.d.ts.map +1 -0
  134. package/dist/src/commands/status.js +83 -0
  135. package/dist/src/commands/status.js.map +1 -0
  136. package/dist/src/commands/sync.d.ts +21 -0
  137. package/dist/src/commands/sync.d.ts.map +1 -0
  138. package/dist/src/commands/sync.js +94 -0
  139. package/dist/src/commands/sync.js.map +1 -0
  140. package/dist/src/commands/test-query.d.ts +19 -0
  141. package/dist/src/commands/test-query.d.ts.map +1 -0
  142. package/dist/src/commands/test-query.js +116 -0
  143. package/dist/src/commands/test-query.js.map +1 -0
  144. package/dist/src/commands/uninstall.d.ts +19 -0
  145. package/dist/src/commands/uninstall.d.ts.map +1 -0
  146. package/dist/src/commands/uninstall.js +84 -0
  147. package/dist/src/commands/uninstall.js.map +1 -0
  148. package/dist/src/commands/update.d.ts +21 -0
  149. package/dist/src/commands/update.d.ts.map +1 -0
  150. package/dist/src/commands/update.js +145 -0
  151. package/dist/src/commands/update.js.map +1 -0
  152. package/dist/src/commands/validate.d.ts +19 -0
  153. package/dist/src/commands/validate.d.ts.map +1 -0
  154. package/dist/src/commands/validate.js +114 -0
  155. package/dist/src/commands/validate.js.map +1 -0
  156. package/dist/src/fixtures/incident-response.d.ts +91 -0
  157. package/dist/src/fixtures/incident-response.d.ts.map +1 -0
  158. package/dist/src/fixtures/incident-response.js +208 -0
  159. package/dist/src/fixtures/incident-response.js.map +1 -0
  160. package/dist/src/main.d.ts +8 -0
  161. package/dist/src/main.d.ts.map +1 -0
  162. package/dist/src/main.js +30 -0
  163. package/dist/src/main.js.map +1 -0
  164. package/dist/src/shared/platform-client.d.ts +92 -0
  165. package/dist/src/shared/platform-client.d.ts.map +1 -0
  166. package/dist/src/shared/platform-client.js +155 -0
  167. package/dist/src/shared/platform-client.js.map +1 -0
  168. package/dist/src/shared/repo-discovery.d.ts +11 -0
  169. package/dist/src/shared/repo-discovery.d.ts.map +1 -0
  170. package/dist/src/shared/repo-discovery.js +33 -0
  171. package/dist/src/shared/repo-discovery.js.map +1 -0
  172. package/dist/src/templates/compose-template.d.ts +10 -0
  173. package/dist/src/templates/compose-template.d.ts.map +1 -0
  174. package/dist/src/templates/compose-template.js +30 -0
  175. package/dist/src/templates/compose-template.js.map +1 -0
  176. package/dist/src/templates/config-template.d.ts +14 -0
  177. package/dist/src/templates/config-template.d.ts.map +1 -0
  178. package/dist/src/templates/config-template.js +35 -0
  179. package/dist/src/templates/config-template.js.map +1 -0
  180. package/dist/src/templates/dockerfile-template.d.ts +10 -0
  181. package/dist/src/templates/dockerfile-template.d.ts.map +1 -0
  182. package/dist/src/templates/dockerfile-template.js +30 -0
  183. package/dist/src/templates/dockerfile-template.js.map +1 -0
  184. package/dist/src/templates/env-template.d.ts +12 -0
  185. package/dist/src/templates/env-template.d.ts.map +1 -0
  186. package/dist/src/templates/env-template.js +24 -0
  187. package/dist/src/templates/env-template.js.map +1 -0
  188. package/dist/src/templates/knowledge-template.d.ts +10 -0
  189. package/dist/src/templates/knowledge-template.d.ts.map +1 -0
  190. package/dist/src/templates/knowledge-template.js +24 -0
  191. package/dist/src/templates/knowledge-template.js.map +1 -0
  192. package/dist/src/templates/skill-template.d.ts +10 -0
  193. package/dist/src/templates/skill-template.d.ts.map +1 -0
  194. package/dist/src/templates/skill-template.js +27 -0
  195. package/dist/src/templates/skill-template.js.map +1 -0
  196. package/dist/src/ui/AskUserPrompt.d.ts +14 -0
  197. package/dist/src/ui/AskUserPrompt.d.ts.map +1 -0
  198. package/dist/src/ui/AskUserPrompt.js +17 -0
  199. package/dist/src/ui/AskUserPrompt.js.map +1 -0
  200. package/dist/src/ui/AssistantMessage.d.ts +14 -0
  201. package/dist/src/ui/AssistantMessage.d.ts.map +1 -0
  202. package/dist/src/ui/AssistantMessage.js +8 -0
  203. package/dist/src/ui/AssistantMessage.js.map +1 -0
  204. package/dist/src/ui/ChatApp.d.ts +15 -0
  205. package/dist/src/ui/ChatApp.d.ts.map +1 -0
  206. package/dist/src/ui/ChatApp.js +144 -0
  207. package/dist/src/ui/ChatApp.js.map +1 -0
  208. package/dist/src/ui/ConfirmationPrompt.d.ts +17 -0
  209. package/dist/src/ui/ConfirmationPrompt.d.ts.map +1 -0
  210. package/dist/src/ui/ConfirmationPrompt.js +21 -0
  211. package/dist/src/ui/ConfirmationPrompt.js.map +1 -0
  212. package/dist/src/ui/DiffRenderer.d.ts +32 -0
  213. package/dist/src/ui/DiffRenderer.d.ts.map +1 -0
  214. package/dist/src/ui/DiffRenderer.js +118 -0
  215. package/dist/src/ui/DiffRenderer.js.map +1 -0
  216. package/dist/src/ui/ExpandableContent.d.ts +15 -0
  217. package/dist/src/ui/ExpandableContent.d.ts.map +1 -0
  218. package/dist/src/ui/ExpandableContent.js +22 -0
  219. package/dist/src/ui/ExpandableContent.js.map +1 -0
  220. package/dist/src/ui/ExploreIndicator.d.ts +13 -0
  221. package/dist/src/ui/ExploreIndicator.d.ts.map +1 -0
  222. package/dist/src/ui/ExploreIndicator.js +14 -0
  223. package/dist/src/ui/ExploreIndicator.js.map +1 -0
  224. package/dist/src/ui/Footer.d.ts +19 -0
  225. package/dist/src/ui/Footer.d.ts.map +1 -0
  226. package/dist/src/ui/Footer.js +57 -0
  227. package/dist/src/ui/Footer.js.map +1 -0
  228. package/dist/src/ui/FullScreenLayout.d.ts +18 -0
  229. package/dist/src/ui/FullScreenLayout.d.ts.map +1 -0
  230. package/dist/src/ui/FullScreenLayout.js +14 -0
  231. package/dist/src/ui/FullScreenLayout.js.map +1 -0
  232. package/dist/src/ui/Header.d.ts +14 -0
  233. package/dist/src/ui/Header.d.ts.map +1 -0
  234. package/dist/src/ui/Header.js +11 -0
  235. package/dist/src/ui/Header.js.map +1 -0
  236. package/dist/src/ui/InputBar.d.ts +17 -0
  237. package/dist/src/ui/InputBar.d.ts.map +1 -0
  238. package/dist/src/ui/InputBar.js +49 -0
  239. package/dist/src/ui/InputBar.js.map +1 -0
  240. package/dist/src/ui/MessageList.d.ts +18 -0
  241. package/dist/src/ui/MessageList.d.ts.map +1 -0
  242. package/dist/src/ui/MessageList.js +9 -0
  243. package/dist/src/ui/MessageList.js.map +1 -0
  244. package/dist/src/ui/NotificationBar.d.ts +14 -0
  245. package/dist/src/ui/NotificationBar.d.ts.map +1 -0
  246. package/dist/src/ui/NotificationBar.js +38 -0
  247. package/dist/src/ui/NotificationBar.js.map +1 -0
  248. package/dist/src/ui/ScrollableMessageList.d.ts +27 -0
  249. package/dist/src/ui/ScrollableMessageList.d.ts.map +1 -0
  250. package/dist/src/ui/ScrollableMessageList.js +16 -0
  251. package/dist/src/ui/ScrollableMessageList.js.map +1 -0
  252. package/dist/src/ui/SessionBrowser.d.ts +20 -0
  253. package/dist/src/ui/SessionBrowser.d.ts.map +1 -0
  254. package/dist/src/ui/SessionBrowser.js +93 -0
  255. package/dist/src/ui/SessionBrowser.js.map +1 -0
  256. package/dist/src/ui/StatusMessage.d.ts +13 -0
  257. package/dist/src/ui/StatusMessage.d.ts.map +1 -0
  258. package/dist/src/ui/StatusMessage.js +17 -0
  259. package/dist/src/ui/StatusMessage.js.map +1 -0
  260. package/dist/src/ui/StreamingView.d.ts +19 -0
  261. package/dist/src/ui/StreamingView.d.ts.map +1 -0
  262. package/dist/src/ui/StreamingView.js +18 -0
  263. package/dist/src/ui/StreamingView.js.map +1 -0
  264. package/dist/src/ui/SubagentDisplay.d.ts +13 -0
  265. package/dist/src/ui/SubagentDisplay.d.ts.map +1 -0
  266. package/dist/src/ui/SubagentDisplay.js +22 -0
  267. package/dist/src/ui/SubagentDisplay.js.map +1 -0
  268. package/dist/src/ui/ThinkingDisplay.d.ts +13 -0
  269. package/dist/src/ui/ThinkingDisplay.d.ts.map +1 -0
  270. package/dist/src/ui/ThinkingDisplay.js +15 -0
  271. package/dist/src/ui/ThinkingDisplay.js.map +1 -0
  272. package/dist/src/ui/ToolCallDisplay.d.ts +16 -0
  273. package/dist/src/ui/ToolCallDisplay.d.ts.map +1 -0
  274. package/dist/src/ui/ToolCallDisplay.js +136 -0
  275. package/dist/src/ui/ToolCallDisplay.js.map +1 -0
  276. package/dist/src/ui/UserMessage.d.ts +12 -0
  277. package/dist/src/ui/UserMessage.d.ts.map +1 -0
  278. package/dist/src/ui/UserMessage.js +5 -0
  279. package/dist/src/ui/UserMessage.js.map +1 -0
  280. package/dist/src/ui/commands/clear.d.ts +7 -0
  281. package/dist/src/ui/commands/clear.d.ts.map +1 -0
  282. package/dist/src/ui/commands/clear.js +13 -0
  283. package/dist/src/ui/commands/clear.js.map +1 -0
  284. package/dist/src/ui/commands/help.d.ts +7 -0
  285. package/dist/src/ui/commands/help.d.ts.map +1 -0
  286. package/dist/src/ui/commands/help.js +26 -0
  287. package/dist/src/ui/commands/help.js.map +1 -0
  288. package/dist/src/ui/commands/index.d.ts +14 -0
  289. package/dist/src/ui/commands/index.d.ts.map +1 -0
  290. package/dist/src/ui/commands/index.js +15 -0
  291. package/dist/src/ui/commands/index.js.map +1 -0
  292. package/dist/src/ui/commands/model.d.ts +7 -0
  293. package/dist/src/ui/commands/model.d.ts.map +1 -0
  294. package/dist/src/ui/commands/model.js +16 -0
  295. package/dist/src/ui/commands/model.js.map +1 -0
  296. package/dist/src/ui/commands/registry.d.ts +30 -0
  297. package/dist/src/ui/commands/registry.d.ts.map +1 -0
  298. package/dist/src/ui/commands/registry.js +45 -0
  299. package/dist/src/ui/commands/registry.js.map +1 -0
  300. package/dist/src/ui/commands/sessions.d.ts +7 -0
  301. package/dist/src/ui/commands/sessions.d.ts.map +1 -0
  302. package/dist/src/ui/commands/sessions.js +13 -0
  303. package/dist/src/ui/commands/sessions.js.map +1 -0
  304. package/dist/src/ui/commands/stats.d.ts +7 -0
  305. package/dist/src/ui/commands/stats.d.ts.map +1 -0
  306. package/dist/src/ui/commands/stats.js +33 -0
  307. package/dist/src/ui/commands/stats.js.map +1 -0
  308. package/dist/src/ui/commands/theme.d.ts +7 -0
  309. package/dist/src/ui/commands/theme.d.ts.map +1 -0
  310. package/dist/src/ui/commands/theme.js +35 -0
  311. package/dist/src/ui/commands/theme.js.map +1 -0
  312. package/dist/src/ui/markdown/CodeBlock.d.ts +14 -0
  313. package/dist/src/ui/markdown/CodeBlock.d.ts.map +1 -0
  314. package/dist/src/ui/markdown/CodeBlock.js +55 -0
  315. package/dist/src/ui/markdown/CodeBlock.js.map +1 -0
  316. package/dist/src/ui/markdown/InlineRenderer.d.ts +12 -0
  317. package/dist/src/ui/markdown/InlineRenderer.d.ts.map +1 -0
  318. package/dist/src/ui/markdown/InlineRenderer.js +70 -0
  319. package/dist/src/ui/markdown/InlineRenderer.js.map +1 -0
  320. package/dist/src/ui/markdown/MarkdownDisplay.d.ts +17 -0
  321. package/dist/src/ui/markdown/MarkdownDisplay.d.ts.map +1 -0
  322. package/dist/src/ui/markdown/MarkdownDisplay.js +142 -0
  323. package/dist/src/ui/markdown/MarkdownDisplay.js.map +1 -0
  324. package/dist/src/ui/markdown/Table.d.ts +14 -0
  325. package/dist/src/ui/markdown/Table.d.ts.map +1 -0
  326. package/dist/src/ui/markdown/Table.js +31 -0
  327. package/dist/src/ui/markdown/Table.js.map +1 -0
  328. package/dist/src/ui/theme.d.ts +39 -0
  329. package/dist/src/ui/theme.d.ts.map +1 -0
  330. package/dist/src/ui/theme.js +39 -0
  331. package/dist/src/ui/theme.js.map +1 -0
  332. package/dist/src/ui/themes/index.d.ts +45 -0
  333. package/dist/src/ui/themes/index.d.ts.map +1 -0
  334. package/dist/src/ui/themes/index.js +73 -0
  335. package/dist/src/ui/themes/index.js.map +1 -0
  336. package/dist/src/ui/themes/light.d.ts +8 -0
  337. package/dist/src/ui/themes/light.d.ts.map +1 -0
  338. package/dist/src/ui/themes/light.js +37 -0
  339. package/dist/src/ui/themes/light.js.map +1 -0
  340. package/dist/src/ui/themes/monochrome.d.ts +8 -0
  341. package/dist/src/ui/themes/monochrome.d.ts.map +1 -0
  342. package/dist/src/ui/themes/monochrome.js +37 -0
  343. package/dist/src/ui/themes/monochrome.js.map +1 -0
  344. package/dist/src/ui/types.d.ts +191 -0
  345. package/dist/src/ui/types.d.ts.map +1 -0
  346. package/dist/src/ui/types.js +7 -0
  347. package/dist/src/ui/types.js.map +1 -0
  348. package/dist/src/ui/useAlternateBuffer.d.ts +11 -0
  349. package/dist/src/ui/useAlternateBuffer.d.ts.map +1 -0
  350. package/dist/src/ui/useAlternateBuffer.js +25 -0
  351. package/dist/src/ui/useAlternateBuffer.js.map +1 -0
  352. package/dist/src/ui/useChat.d.ts +18 -0
  353. package/dist/src/ui/useChat.d.ts.map +1 -0
  354. package/dist/src/ui/useChat.js +599 -0
  355. package/dist/src/ui/useChat.js.map +1 -0
  356. package/dist/src/ui/useElapsedTime.d.ts +11 -0
  357. package/dist/src/ui/useElapsedTime.d.ts.map +1 -0
  358. package/dist/src/ui/useElapsedTime.js +39 -0
  359. package/dist/src/ui/useElapsedTime.js.map +1 -0
  360. package/dist/src/ui/useResponsiveLayout.d.ts +16 -0
  361. package/dist/src/ui/useResponsiveLayout.d.ts.map +1 -0
  362. package/dist/src/ui/useResponsiveLayout.js +24 -0
  363. package/dist/src/ui/useResponsiveLayout.js.map +1 -0
  364. package/dist/src/ui/useScroll.d.ts +20 -0
  365. package/dist/src/ui/useScroll.d.ts.map +1 -0
  366. package/dist/src/ui/useScroll.js +64 -0
  367. package/dist/src/ui/useScroll.js.map +1 -0
  368. package/dist/src/ui/useSessionResume.d.ts +20 -0
  369. package/dist/src/ui/useSessionResume.d.ts.map +1 -0
  370. package/dist/src/ui/useSessionResume.js +77 -0
  371. package/dist/src/ui/useSessionResume.js.map +1 -0
  372. package/dist/tsconfig.tsbuildinfo +1 -0
  373. package/package.json +60 -0
  374. package/src/auth/index.ts +13 -0
  375. package/src/auth/oauth2.test.ts +305 -0
  376. package/src/auth/oauth2.ts +269 -0
  377. package/src/auth/prompt.test.ts +205 -0
  378. package/src/auth/prompt.ts +111 -0
  379. package/src/auth/test-connection.test.ts +224 -0
  380. package/src/auth/test-connection.ts +196 -0
  381. package/src/auth/types.ts +34 -0
  382. package/src/commands/audit.test.ts +92 -0
  383. package/src/commands/audit.ts +113 -0
  384. package/src/commands/automations.test.ts +85 -0
  385. package/src/commands/automations.ts +205 -0
  386. package/src/commands/build-manifest-types.ts +35 -0
  387. package/src/commands/build-tools.ts +281 -0
  388. package/src/commands/build.test.ts +63 -0
  389. package/src/commands/build.ts +135 -0
  390. package/src/commands/chat.ts +147 -0
  391. package/src/commands/command-exports.test.ts +88 -0
  392. package/src/commands/connect.test.ts +343 -0
  393. package/src/commands/connect.ts +237 -0
  394. package/src/commands/deploy.test.ts +124 -0
  395. package/src/commands/deploy.ts +153 -0
  396. package/src/commands/deployments.ts +90 -0
  397. package/src/commands/dev.test.ts +63 -0
  398. package/src/commands/dev.ts +124 -0
  399. package/src/commands/diff.test.ts +183 -0
  400. package/src/commands/diff.ts +143 -0
  401. package/src/commands/docker.ts +232 -0
  402. package/src/commands/eval.test.ts +88 -0
  403. package/src/commands/eval.ts +268 -0
  404. package/src/commands/experiment.test.ts +125 -0
  405. package/src/commands/experiment.ts +153 -0
  406. package/src/commands/index.ts +76 -0
  407. package/src/commands/init.test.ts +109 -0
  408. package/src/commands/init.ts +98 -0
  409. package/src/commands/inspect.test.ts +234 -0
  410. package/src/commands/inspect.ts +157 -0
  411. package/src/commands/install-pkg.test.ts +265 -0
  412. package/src/commands/install-pkg.ts +234 -0
  413. package/src/commands/link.ts +270 -0
  414. package/src/commands/list.test.ts +152 -0
  415. package/src/commands/list.ts +95 -0
  416. package/src/commands/login.test.ts +195 -0
  417. package/src/commands/login.ts +258 -0
  418. package/src/commands/promote.ts +64 -0
  419. package/src/commands/publish.test.ts +203 -0
  420. package/src/commands/publish.ts +142 -0
  421. package/src/commands/rollback.ts +72 -0
  422. package/src/commands/search.test.ts +174 -0
  423. package/src/commands/search.ts +154 -0
  424. package/src/commands/secrets.test.ts +168 -0
  425. package/src/commands/secrets.ts +163 -0
  426. package/src/commands/serve.ts +166 -0
  427. package/src/commands/status.ts +94 -0
  428. package/src/commands/sync.test.ts +130 -0
  429. package/src/commands/sync.ts +119 -0
  430. package/src/commands/test-query.test.ts +42 -0
  431. package/src/commands/test-query.ts +129 -0
  432. package/src/commands/uninstall.test.ts +162 -0
  433. package/src/commands/uninstall.ts +107 -0
  434. package/src/commands/update.test.ts +281 -0
  435. package/src/commands/update.ts +180 -0
  436. package/src/commands/validate.test.ts +260 -0
  437. package/src/commands/validate.ts +139 -0
  438. package/src/e2e-automations.test.ts +305 -0
  439. package/src/e2e-commands.test.ts +587 -0
  440. package/src/e2e-incident-response.test.ts +345 -0
  441. package/src/e2e-plugin-connections.test.ts +415 -0
  442. package/src/e2e-plugins.test.ts +492 -0
  443. package/src/e2e.test.ts +602 -0
  444. package/src/fixtures/incident-response.ts +232 -0
  445. package/src/main.ts +35 -0
  446. package/src/shared/platform-client.test.ts +106 -0
  447. package/src/shared/platform-client.ts +193 -0
  448. package/src/shared/repo-discovery.test.ts +56 -0
  449. package/src/shared/repo-discovery.ts +40 -0
  450. package/src/templates/compose-template.ts +30 -0
  451. package/src/templates/config-template.ts +44 -0
  452. package/src/templates/deployment-templates.test.ts +99 -0
  453. package/src/templates/dockerfile-template.ts +30 -0
  454. package/src/templates/env-template.ts +27 -0
  455. package/src/templates/knowledge-template.ts +24 -0
  456. package/src/templates/skill-template.ts +27 -0
  457. package/src/ui/AskUserPrompt.tsx +58 -0
  458. package/src/ui/AssistantMessage.tsx +51 -0
  459. package/src/ui/ChatApp.tsx +283 -0
  460. package/src/ui/ConfirmationPrompt.tsx +75 -0
  461. package/src/ui/DiffRenderer.test.ts +104 -0
  462. package/src/ui/DiffRenderer.tsx +188 -0
  463. package/src/ui/ExpandableContent.tsx +68 -0
  464. package/src/ui/ExploreIndicator.tsx +44 -0
  465. package/src/ui/Footer.tsx +87 -0
  466. package/src/ui/FullScreenLayout.tsx +45 -0
  467. package/src/ui/Header.tsx +50 -0
  468. package/src/ui/InputBar.tsx +105 -0
  469. package/src/ui/MessageList.tsx +31 -0
  470. package/src/ui/NotificationBar.tsx +64 -0
  471. package/src/ui/ScrollableMessageList.tsx +82 -0
  472. package/src/ui/SessionBrowser.test.ts +49 -0
  473. package/src/ui/SessionBrowser.tsx +179 -0
  474. package/src/ui/StatusMessage.tsx +35 -0
  475. package/src/ui/StreamingView.tsx +87 -0
  476. package/src/ui/SubagentDisplay.tsx +57 -0
  477. package/src/ui/ThinkingDisplay.tsx +45 -0
  478. package/src/ui/ToolCallDisplay.tsx +268 -0
  479. package/src/ui/UserMessage.tsx +22 -0
  480. package/src/ui/chat-e2e.test.ts +581 -0
  481. package/src/ui/commands/clear.ts +15 -0
  482. package/src/ui/commands/help.ts +31 -0
  483. package/src/ui/commands/index.ts +22 -0
  484. package/src/ui/commands/model.ts +19 -0
  485. package/src/ui/commands/registry.test.ts +76 -0
  486. package/src/ui/commands/registry.ts +66 -0
  487. package/src/ui/commands/sessions.ts +16 -0
  488. package/src/ui/commands/stats.ts +35 -0
  489. package/src/ui/commands/theme.ts +41 -0
  490. package/src/ui/markdown/CodeBlock.tsx +118 -0
  491. package/src/ui/markdown/InlineRenderer.tsx +115 -0
  492. package/src/ui/markdown/MarkdownDisplay.tsx +223 -0
  493. package/src/ui/markdown/Table.tsx +75 -0
  494. package/src/ui/theme.ts +39 -0
  495. package/src/ui/themes/index.ts +113 -0
  496. package/src/ui/themes/light.ts +39 -0
  497. package/src/ui/themes/monochrome.ts +39 -0
  498. package/src/ui/types.ts +157 -0
  499. package/src/ui/useAlternateBuffer.ts +27 -0
  500. package/src/ui/useChat.test.ts +492 -0
  501. package/src/ui/useChat.ts +693 -0
  502. package/src/ui/useElapsedTime.test.ts +33 -0
  503. package/src/ui/useElapsedTime.ts +43 -0
  504. package/src/ui/useResponsiveLayout.test.ts +54 -0
  505. package/src/ui/useResponsiveLayout.ts +32 -0
  506. package/src/ui/useScroll.test.ts +99 -0
  507. package/src/ui/useScroll.ts +97 -0
  508. package/src/ui/useSessionResume.test.ts +80 -0
  509. package/src/ui/useSessionResume.ts +102 -0
  510. package/tsconfig.json +17 -0
  511. package/vitest.config.ts +20 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ export interface ConfigTemplateOptions {
8
+ name: string;
9
+ provider: 'anthropic' | 'openai' | 'google';
10
+ }
11
+
12
+ /**
13
+ * Generates the default config.json content for a new project.
14
+ */
15
+ export function generateConfigTemplate(options: ConfigTemplateOptions): string {
16
+ const modelMap: Record<string, string> = {
17
+ anthropic: 'claude-sonnet-4-20250514',
18
+ openai: 'gpt-4o',
19
+ google: 'gemini-2.0-flash',
20
+ };
21
+
22
+ const envKeyMap: Record<string, string> = {
23
+ anthropic: 'ANTHROPIC_API_KEY',
24
+ openai: 'OPENAI_API_KEY',
25
+ google: 'GOOGLE_API_KEY',
26
+ };
27
+
28
+ const model = modelMap[options.provider] ?? modelMap['anthropic'];
29
+ const envKey = envKeyMap[options.provider] ?? envKeyMap['anthropic'];
30
+
31
+ const config = {
32
+ name: options.name,
33
+ version: '1.0.0',
34
+ models: {
35
+ main: {
36
+ provider: options.provider,
37
+ model,
38
+ apiKey: `\${${envKey}}`,
39
+ },
40
+ },
41
+ };
42
+
43
+ return JSON.stringify(config, null, 2) + '\n';
44
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {describe, it, expect} from 'vitest';
8
+ import {generateDockerfile} from './dockerfile-template.js';
9
+ import {generateCompose} from './compose-template.js';
10
+ import {extractEnvVars} from './env-template.js';
11
+
12
+ describe('generateDockerfile', () => {
13
+ it('should generate valid Dockerfile', () => {
14
+ const content = generateDockerfile();
15
+ expect(content).toContain('FROM node:20-slim AS builder');
16
+ expect(content).toContain('FROM node:20-slim AS production');
17
+ expect(content).toContain('EXPOSE 3847');
18
+ });
19
+
20
+ it('should include multi-stage build', () => {
21
+ const content = generateDockerfile();
22
+ expect(content).toContain('AS builder');
23
+ expect(content).toContain('AS production');
24
+ expect(content).toContain('COPY --from=builder');
25
+ });
26
+
27
+ it('should set NODE_ENV', () => {
28
+ const content = generateDockerfile();
29
+ expect(content).toContain('NODE_ENV=production');
30
+ });
31
+ });
32
+
33
+ describe('generateCompose', () => {
34
+ it('should use service name', () => {
35
+ const content = generateCompose('my-agent');
36
+ expect(content).toContain('my-agent:');
37
+ });
38
+
39
+ it('should sanitize special characters in service name', () => {
40
+ const content = generateCompose('My Agent v2.0');
41
+ expect(content).toContain('my-agent-v2-0:');
42
+ });
43
+
44
+ it('should include health check', () => {
45
+ const content = generateCompose('test');
46
+ expect(content).toContain('healthcheck:');
47
+ expect(content).toContain('/health');
48
+ });
49
+
50
+ it('should reference .env.production', () => {
51
+ const content = generateCompose('test');
52
+ expect(content).toContain('.env.production');
53
+ });
54
+
55
+ it('should expose port 3847', () => {
56
+ const content = generateCompose('test');
57
+ expect(content).toContain('3847:3847');
58
+ });
59
+ });
60
+
61
+ describe('extractEnvVars', () => {
62
+ it('should extract env:VAR_NAME references', () => {
63
+ const json = '{"key": "env:MY_API_KEY", "model": "env:MODEL_NAME"}';
64
+ const vars = extractEnvVars(json);
65
+ expect(vars).toEqual(['MODEL_NAME', 'MY_API_KEY']);
66
+ });
67
+
68
+ it('should deduplicate vars', () => {
69
+ const json = '{"a": "env:MY_KEY", "b": "env:MY_KEY"}';
70
+ const vars = extractEnvVars(json);
71
+ expect(vars).toEqual(['MY_KEY']);
72
+ });
73
+
74
+ it('should return empty for no env refs', () => {
75
+ const json = '{"key": "literal-value"}';
76
+ expect(extractEnvVars(json)).toEqual([]);
77
+ });
78
+
79
+ it('should handle complex nested JSON', () => {
80
+ const json = JSON.stringify({
81
+ models: {
82
+ main: {provider: 'env:PROVIDER', model: 'env:MODEL'},
83
+ },
84
+ platform: {apiKey: 'env:API_KEY'},
85
+ });
86
+ const vars = extractEnvVars(json);
87
+ expect(vars).toEqual(['API_KEY', 'MODEL', 'PROVIDER']);
88
+ });
89
+
90
+ it('should sort results alphabetically', () => {
91
+ const json = '{"z": "env:ZEBRA", "a": "env:ALPHA"}';
92
+ const vars = extractEnvVars(json);
93
+ expect(vars).toEqual(['ALPHA', 'ZEBRA']);
94
+ });
95
+
96
+ it('should handle empty string', () => {
97
+ expect(extractEnvVars('')).toEqual([]);
98
+ });
99
+ });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ /**
8
+ * Generate a production Dockerfile for amodal runtime.
9
+ */
10
+ export function generateDockerfile(): string {
11
+ return `# Multi-stage build for amodal runtime
12
+ # Generated by: amodal deploy init
13
+
14
+ # Stage 1: Build
15
+ FROM node:20-slim AS builder
16
+ WORKDIR /app
17
+ COPY package.json pnpm-lock.yaml* package-lock.json* ./
18
+ RUN corepack enable && corepack prepare pnpm@latest --activate 2>/dev/null || npm install
19
+ COPY . .
20
+ RUN if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else npm ci; fi
21
+
22
+ # Stage 2: Production
23
+ FROM node:20-slim AS production
24
+ WORKDIR /app
25
+ ENV NODE_ENV=production
26
+ COPY --from=builder /app .
27
+ EXPOSE 3847
28
+ CMD ["node", "node_modules/@amodalai/runtime/dist/src/index.js"]
29
+ `;
30
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ const ENV_PATTERN = /env:([A-Z_][A-Z0-9_]*)/g;
8
+
9
+ /**
10
+ * Extract all env:VAR_NAME references from JSON config strings.
11
+ *
12
+ * Returns a deduplicated list of environment variable names.
13
+ */
14
+ export function extractEnvVars(jsonString: string): string[] {
15
+ const vars = new Set<string>();
16
+ let match: RegExpExecArray | null;
17
+
18
+ // Reset regex state
19
+ ENV_PATTERN.lastIndex = 0;
20
+ while ((match = ENV_PATTERN.exec(jsonString)) !== null) {
21
+ if (match[1]) {
22
+ vars.add(match[1]);
23
+ }
24
+ }
25
+
26
+ return [...vars].sort();
27
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ /**
8
+ * Generates a starter knowledge.md.
9
+ */
10
+ export function generateKnowledgeTemplate(): string {
11
+ return `---
12
+ title: Domain Knowledge
13
+ ---
14
+
15
+ ## Getting Started
16
+
17
+ Add domain-specific knowledge here. Good knowledge documents include:
18
+
19
+ - **Terminology**: Define domain-specific terms the agent should understand
20
+ - **Baselines**: What "normal" looks like for key metrics
21
+ - **Common patterns**: Recurring scenarios the agent should recognize
22
+ - **Decision frameworks**: How to prioritize or categorize findings
23
+ `;
24
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ /**
8
+ * Generates a starter SKILL.md.
9
+ */
10
+ export function generateSkillTemplate(): string {
11
+ return `---
12
+ name: general-analysis
13
+ description: General-purpose analysis skill — customize for your domain
14
+ trigger: When the user asks for investigation or analysis
15
+ ---
16
+
17
+ ## Analysis
18
+
19
+ Customize this skill for your specific domain. A good skill tells the agent:
20
+
21
+ 1. **What to investigate** — the scope and constraints
22
+ 2. **How to gather data** — which connections and endpoints to use
23
+ 3. **How to reason** — the analytical framework to apply
24
+ 4. **How to present findings** — the format and level of detail
25
+ 5. **What to avoid** — common pitfalls and anti-patterns
26
+ `;
27
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type React from 'react';
8
+ import {useState, useCallback} from 'react';
9
+ import {Box, Text} from 'ink';
10
+ import TextInput from 'ink-text-input';
11
+ import {theme} from './theme.js';
12
+ import type {AskUserQuestion} from './types.js';
13
+
14
+ interface AskUserPromptProps {
15
+ question: AskUserQuestion;
16
+ onRespond: (askId: string, answer: string) => void;
17
+ }
18
+
19
+ export const AskUserPrompt: React.FC<AskUserPromptProps> = ({question, onRespond}) => {
20
+ const [value, setValue] = useState('');
21
+
22
+ const handleSubmit = useCallback(
23
+ (text: string) => {
24
+ const trimmed = text.trim();
25
+ if (!trimmed) return;
26
+ onRespond(question.askId, trimmed);
27
+ setValue('');
28
+ },
29
+ [onRespond, question.askId],
30
+ );
31
+
32
+ return (
33
+ <Box
34
+ flexDirection="column"
35
+ marginTop={1}
36
+ borderStyle="round"
37
+ borderColor={theme.text.accent}
38
+ paddingLeft={1}
39
+ paddingRight={1}
40
+ >
41
+ <Text color={theme.text.accent} bold>
42
+ Agent Question
43
+ </Text>
44
+ <Text wrap="wrap">{question.text}</Text>
45
+ <Box marginTop={1}>
46
+ <Text color={theme.text.accent} bold>
47
+ {'\u203A '}
48
+ </Text>
49
+ <TextInput
50
+ value={value}
51
+ onChange={setValue}
52
+ onSubmit={handleSubmit}
53
+ placeholder="Type your answer..."
54
+ />
55
+ </Box>
56
+ </Box>
57
+ );
58
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type React from 'react';
8
+ import {Box, Text} from 'ink';
9
+ import {theme} from './theme.js';
10
+ import {MarkdownDisplay} from './markdown/MarkdownDisplay.js';
11
+ import {ToolCallDisplay} from './ToolCallDisplay.js';
12
+ import {ThinkingDisplay} from './ThinkingDisplay.js';
13
+ import type {ChatMessage} from './types.js';
14
+
15
+ interface AssistantMessageProps {
16
+ message: ChatMessage;
17
+ width?: number;
18
+ }
19
+
20
+ export const AssistantMessage: React.FC<AssistantMessageProps> = ({
21
+ message,
22
+ width,
23
+ }) => (
24
+ <Box flexDirection="column" marginTop={1}>
25
+ {/* Skills activated */}
26
+ {message.skills?.map((skill, i) => (
27
+ <Text key={i} color={theme.status.warning}>
28
+ {' \u26A1 '}
29
+ {skill}
30
+ </Text>
31
+ ))}
32
+
33
+ {/* Collapsed thinking */}
34
+ {message.thinking ? <ThinkingDisplay text={message.thinking} collapsed /> : null}
35
+
36
+ {/* Tool calls — inline before text (matches actual execution order) */}
37
+ {message.toolCalls?.map((tool) => (
38
+ <ToolCallDisplay key={tool.toolId} tool={tool} width={width} compact />
39
+ ))}
40
+
41
+ {/* Main text with markdown */}
42
+ {message.text ? (
43
+ <Box>
44
+ <Text color={theme.text.accent}>{'\u25C6 '}</Text>
45
+ <Box flexDirection="column" width={width ? width - 4 : undefined}>
46
+ <MarkdownDisplay text={message.text} width={width ? width - 4 : undefined} />
47
+ </Box>
48
+ </Box>
49
+ ) : null}
50
+ </Box>
51
+ );
@@ -0,0 +1,283 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type React from 'react';
8
+ import {useCallback, useEffect} from 'react';
9
+ import {Box, Text, useApp, useInput, useStdout} from 'ink';
10
+ import {useChat} from './useChat.js';
11
+ import {ScrollableMessageList} from './ScrollableMessageList.js';
12
+ import {InputBar} from './InputBar.js';
13
+ import {Header} from './Header.js';
14
+ import {Footer} from './Footer.js';
15
+ import {NotificationBar} from './NotificationBar.js';
16
+ import {AskUserPrompt} from './AskUserPrompt.js';
17
+ import {ConfirmationPrompt} from './ConfirmationPrompt.js';
18
+ import {StatusMessage} from './StatusMessage.js';
19
+ import {SessionBrowser} from './SessionBrowser.js';
20
+ import {FullScreenLayout} from './FullScreenLayout.js';
21
+ import {theme} from './theme.js';
22
+ import {useScroll} from './useScroll.js';
23
+ import {useElapsedTime} from './useElapsedTime.js';
24
+ import {useSessionResume} from './useSessionResume.js';
25
+ import {getResponsiveLayout} from './useResponsiveLayout.js';
26
+ import {getCommand} from './commands/index.js';
27
+
28
+ interface ChatAppProps {
29
+ baseUrl: string;
30
+ tenantId: string;
31
+ resumeSessionId?: string;
32
+ fullscreen?: boolean;
33
+ }
34
+
35
+ // Approximate row counts for layout calculation
36
+ const HEADER_ROWS = 2;
37
+ const FOOTER_ROWS = 3;
38
+ const INPUT_ROWS = 2;
39
+
40
+ export const ChatApp: React.FC<ChatAppProps> = ({
41
+ baseUrl,
42
+ tenantId,
43
+ resumeSessionId,
44
+ fullscreen,
45
+ }) => {
46
+ const {state, sendMessage, respondToQuestion, respondToConfirmation, dismissNotification, dispatch} =
47
+ useChat(baseUrl, tenantId);
48
+ const {exit} = useApp();
49
+ const {stdout} = useStdout();
50
+ const width = stdout?.columns ?? 80;
51
+ const rows = stdout?.rows ?? 24;
52
+
53
+ const layout = getResponsiveLayout(width);
54
+ const elapsed = useElapsedTime(state.isStreaming);
55
+
56
+ // Scroll management
57
+ const viewportHeight = Math.max(rows - HEADER_ROWS - FOOTER_ROWS - INPUT_ROWS, 5);
58
+ const scroll = useScroll(true);
59
+
60
+ // Update viewport height
61
+ useEffect(() => {
62
+ scroll.setViewportHeight(viewportHeight);
63
+ }, [viewportHeight, scroll]);
64
+
65
+ // Auto-scroll when messages or streaming content changes
66
+ useEffect(() => {
67
+ // Estimate content height as number of messages * ~3 lines each + streaming
68
+ const estimatedHeight = state.messages.length * 3 +
69
+ (state.isStreaming ? 5 : 0) +
70
+ state.activeToolCalls.length * 4;
71
+ scroll.setContentHeight(estimatedHeight);
72
+ }, [state.messages.length, state.isStreaming, state.activeToolCalls.length, scroll]);
73
+
74
+ // Session resume
75
+ const resume = useSessionResume(resumeSessionId ?? null, baseUrl);
76
+ useEffect(() => {
77
+ if (resume.messages && resumeSessionId) {
78
+ dispatch({
79
+ type: 'RESUME_SESSION',
80
+ sessionId: resumeSessionId,
81
+ messages: resume.messages,
82
+ });
83
+ }
84
+ }, [resume.messages, resumeSessionId, dispatch]);
85
+
86
+ // Keyboard navigation for scrolling
87
+ const canScroll = !state.isStreaming && !state.pendingQuestion && !state.pendingConfirmation && !state.showSessionBrowser;
88
+ useInput((_input, key) => {
89
+ if (key.ctrl && _input === 'c') {
90
+ exit();
91
+ return;
92
+ }
93
+
94
+ if (!canScroll) return;
95
+
96
+ // j/k line scroll
97
+ if (_input === 'j') {
98
+ scroll.scrollBy(1);
99
+ } else if (_input === 'k') {
100
+ scroll.scrollBy(-1);
101
+ }
102
+
103
+ // Page up/down
104
+ if (key.pageUp) {
105
+ scroll.scrollBy(-viewportHeight);
106
+ } else if (key.pageDown) {
107
+ scroll.scrollBy(viewportHeight);
108
+ }
109
+
110
+ // Home/End (map to Meta+< and Meta+>)
111
+ if (key.home) {
112
+ scroll.scrollToTop();
113
+ } else if (key.end) {
114
+ scroll.scrollToBottom();
115
+ }
116
+ });
117
+
118
+ // Slash command handler
119
+ const handleSlashCommand = useCallback(
120
+ (name: string, args: string) => {
121
+ const cmd = getCommand(name);
122
+ if (!cmd) {
123
+ dispatch({type: 'LOCAL_MESSAGE', text: `Unknown command: /${name}. Type /help for available commands.`});
124
+ return;
125
+ }
126
+ const result = cmd.execute(args, state);
127
+ switch (result.type) {
128
+ case 'message':
129
+ dispatch({type: 'LOCAL_MESSAGE', text: result.text ?? ''});
130
+ break;
131
+ case 'clear':
132
+ dispatch({type: 'CLEAR_HISTORY'});
133
+ break;
134
+ case 'noop':
135
+ break;
136
+ default:
137
+ break;
138
+ }
139
+ },
140
+ [state, dispatch],
141
+ );
142
+
143
+ // Confirmation queue handlers
144
+ const handleApproveAll = useCallback(() => {
145
+ for (let i = 0; i < state.confirmationQueue.length; i++) {
146
+ respondToConfirmation(true);
147
+ }
148
+ }, [state.confirmationQueue.length, respondToConfirmation]);
149
+
150
+ const handleRejectAll = useCallback(() => {
151
+ for (let i = 0; i < state.confirmationQueue.length; i++) {
152
+ respondToConfirmation(false);
153
+ }
154
+ }, [state.confirmationQueue.length, respondToConfirmation]);
155
+
156
+ // Session browser handlers
157
+ const handleSessionSelect = useCallback(
158
+ (sessionId: string) => {
159
+ dispatch({type: 'HIDE_SESSION_BROWSER'});
160
+ // Trigger resume by re-mounting — for now just dispatch
161
+ dispatch({type: 'LOCAL_MESSAGE', text: `Resuming session ${sessionId}...`});
162
+ },
163
+ [dispatch],
164
+ );
165
+
166
+ const handleSessionBrowserClose = useCallback(() => {
167
+ dispatch({type: 'HIDE_SESSION_BROWSER'});
168
+ }, [dispatch]);
169
+
170
+ // Get first running tool name for InputBar
171
+ const activeToolName = state.activeToolCalls.find((t) => t.status === 'running')?.toolName;
172
+ const exploreQuery = state.explorePhase?.active ? state.explorePhase.query : undefined;
173
+ const cwd = process.cwd();
174
+
175
+ const currentConfirmation = state.confirmationQueue[0] ?? state.pendingConfirmation;
176
+
177
+ const headerEl = (
178
+ <Header sessionId={state.sessionId} isStreaming={state.isStreaming} isNarrow={layout.isNarrow} />
179
+ );
180
+
181
+ const footerEl = (
182
+ <Footer
183
+ isStreaming={state.isStreaming}
184
+ hasPendingQuestion={!!state.pendingQuestion}
185
+ hasPendingConfirmation={!!currentConfirmation}
186
+ tokenUsage={state.tokenUsage}
187
+ cwd={cwd}
188
+ modelName={state.tokenUsage.model ?? undefined}
189
+ isNarrow={layout.isNarrow}
190
+ />
191
+ );
192
+
193
+ const content = (
194
+ <>
195
+ {/* Resume loading indicator */}
196
+ {resume.loading ? (
197
+ <Box marginBottom={1}>
198
+ <StatusMessage type="info">Resuming session...</StatusMessage>
199
+ </Box>
200
+ ) : null}
201
+ {resume.error ? (
202
+ <Box marginBottom={1}>
203
+ <StatusMessage type="error">Resume failed: {resume.error}</StatusMessage>
204
+ </Box>
205
+ ) : null}
206
+
207
+ {/* Scrollable message viewport */}
208
+ <ScrollableMessageList
209
+ messages={state.messages}
210
+ width={width}
211
+ viewportHeight={viewportHeight}
212
+ scrollTop={scroll.scrollTop}
213
+ isStreaming={state.isStreaming}
214
+ streamingText={state.streamingText}
215
+ thinkingText={state.thinkingText}
216
+ toolCalls={state.activeToolCalls}
217
+ skills={state.activatedSkills}
218
+ explore={state.explorePhase}
219
+ error={state.error}
220
+ />
221
+
222
+ {/* Scroll position indicator */}
223
+ {!scroll.isAtBottom && !state.isStreaming ? (
224
+ <Box justifyContent="center">
225
+ <Text color={theme.ui.dim}>{'\u2193'} more below</Text>
226
+ </Box>
227
+ ) : null}
228
+
229
+ {/* Notifications */}
230
+ <NotificationBar notifications={state.notifications} onDismiss={dismissNotification} />
231
+
232
+ {/* Session Browser overlay */}
233
+ {state.showSessionBrowser ? (
234
+ <SessionBrowser
235
+ baseUrl={baseUrl}
236
+ onSelect={handleSessionSelect}
237
+ onClose={handleSessionBrowserClose}
238
+ />
239
+ ) : null}
240
+
241
+ {/* Input area — conditional on pending prompts */}
242
+ {!state.showSessionBrowser ? (
243
+ currentConfirmation ? (
244
+ <ConfirmationPrompt
245
+ request={currentConfirmation}
246
+ queueSize={state.confirmationQueue.length}
247
+ onRespond={respondToConfirmation}
248
+ onApproveAll={handleApproveAll}
249
+ onRejectAll={handleRejectAll}
250
+ />
251
+ ) : state.pendingQuestion ? (
252
+ <AskUserPrompt question={state.pendingQuestion} onRespond={respondToQuestion} />
253
+ ) : (
254
+ <InputBar
255
+ onSubmit={sendMessage}
256
+ onSlashCommand={handleSlashCommand}
257
+ isStreaming={state.isStreaming}
258
+ elapsed={elapsed}
259
+ exploreQuery={exploreQuery}
260
+ activeToolName={activeToolName}
261
+ />
262
+ )
263
+ ) : null}
264
+ </>
265
+ );
266
+
267
+ if (fullscreen) {
268
+ return (
269
+ <FullScreenLayout header={headerEl} footer={footerEl}>
270
+ {content}
271
+ </FullScreenLayout>
272
+ );
273
+ }
274
+
275
+ return (
276
+ <Box flexDirection="column" width={width}>
277
+ {headerEl}
278
+ {content}
279
+ {footerEl}
280
+ </Box>
281
+ );
282
+ };
283
+