@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,94 @@
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 StatusOptions {
11
+ env?: string;
12
+ json?: boolean;
13
+ }
14
+
15
+ /**
16
+ * Show current deployment status per environment.
17
+ */
18
+ export async function runStatus(options: StatusOptions = {}): Promise<number> {
19
+ let client: PlatformClient;
20
+ try {
21
+ client = await PlatformClient.create();
22
+ } catch (err) {
23
+ const msg = err instanceof Error ? err.message : String(err);
24
+ process.stderr.write(`[status] ${msg}\n`);
25
+ return 1;
26
+ }
27
+
28
+ const environments = options.env ? [options.env] : ['production', 'staging'];
29
+
30
+ try {
31
+ const results: Array<{environment: string; id?: string; createdAt?: string; createdBy?: string; commitSha?: string}> = [];
32
+
33
+ for (const env of environments) {
34
+ const deployments = await client.listDeployments({environment: env, limit: 1});
35
+ const active = deployments.find((d) => d.isActive);
36
+ if (active) {
37
+ results.push({
38
+ environment: env,
39
+ id: active.id,
40
+ createdAt: active.createdAt,
41
+ createdBy: active.createdBy ?? undefined,
42
+ commitSha: active.commitSha ?? undefined,
43
+ });
44
+ } else {
45
+ results.push({environment: env});
46
+ }
47
+ }
48
+
49
+ if (options.json) {
50
+ process.stdout.write(JSON.stringify(results, null, 2) + '\n');
51
+ return 0;
52
+ }
53
+
54
+ for (const r of results) {
55
+ if (r.id) {
56
+ const sha = r.commitSha ? ` (${r.commitSha.slice(0, 7)})` : '';
57
+ process.stdout.write(`${r.environment}: ${r.id}${sha} — ${r.createdBy ?? 'unknown'} at ${r.createdAt}\n`);
58
+ } else {
59
+ process.stdout.write(`${r.environment}: no active deployment\n`);
60
+ }
61
+ }
62
+
63
+ return 0;
64
+ } catch (err) {
65
+ const msg = err instanceof Error ? err.message : String(err);
66
+ process.stderr.write(`[status] Failed: ${msg}\n`);
67
+ return 1;
68
+ }
69
+ }
70
+
71
+ export const statusCommand: CommandModule = {
72
+ command: 'status',
73
+ describe: 'Show current deployment status',
74
+ builder: (yargs) =>
75
+ yargs
76
+ .option('env', {
77
+ type: 'string',
78
+ describe: 'Check specific environment',
79
+ })
80
+ .option('json', {
81
+ type: 'boolean',
82
+ describe: 'Output as JSON',
83
+ default: false,
84
+ }),
85
+ handler: async (argv) => {
86
+ const code = await runStatus({
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
88
+ env: argv['env'] as string | undefined,
89
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
90
+ json: argv['json'] as boolean | undefined,
91
+ });
92
+ process.exit(code);
93
+ },
94
+ };
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
8
+
9
+ const mockFindRepoRoot = vi.fn(() => '/test/repo');
10
+ const mockLoadRepo = vi.fn();
11
+ const mockBuildSyncPlan = vi.fn();
12
+
13
+ vi.mock('../shared/repo-discovery.js', () => ({
14
+ findRepoRoot: mockFindRepoRoot,
15
+ }));
16
+
17
+ vi.mock('@amodalai/core', () => ({
18
+ loadRepo: mockLoadRepo,
19
+ buildSyncPlan: mockBuildSyncPlan,
20
+ }));
21
+
22
+ describe('runSync', () => {
23
+ beforeEach(() => {
24
+ vi.clearAllMocks();
25
+ mockFindRepoRoot.mockReturnValue('/test/repo');
26
+ });
27
+
28
+ it('should return 0 when all connections are in sync', async () => {
29
+ mockLoadRepo.mockResolvedValue({
30
+ connections: new Map([['api', {spec: {format: 'openapi', source: 'https://api.test'}}]]),
31
+ });
32
+ mockBuildSyncPlan.mockResolvedValue({
33
+ connectionName: 'api',
34
+ added: [],
35
+ removed: [],
36
+ changed: [],
37
+ unchanged: ['GET /users'],
38
+ });
39
+
40
+ const {runSync} = await import('./sync.js');
41
+ const result = await runSync();
42
+ expect(result).toBe(0);
43
+ });
44
+
45
+ it('should return 1 in check mode when drift detected', async () => {
46
+ mockLoadRepo.mockResolvedValue({
47
+ connections: new Map([['api', {spec: {format: 'openapi', source: 'https://api.test'}}]]),
48
+ });
49
+ mockBuildSyncPlan.mockResolvedValue({
50
+ connectionName: 'api',
51
+ added: [{method: 'GET', path: '/new'}],
52
+ removed: [],
53
+ changed: [],
54
+ unchanged: [],
55
+ });
56
+
57
+ const {runSync} = await import('./sync.js');
58
+ const result = await runSync({check: true});
59
+ expect(result).toBe(1);
60
+ });
61
+
62
+ it('should skip non-openapi connections', async () => {
63
+ mockLoadRepo.mockResolvedValue({
64
+ connections: new Map([['api', {spec: {format: 'graphql', source: 'https://api.test'}}]]),
65
+ });
66
+
67
+ const {runSync} = await import('./sync.js');
68
+ const result = await runSync();
69
+ expect(result).toBe(0);
70
+ expect(mockBuildSyncPlan).not.toHaveBeenCalled();
71
+ });
72
+
73
+ it('should filter by connection name', async () => {
74
+ mockLoadRepo.mockResolvedValue({
75
+ connections: new Map([
76
+ ['api-1', {spec: {format: 'openapi', source: 'https://api1.test'}}],
77
+ ['api-2', {spec: {format: 'openapi', source: 'https://api2.test'}}],
78
+ ]),
79
+ });
80
+ mockBuildSyncPlan.mockResolvedValue({
81
+ connectionName: 'api-1',
82
+ added: [],
83
+ removed: [],
84
+ changed: [],
85
+ unchanged: [],
86
+ });
87
+
88
+ const {runSync} = await import('./sync.js');
89
+ await runSync({connection: 'api-1'});
90
+ expect(mockBuildSyncPlan).toHaveBeenCalledTimes(1);
91
+ });
92
+
93
+ it('should return 1 when repo not found', async () => {
94
+ mockFindRepoRoot.mockImplementation(() => {
95
+ throw new Error('Not found');
96
+ });
97
+
98
+ const {runSync} = await import('./sync.js');
99
+ const result = await runSync();
100
+ expect(result).toBe(1);
101
+ });
102
+
103
+ it('should handle sync errors gracefully', async () => {
104
+ mockLoadRepo.mockResolvedValue({
105
+ connections: new Map([['api', {spec: {format: 'openapi', source: 'https://api.test'}}]]),
106
+ });
107
+ mockBuildSyncPlan.mockRejectedValue(new Error('Fetch failed'));
108
+
109
+ const {runSync} = await import('./sync.js');
110
+ const result = await runSync();
111
+ expect(result).toBe(0);
112
+ });
113
+
114
+ it('should return 0 in check mode when no drift', async () => {
115
+ mockLoadRepo.mockResolvedValue({
116
+ connections: new Map([['api', {spec: {format: 'openapi', source: 'https://api.test'}}]]),
117
+ });
118
+ mockBuildSyncPlan.mockResolvedValue({
119
+ connectionName: 'api',
120
+ added: [],
121
+ removed: [],
122
+ changed: [],
123
+ unchanged: ['GET /users'],
124
+ });
125
+
126
+ const {runSync} = await import('./sync.js');
127
+ const result = await runSync({check: true});
128
+ expect(result).toBe(0);
129
+ });
130
+ });
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {loadRepo,buildSyncPlan} from '@amodalai/core';
8
+ import type {SyncPlan} from '@amodalai/core';
9
+ import type {CommandModule} from 'yargs';
10
+ import {findRepoRoot} from '../shared/repo-discovery.js';
11
+
12
+ export interface SyncOptions {
13
+ cwd?: string;
14
+ /** CI mode — just check, exit 1 if drift detected */
15
+ check?: boolean;
16
+ /** Only sync a specific connection */
17
+ connection?: string;
18
+ }
19
+
20
+ /**
21
+ * For each connection with an OpenAPI spec URL, fetch the spec,
22
+ * detect drift against the surface endpoints, and optionally
23
+ * apply updates interactively.
24
+ */
25
+ export async function runSync(options: SyncOptions = {}): Promise<number> {
26
+ let repoPath: string;
27
+ try {
28
+ repoPath = findRepoRoot(options.cwd);
29
+ } catch (err) {
30
+ const msg = err instanceof Error ? err.message : String(err);
31
+ process.stderr.write(`[sync] ${msg}\n`);
32
+ return 1;
33
+ }
34
+
35
+ process.stderr.write(`[sync] Loading repo from ${repoPath}\n`);
36
+
37
+ const repo = await loadRepo({localPath: repoPath});
38
+ let hasDrift = false;
39
+
40
+ for (const [name, conn] of repo.connections) {
41
+ if (options.connection && name !== options.connection) {
42
+ continue;
43
+ }
44
+
45
+ if (conn.spec.format !== 'openapi') {
46
+ process.stderr.write(`[sync] ${name}: not an openapi connection (${conn.spec.format}), skipping\n`);
47
+ continue;
48
+ }
49
+
50
+ process.stderr.write(`[sync] ${name}: checking for drift...\n`);
51
+
52
+ try {
53
+ const plan = await buildSyncPlan(conn);
54
+ printSyncPlan(name, plan);
55
+
56
+ if (plan.added.length > 0 || plan.removed.length > 0 || plan.changed.length > 0) {
57
+ hasDrift = true;
58
+ }
59
+ } catch (err) {
60
+ const msg = err instanceof Error ? err.message : String(err);
61
+ process.stderr.write(`[sync] ${name}: error — ${msg}\n`);
62
+ }
63
+ }
64
+
65
+ if (options.check) {
66
+ return hasDrift ? 1 : 0;
67
+ }
68
+
69
+ return 0;
70
+ }
71
+
72
+ function printSyncPlan(connectionName: string, plan: SyncPlan): void {
73
+ const total = plan.added.length + plan.removed.length + plan.changed.length;
74
+
75
+ if (total === 0) {
76
+ process.stderr.write(`[sync] ${connectionName}: in sync (${plan.unchanged.length} endpoints)\n`);
77
+ return;
78
+ }
79
+
80
+ process.stderr.write(`[sync] ${connectionName}: ${total} change(s) detected\n`);
81
+
82
+ for (const ep of plan.added) {
83
+ const label = 'method' in ep ? `${ep['method']} ${ep['path']}` : ep.name;
84
+ process.stderr.write(` + ${label}\n`);
85
+ }
86
+
87
+ for (const ep of plan.removed) {
88
+ process.stderr.write(` - ${ep.method} ${ep.path}\n`);
89
+ }
90
+
91
+ for (const change of plan.changed) {
92
+ const label = 'endpoint' in change ? change['endpoint'] : change.name;
93
+ process.stderr.write(` ~ ${label} (${change.changes.join(', ')})\n`);
94
+ }
95
+ }
96
+
97
+ export const syncCommand: CommandModule = {
98
+ command: 'sync',
99
+ describe: 'Check for OpenAPI spec drift',
100
+ builder: {
101
+ check: {
102
+ type: 'boolean' as const,
103
+ default: false,
104
+ describe: 'CI mode — exit 1 if drift detected',
105
+ },
106
+ connection: {
107
+ type: 'string' as const,
108
+ describe: 'Only sync a specific connection',
109
+ },
110
+ },
111
+ handler: async (argv) => {
112
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
113
+ const check = argv['check'] as boolean;
114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
115
+ const connection = argv['connection'] as string | undefined;
116
+ const code = await runSync({check, connection});
117
+ process.exit(code);
118
+ },
119
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {describe, it, expect, vi} from 'vitest';
8
+
9
+ vi.mock('../shared/repo-discovery.js', () => ({
10
+ findRepoRoot: vi.fn(() => '/test/repo'),
11
+ }));
12
+
13
+ vi.mock('@amodalai/runtime', () => ({
14
+ createLocalServer: vi.fn().mockResolvedValue({
15
+ app: {},
16
+ start: vi.fn().mockResolvedValue({address: () => ({port: 9999})}),
17
+ stop: vi.fn().mockResolvedValue(undefined),
18
+ }),
19
+ }));
20
+
21
+ describe('test-query command', () => {
22
+ it('should import without error', async () => {
23
+ const mod = await import('./test-query.js');
24
+ expect(mod.runTestQuery).toBeDefined();
25
+ expect(typeof mod.runTestQuery).toBe('function');
26
+ });
27
+
28
+ it('should require a message', async () => {
29
+ const mod = await import('./test-query.js');
30
+ expect(mod.runTestQuery).toBeDefined();
31
+ });
32
+
33
+ it('should use default tenant ID', async () => {
34
+ const mod = await import('./test-query.js');
35
+ expect(mod.runTestQuery).toBeDefined();
36
+ });
37
+
38
+ it('should accept custom port', async () => {
39
+ const mod = await import('./test-query.js');
40
+ expect(mod.runTestQuery).toBeDefined();
41
+ });
42
+ });
@@ -0,0 +1,129 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type {CommandModule} from 'yargs';
8
+ import {createLocalServer} from '@amodalai/runtime';
9
+ import {findRepoRoot} from '../shared/repo-discovery.js';
10
+
11
+ export interface TestQueryOptions {
12
+ cwd?: string;
13
+ message: string;
14
+ tenantId?: string;
15
+ port?: number;
16
+ }
17
+
18
+ /**
19
+ * Sends a single test query to an ephemeral repo server and streams
20
+ * the response to stdout.
21
+ */
22
+ export async function runTestQuery(options: TestQueryOptions): Promise<void> {
23
+ let repoPath: string;
24
+ try {
25
+ repoPath = findRepoRoot(options.cwd);
26
+ } catch (err) {
27
+ const msg = err instanceof Error ? err.message : String(err);
28
+ process.stderr.write(`[test-query] ${msg}\n`);
29
+ process.exit(1);
30
+ }
31
+
32
+ const port = options.port ?? 0; // 0 = random available port
33
+ const tenantId = options.tenantId ?? 'test-user';
34
+
35
+ process.stderr.write(`[test-query] Loading repo from ${repoPath}\n`);
36
+
37
+ const server = await createLocalServer({
38
+ repoPath,
39
+ port,
40
+ host: '127.0.0.1',
41
+ hotReload: false,
42
+ });
43
+
44
+ const httpServer = await server.start();
45
+ const addr = httpServer.address();
46
+ const actualPort = typeof addr === 'object' && addr !== null ? addr.port : port;
47
+
48
+ try {
49
+ const url = `http://127.0.0.1:${actualPort}/chat`;
50
+ const response = await fetch(url, {
51
+ method: 'POST',
52
+ headers: {'Content-Type': 'application/json'},
53
+ body: JSON.stringify({
54
+ message: options.message,
55
+ tenant_id: tenantId,
56
+ }),
57
+ });
58
+
59
+ if (!response.ok) {
60
+ process.stderr.write(`[test-query] HTTP ${response.status}: ${await response.text()}\n`);
61
+ return;
62
+ }
63
+
64
+ // Parse SSE response
65
+ const text = await response.text();
66
+ const lines = text.split('\n');
67
+
68
+ for (const line of lines) {
69
+ if (!line.startsWith('data: ')) continue;
70
+ const jsonStr = line.substring(6);
71
+ try {
72
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- parsing SSE event
73
+ const event = JSON.parse(jsonStr) as Record<string, unknown>;
74
+ if (event['type'] === 'text_delta') {
75
+ process.stdout.write(String(event['content'] ?? ''));
76
+ } else if (event['type'] === 'tool_call_start') {
77
+ process.stderr.write(`\n[tool] ${event['tool_name']}(${JSON.stringify(event['parameters'])})\n`);
78
+ } else if (event['type'] === 'tool_call_result') {
79
+ const status = event['status'];
80
+ if (status === 'error') {
81
+ process.stderr.write(`[tool] ERROR: ${event['error']}\n`);
82
+ } else {
83
+ const result = String(event['result'] ?? '');
84
+ const preview = result.length > 200 ? result.substring(0, 200) + '...' : result;
85
+ process.stderr.write(`[tool] OK (${event['duration_ms']}ms): ${preview}\n`);
86
+ }
87
+ } else if (event['type'] === 'error') {
88
+ process.stderr.write(`\n[error] ${event['message']}\n`);
89
+ }
90
+ } catch {
91
+ // Skip invalid JSON lines
92
+ }
93
+ }
94
+
95
+ process.stdout.write('\n');
96
+ } finally {
97
+ await server.stop();
98
+ }
99
+ }
100
+
101
+ export const testQueryCommand: CommandModule = {
102
+ command: 'test-query <message>',
103
+ describe: 'Send a test query to the local server',
104
+ builder: (yargs) =>
105
+ yargs
106
+ .positional('message', {
107
+ type: 'string',
108
+ demandOption: true,
109
+ describe: 'The message to send',
110
+ })
111
+ .option('tenant-id', {
112
+ type: 'string',
113
+ describe: 'Tenant ID to use for the query',
114
+ })
115
+ .option('port', {
116
+ type: 'number',
117
+ describe: 'Port for the ephemeral server',
118
+ }),
119
+ handler: async (argv) => {
120
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
121
+ const message = argv['message'] as string;
122
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
123
+ const tenantId = argv['tenant-id'] as string | undefined;
124
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
125
+ const port = argv['port'] as number | undefined;
126
+
127
+ await runTestQuery({message, tenantId, port});
128
+ },
129
+ };
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
8
+
9
+ const mockFindRepoRoot = vi.fn(() => '/test/repo');
10
+ const mockGetLockEntry = vi.fn();
11
+ const mockGetNpmContextPaths = vi.fn();
12
+ const mockMakePackageRef = vi.fn((type: string, name: string) => ({
13
+ type,
14
+ name,
15
+ key: `${type}/${name}`,
16
+ npmName: `@amodalai/${type}-${name}`,
17
+ }));
18
+ const mockNpmUninstall = vi.fn();
19
+ const mockRemoveLockEntry = vi.fn();
20
+ const mockToSymlinkName = vi.fn((type: string, name: string) => `${type}--${name}`);
21
+
22
+ const mockUnlink = vi.fn();
23
+ const mockStat = vi.fn();
24
+
25
+ vi.mock('../shared/repo-discovery.js', () => ({
26
+ findRepoRoot: mockFindRepoRoot,
27
+ }));
28
+
29
+ vi.mock('@amodalai/core', () => ({
30
+ getLockEntry: mockGetLockEntry,
31
+ getNpmContextPaths: mockGetNpmContextPaths,
32
+ makePackageRef: mockMakePackageRef,
33
+ npmUninstall: mockNpmUninstall,
34
+ removeLockEntry: mockRemoveLockEntry,
35
+ toSymlinkName: mockToSymlinkName,
36
+ }));
37
+
38
+ vi.mock('node:fs/promises', () => ({
39
+ unlink: mockUnlink,
40
+ stat: mockStat,
41
+ }));
42
+
43
+ const mockPaths = {
44
+ root: '/test/repo/.amodal/packages',
45
+ npmDir: '/test/repo/.amodal/packages/.npm',
46
+ npmrc: '/test/repo/.amodal/packages/.npm/.npmrc',
47
+ packageJson: '/test/repo/.amodal/packages/.npm/package.json',
48
+ nodeModules: '/test/repo/.amodal/packages/.npm/node_modules',
49
+ };
50
+
51
+ describe('runUninstall', () => {
52
+ let stderrOutput: string;
53
+
54
+ beforeEach(() => {
55
+ vi.clearAllMocks();
56
+ mockFindRepoRoot.mockReturnValue('/test/repo');
57
+ mockGetNpmContextPaths.mockReturnValue(mockPaths);
58
+ mockGetLockEntry.mockResolvedValue({version: '1.0.0', npm: '@amodalai/connection-stripe', integrity: 'sha512-abc'});
59
+ mockNpmUninstall.mockResolvedValue(undefined);
60
+ mockRemoveLockEntry.mockResolvedValue({lockVersion: 1, packages: {}});
61
+ mockUnlink.mockResolvedValue(undefined);
62
+ mockStat.mockRejectedValue(Object.assign(new Error('ENOENT'), {code: 'ENOENT'}));
63
+ stderrOutput = '';
64
+ vi.spyOn(process.stderr, 'write').mockImplementation((chunk) => {
65
+ stderrOutput += String(chunk);
66
+ return true;
67
+ });
68
+ });
69
+
70
+ it('should uninstall a package successfully', async () => {
71
+ const {runUninstall} = await import('./uninstall.js');
72
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
73
+ expect(result).toBe(0);
74
+ expect(mockNpmUninstall).toHaveBeenCalledWith(mockPaths, '@amodalai/connection-stripe');
75
+ expect(mockRemoveLockEntry).toHaveBeenCalledWith('/test/repo', 'connection', 'stripe');
76
+ expect(mockUnlink).toHaveBeenCalled();
77
+ expect(stderrOutput).toContain('Removed connection/stripe');
78
+ });
79
+
80
+ it('should return 1 when package not in lock file', async () => {
81
+ mockGetLockEntry.mockResolvedValue(null);
82
+
83
+ const {runUninstall} = await import('./uninstall.js');
84
+ const result = await runUninstall({type: 'connection', name: 'unknown'});
85
+ expect(result).toBe(1);
86
+ expect(stderrOutput).toContain('not installed');
87
+ expect(mockNpmUninstall).not.toHaveBeenCalled();
88
+ });
89
+
90
+ it('should handle symlink already gone (ENOENT)', async () => {
91
+ mockUnlink.mockRejectedValue(Object.assign(new Error('ENOENT'), {code: 'ENOENT'}));
92
+
93
+ const {runUninstall} = await import('./uninstall.js');
94
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
95
+ expect(result).toBe(0);
96
+ expect(stderrOutput).toContain('Removed connection/stripe');
97
+ });
98
+
99
+ it('should return 1 when npm uninstall fails', async () => {
100
+ mockNpmUninstall.mockRejectedValue(new Error('npm error'));
101
+
102
+ const {runUninstall} = await import('./uninstall.js');
103
+ const result = await runUninstall({type: 'skill', name: 'triage'});
104
+ expect(result).toBe(1);
105
+ expect(stderrOutput).toContain('npm uninstall failed');
106
+ });
107
+
108
+ it('should return 1 when repo not found', async () => {
109
+ mockFindRepoRoot.mockImplementation(() => {
110
+ throw new Error('Not found');
111
+ });
112
+
113
+ const {runUninstall} = await import('./uninstall.js');
114
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
115
+ expect(result).toBe(1);
116
+ expect(stderrOutput).toContain('Not found');
117
+ });
118
+
119
+ it('should print note when override directory exists', async () => {
120
+ mockStat.mockResolvedValue({isDirectory: () => true});
121
+
122
+ const {runUninstall} = await import('./uninstall.js');
123
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
124
+ expect(result).toBe(0);
125
+ expect(stderrOutput).toContain('local override directory still exists');
126
+ });
127
+
128
+ it('should pass cwd to findRepoRoot', async () => {
129
+ const {runUninstall} = await import('./uninstall.js');
130
+ await runUninstall({cwd: '/custom/dir', type: 'connection', name: 'test'});
131
+ expect(mockFindRepoRoot).toHaveBeenCalledWith('/custom/dir');
132
+ });
133
+
134
+ it('should warn but succeed when symlink removal fails with non-ENOENT error', async () => {
135
+ mockUnlink.mockRejectedValue(Object.assign(new Error('EPERM'), {code: 'EPERM'}));
136
+
137
+ const {runUninstall} = await import('./uninstall.js');
138
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
139
+ expect(result).toBe(0);
140
+ expect(stderrOutput).toContain('could not remove symlink');
141
+ });
142
+
143
+ it('should use correct override dir path with plural type', async () => {
144
+ mockStat.mockResolvedValue({isDirectory: () => true});
145
+
146
+ const {runUninstall} = await import('./uninstall.js');
147
+ await runUninstall({type: 'skill', name: 'triage'});
148
+ // Override dir: skills/triage
149
+ expect(mockStat).toHaveBeenCalledWith(
150
+ expect.stringContaining('skills/triage'),
151
+ );
152
+ });
153
+
154
+ it('should handle no override dir without error', async () => {
155
+ mockStat.mockRejectedValue(Object.assign(new Error('ENOENT'), {code: 'ENOENT'}));
156
+
157
+ const {runUninstall} = await import('./uninstall.js');
158
+ const result = await runUninstall({type: 'connection', name: 'stripe'});
159
+ expect(result).toBe(0);
160
+ expect(stderrOutput).not.toContain('override');
161
+ });
162
+ });