@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,195 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
8
+ import {createServer} from 'node:http';
9
+ import type {Server} from 'node:http';
10
+
11
+ const mockReadFile = vi.fn();
12
+ const mockWriteFile = vi.fn();
13
+ const mockMkdir = vi.fn();
14
+ const mockOpen = vi.fn();
15
+
16
+ vi.mock('node:fs/promises', () => ({
17
+ readFile: mockReadFile,
18
+ writeFile: mockWriteFile,
19
+ mkdir: mockMkdir,
20
+ }));
21
+
22
+ vi.mock('open', () => ({
23
+ default: mockOpen,
24
+ }));
25
+
26
+ describe('runLogin', () => {
27
+ let stderrOutput: string;
28
+ let mockPlatformServer: Server;
29
+ let platformPort: number;
30
+
31
+ beforeEach(async () => {
32
+ vi.clearAllMocks();
33
+ mockReadFile.mockRejectedValue(new Error('ENOENT'));
34
+ mockWriteFile.mockResolvedValue(undefined);
35
+ mockMkdir.mockResolvedValue(undefined);
36
+ stderrOutput = '';
37
+ vi.spyOn(process.stderr, 'write').mockImplementation((chunk) => {
38
+ stderrOutput += String(chunk);
39
+ return true;
40
+ });
41
+
42
+ // Start a mock platform API server (for /api/me verification)
43
+ await new Promise<void>((resolve) => {
44
+ mockPlatformServer = createServer((req, res) => {
45
+ if (req.url === '/api/me') {
46
+ res.writeHead(200, {'Content-Type': 'application/json'});
47
+ res.end(JSON.stringify({
48
+ user: {email: 'test@example.com', name: 'Test User'},
49
+ org: {name: 'Test Org'},
50
+ }));
51
+ return;
52
+ }
53
+ res.writeHead(404);
54
+ res.end('Not found');
55
+ });
56
+ mockPlatformServer.listen(0, '127.0.0.1', () => {
57
+ const addr = mockPlatformServer.address();
58
+ if (addr && typeof addr !== 'string') {
59
+ platformPort = addr.port;
60
+ }
61
+ resolve();
62
+ });
63
+ });
64
+ });
65
+
66
+ afterEach(() => {
67
+ mockPlatformServer?.close();
68
+ });
69
+
70
+ it('should skip login when already authenticated', async () => {
71
+ const url = `http://127.0.0.1:${platformPort}`;
72
+ mockReadFile.mockResolvedValue(JSON.stringify({
73
+ platform: {url, token: 'existing-token'},
74
+ }));
75
+
76
+ const {runLogin} = await import('./login.js');
77
+ const result = await runLogin({platformUrl: url});
78
+ expect(result).toBe(0);
79
+ expect(stderrOutput).toContain('Already logged in');
80
+ });
81
+
82
+ it('should open browser and complete login on callback', async () => {
83
+ // Mock open to simulate browser: extract port from URL and call callback
84
+ mockOpen.mockImplementation(async (loginUrl: string) => {
85
+ const url = new URL(loginUrl);
86
+ const port = url.searchParams.get('port');
87
+ const state = url.searchParams.get('state');
88
+ // Simulate browser redirect to callback
89
+ await fetch(
90
+ `http://127.0.0.1:${port}/callback?token=test-jwt-token&refresh_token=test-refresh&state=${state}`,
91
+ );
92
+ });
93
+
94
+ const {runLogin} = await import('./login.js');
95
+ const result = await runLogin({
96
+ platformUrl: `http://127.0.0.1:${platformPort}`,
97
+ adminUrl: 'http://localhost:9999', // Not actually hit — open is mocked
98
+ });
99
+ expect(result).toBe(0);
100
+ expect(stderrOutput).toContain('Logged in as test@example.com');
101
+ expect(stderrOutput).toContain('org: Test Org');
102
+ expect(mockWriteFile).toHaveBeenCalled();
103
+
104
+ // Verify the saved content
105
+ const writeCall = mockWriteFile.mock.calls[0];
106
+
107
+ const content = writeCall[1] as string;
108
+ expect(content).toContain('test-jwt-token');
109
+ expect(content).toContain('test-refresh');
110
+ });
111
+
112
+ it('should open admin UI URL, not platform API', async () => {
113
+ mockOpen.mockImplementation(async (loginUrl: string) => {
114
+ const url = new URL(loginUrl);
115
+ // Verify it opens the admin UI
116
+ expect(url.origin).toBe('http://localhost:3333');
117
+ expect(url.pathname).toBe('/cli-auth');
118
+ expect(url.searchParams.get('port')).toBeTruthy();
119
+ expect(url.searchParams.get('state')).toBeTruthy();
120
+
121
+ const port = url.searchParams.get('port');
122
+ const state = url.searchParams.get('state');
123
+ await fetch(
124
+ `http://127.0.0.1:${port}/callback?token=jwt&state=${state}`,
125
+ );
126
+ });
127
+
128
+ const {runLogin} = await import('./login.js');
129
+ await runLogin({
130
+ platformUrl: `http://127.0.0.1:${platformPort}`,
131
+ adminUrl: 'http://localhost:3333',
132
+ });
133
+
134
+ expect(mockOpen).toHaveBeenCalledOnce();
135
+ });
136
+
137
+ it('should return 1 when state mismatches', async () => {
138
+ mockOpen.mockImplementation(async (loginUrl: string) => {
139
+ const url = new URL(loginUrl);
140
+ const port = url.searchParams.get('port');
141
+ // Send back wrong state
142
+ await fetch(
143
+ `http://127.0.0.1:${port}/callback?token=test-jwt&state=wrong-state`,
144
+ );
145
+ });
146
+
147
+ const {runLogin} = await import('./login.js');
148
+ const result = await runLogin({
149
+ platformUrl: `http://127.0.0.1:${platformPort}`,
150
+ adminUrl: 'http://localhost:9999',
151
+ });
152
+ expect(result).toBe(1);
153
+ expect(stderrOutput).toContain('State mismatch');
154
+ });
155
+
156
+ it('should handle callback error from browser', async () => {
157
+ mockOpen.mockImplementation(async (loginUrl: string) => {
158
+ const url = new URL(loginUrl);
159
+ const port = url.searchParams.get('port');
160
+ await fetch(
161
+ `http://127.0.0.1:${port}/callback?error=access_denied`,
162
+ );
163
+ });
164
+
165
+ const {runLogin} = await import('./login.js');
166
+ const result = await runLogin({
167
+ platformUrl: `http://127.0.0.1:${platformPort}`,
168
+ adminUrl: 'http://localhost:9999',
169
+ });
170
+ expect(result).toBe(1);
171
+ expect(stderrOutput).toContain('access_denied');
172
+ });
173
+
174
+ it('should save credentials with restricted file permissions', async () => {
175
+ mockOpen.mockImplementation(async (loginUrl: string) => {
176
+ const url = new URL(loginUrl);
177
+ const port = url.searchParams.get('port');
178
+ const state = url.searchParams.get('state');
179
+ await fetch(
180
+ `http://127.0.0.1:${port}/callback?token=jwt123&state=${state}`,
181
+ );
182
+ });
183
+
184
+ const {runLogin} = await import('./login.js');
185
+ await runLogin({
186
+ platformUrl: `http://127.0.0.1:${platformPort}`,
187
+ adminUrl: 'http://localhost:9999',
188
+ });
189
+
190
+ const writeCall = mockWriteFile.mock.calls[0];
191
+
192
+ const options = writeCall[2] as {mode: number};
193
+ expect(options.mode).toBe(0o600);
194
+ });
195
+ });
@@ -0,0 +1,258 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {writeFile, readFile, mkdir} from 'node:fs/promises';
8
+ import {createServer} from 'node:http';
9
+ import type {Server} from 'node:http';
10
+ import {homedir} from 'node:os';
11
+ import * as path from 'node:path';
12
+ import {randomUUID} from 'node:crypto';
13
+
14
+ import type {CommandModule} from 'yargs';
15
+ import open from 'open';
16
+
17
+ const DEFAULT_PLATFORM_URL = 'https://api.amodalai.com';
18
+ const DEFAULT_ADMIN_UI_URL = 'https://app.amodalai.com';
19
+ const RC_FILE = '.amodalrc';
20
+ const LOGIN_TIMEOUT_MS = 120_000;
21
+
22
+ export interface LoginOptions {
23
+ platformUrl?: string;
24
+ adminUrl?: string;
25
+ }
26
+
27
+ interface RcFile {
28
+ platform?: {
29
+ url: string;
30
+ token: string;
31
+ refreshToken?: string;
32
+ };
33
+ }
34
+
35
+ export async function readRcFile(): Promise<RcFile> {
36
+ const rcPath = path.join(homedir(), RC_FILE);
37
+ try {
38
+ const content = await readFile(rcPath, 'utf-8');
39
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
40
+ return JSON.parse(content) as RcFile;
41
+ } catch {
42
+ return {};
43
+ }
44
+ }
45
+
46
+ async function writeRcFile(rc: RcFile): Promise<void> {
47
+ const rcPath = path.join(homedir(), RC_FILE);
48
+ await mkdir(path.dirname(rcPath), {recursive: true});
49
+ await writeFile(rcPath, JSON.stringify(rc, null, 2) + '\n', {mode: 0o600});
50
+ }
51
+
52
+ /**
53
+ * Start a local callback server that receives the token from the browser.
54
+ */
55
+ function startCallbackServer(): Promise<{
56
+ server: Server;
57
+ port: number;
58
+ tokenPromise: Promise<{token: string; refreshToken: string; state: string}>;
59
+ }> {
60
+ return new Promise((resolve, reject) => {
61
+ let resolveToken: (value: {token: string; refreshToken: string; state: string}) => void;
62
+ let rejectToken: (reason: Error) => void;
63
+ const tokenPromise = new Promise<{token: string; refreshToken: string; state: string}>(
64
+ (res, rej) => {
65
+ resolveToken = res;
66
+ rejectToken = rej;
67
+ },
68
+ );
69
+
70
+ const server = createServer((req, res) => {
71
+ try {
72
+ const url = new URL(req.url ?? '/', 'http://localhost');
73
+ if (url.pathname !== '/callback') {
74
+ res.writeHead(404);
75
+ res.end('Not found');
76
+ return;
77
+ }
78
+
79
+ const token = url.searchParams.get('token');
80
+ const refreshToken = url.searchParams.get('refresh_token') ?? '';
81
+ const state = url.searchParams.get('state');
82
+ const error = url.searchParams.get('error');
83
+
84
+ if (error) {
85
+ res.writeHead(200, {'Content-Type': 'text/html'});
86
+ res.end(
87
+ '<html><body style="background:#0a0a0a;color:#fff;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh">' +
88
+ '<div><h1>Login Failed</h1><p>You can close this window.</p></div></body></html>',
89
+ );
90
+ rejectToken(new Error(`Login error: ${error}`));
91
+ return;
92
+ }
93
+
94
+ if (!token || !state) {
95
+ res.writeHead(400, {'Content-Type': 'text/html'});
96
+ res.end(
97
+ '<html><body style="background:#0a0a0a;color:#fff;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh">' +
98
+ '<div><h1>Missing Parameters</h1></div></body></html>',
99
+ );
100
+ rejectToken(new Error('Missing token or state parameter'));
101
+ return;
102
+ }
103
+
104
+ res.writeHead(200, {'Content-Type': 'text/html'});
105
+ res.end(
106
+ '<html><body style="background:#0a0a0a;color:#fff;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh">' +
107
+ '<div><h1>Login Successful</h1><p>You can close this window and return to the terminal.</p></div></body></html>',
108
+ );
109
+ resolveToken({token, refreshToken, state});
110
+ } catch (err) {
111
+ res.writeHead(500);
112
+ res.end('Internal error');
113
+ rejectToken(err instanceof Error ? err : new Error(String(err)));
114
+ }
115
+ });
116
+
117
+ server.listen(0, '127.0.0.1', () => {
118
+ const addr = server.address();
119
+ if (!addr || typeof addr === 'string') {
120
+ server.close();
121
+ reject(new Error('Failed to get callback server port'));
122
+ return;
123
+ }
124
+ resolve({server, port: addr.port, tokenPromise});
125
+ });
126
+
127
+ server.on('error', (err) => {
128
+ reject(new Error(`Failed to start callback server: ${err.message}`));
129
+ });
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Log in to the amodal platform via browser OAuth.
135
+ *
136
+ * Opens the admin UI's /cli-auth page in the browser. After the user
137
+ * authenticates via Supabase, the admin UI redirects the token back
138
+ * to a local callback server.
139
+ *
140
+ * Returns 0 on success, 1 on error.
141
+ */
142
+ export async function runLogin(options: LoginOptions = {}): Promise<number> {
143
+ const platformUrl = options.platformUrl ?? process.env['PLATFORM_API_URL'] ?? DEFAULT_PLATFORM_URL;
144
+ const adminUrl = options.adminUrl ?? process.env['ADMIN_UI_URL'] ?? DEFAULT_ADMIN_UI_URL;
145
+
146
+ // Check if already logged in
147
+ const rc = await readRcFile();
148
+ if (rc.platform?.url === platformUrl && rc.platform.token) {
149
+ process.stderr.write(`[login] Already logged in to ${platformUrl}\n`);
150
+ process.stderr.write('[login] Run `amodal logout` first, or use --platform-url for a different instance.\n');
151
+ return 0;
152
+ }
153
+
154
+ // Start local callback server
155
+ let server: Server | undefined;
156
+ try {
157
+ const {server: srv, port, tokenPromise} = await startCallbackServer();
158
+ server = srv;
159
+ // Prevent unhandled rejection if tokenPromise rejects after we've moved on
160
+ tokenPromise.catch(() => {});
161
+
162
+ const state = randomUUID();
163
+
164
+ // Build the admin UI login page URL
165
+ const loginUrl = new URL(`${adminUrl}/cli-auth`);
166
+ loginUrl.searchParams.set('port', String(port));
167
+ loginUrl.searchParams.set('state', state);
168
+
169
+ // Open browser
170
+ process.stderr.write('[login] Opening browser for authentication...\n');
171
+ try {
172
+ await open(loginUrl.toString());
173
+ } catch {
174
+ process.stderr.write(`\nOpen this URL in your browser to log in:\n${loginUrl.toString()}\n\n`);
175
+ }
176
+
177
+ process.stderr.write('[login] Waiting for browser login...\n');
178
+
179
+ // Wait for callback or timeout
180
+ const timeoutPromise = new Promise<never>((_resolve, reject) => {
181
+ setTimeout(() => {
182
+ reject(new Error(`Login timed out after ${LOGIN_TIMEOUT_MS / 1000}s`));
183
+ }, LOGIN_TIMEOUT_MS);
184
+ });
185
+
186
+ const result = await Promise.race([tokenPromise, timeoutPromise]);
187
+
188
+ // Verify CSRF state
189
+ if (result.state !== state) {
190
+ process.stderr.write('[login] State mismatch — possible CSRF attack. Login aborted.\n');
191
+ return 1;
192
+ }
193
+
194
+ // Verify the token works by calling /api/me
195
+ process.stderr.write('[login] Verifying credentials...\n');
196
+ const meResponse = await fetch(`${platformUrl}/api/me`, {
197
+ headers: {Authorization: `Bearer ${result.token}`},
198
+ });
199
+
200
+ if (!meResponse.ok) {
201
+ process.stderr.write('[login] Token verification failed. Please try again.\n');
202
+ return 1;
203
+ }
204
+
205
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
206
+ const me = (await meResponse.json()) as Record<string, unknown>;
207
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
208
+ const user = me['user'] as Record<string, string> | null;
209
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
210
+ const org = me['org'] as Record<string, string> | null;
211
+
212
+ // Save credentials
213
+ rc.platform = {
214
+ url: platformUrl,
215
+ token: result.token,
216
+ refreshToken: result.refreshToken || undefined,
217
+ };
218
+ await writeRcFile(rc);
219
+
220
+ const identity = user?.['email'] ?? user?.['name'] ?? 'unknown';
221
+ const orgName = org?.['name'] ?? '';
222
+ process.stderr.write(
223
+ `[login] Logged in as ${identity}${orgName ? ` (org: ${orgName})` : ''}\n`,
224
+ );
225
+ return 0;
226
+ } catch (err) {
227
+ const msg = err instanceof Error ? err.message : String(err);
228
+ process.stderr.write(`[login] ${msg}\n`);
229
+ return 1;
230
+ } finally {
231
+ if (server) {
232
+ server.close();
233
+ }
234
+ }
235
+ }
236
+
237
+ export const loginCommand: CommandModule = {
238
+ command: 'login',
239
+ describe: 'Log in to the amodal platform',
240
+ builder: (yargs) =>
241
+ yargs
242
+ .option('platform-url', {
243
+ type: 'string',
244
+ describe: 'Platform API URL (default: $PLATFORM_API_URL or https://api.amodalai.com)',
245
+ })
246
+ .option('admin-url', {
247
+ type: 'string',
248
+ describe: 'Admin UI URL (default: $ADMIN_UI_URL or https://app.amodalai.com)',
249
+ }),
250
+ handler: async (argv) => {
251
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
252
+ const platformUrl = argv['platformUrl'] as string | undefined;
253
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
254
+ const adminUrl = argv['adminUrl'] as string | undefined;
255
+ const code = await runLogin({platformUrl, adminUrl});
256
+ process.exit(code);
257
+ },
258
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type {CommandModule} from 'yargs';
8
+ import {PlatformClient} from '../shared/platform-client.js';
9
+
10
+ export interface PromoteOptions {
11
+ fromEnv: string;
12
+ toEnv?: string;
13
+ }
14
+
15
+ /**
16
+ * Promote a deployment from one environment to another.
17
+ */
18
+ export async function runPromote(options: PromoteOptions): Promise<number> {
19
+ let client: PlatformClient;
20
+ try {
21
+ client = new PlatformClient();
22
+ } catch (err) {
23
+ const msg = err instanceof Error ? err.message : String(err);
24
+ process.stderr.write(`[promote] ${msg}\n`);
25
+ return 1;
26
+ }
27
+
28
+ const toEnv = options.toEnv ?? 'production';
29
+
30
+ try {
31
+ const result = await client.promote(options.fromEnv, toEnv);
32
+ process.stderr.write(`[promote] Promoted from ${options.fromEnv} to ${toEnv}: ${result.id}\n`);
33
+ return 0;
34
+ } catch (err) {
35
+ const msg = err instanceof Error ? err.message : String(err);
36
+ process.stderr.write(`[promote] Failed: ${msg}\n`);
37
+ return 1;
38
+ }
39
+ }
40
+
41
+ export const promoteCommand: CommandModule = {
42
+ command: 'promote <from-env>',
43
+ describe: 'Promote a deployment to production',
44
+ builder: (yargs) =>
45
+ yargs
46
+ .positional('from-env', {
47
+ type: 'string',
48
+ demandOption: true,
49
+ describe: 'Source environment to promote from',
50
+ })
51
+ .option('to', {
52
+ type: 'string',
53
+ describe: 'Target environment (default: production)',
54
+ }),
55
+ handler: async (argv) => {
56
+ const code = await runPromote({
57
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
58
+ fromEnv: argv['fromEnv'] as string,
59
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
60
+ toEnv: argv['to'] as string | undefined,
61
+ });
62
+ process.exit(code);
63
+ },
64
+ };