@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.
- package/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/src/auth/index.d.ts +13 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +10 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/oauth2.d.ts +51 -0
- package/dist/src/auth/oauth2.d.ts.map +1 -0
- package/dist/src/auth/oauth2.js +196 -0
- package/dist/src/auth/oauth2.js.map +1 -0
- package/dist/src/auth/prompt.d.ts +21 -0
- package/dist/src/auth/prompt.d.ts.map +1 -0
- package/dist/src/auth/prompt.js +81 -0
- package/dist/src/auth/prompt.js.map +1 -0
- package/dist/src/auth/test-connection.d.ts +27 -0
- package/dist/src/auth/test-connection.d.ts.map +1 -0
- package/dist/src/auth/test-connection.js +153 -0
- package/dist/src/auth/test-connection.js.map +1 -0
- package/dist/src/auth/types.d.ts +32 -0
- package/dist/src/auth/types.d.ts.map +1 -0
- package/dist/src/auth/types.js +7 -0
- package/dist/src/auth/types.js.map +1 -0
- package/dist/src/commands/audit.d.ts +18 -0
- package/dist/src/commands/audit.d.ts.map +1 -0
- package/dist/src/commands/audit.js +86 -0
- package/dist/src/commands/audit.js.map +1 -0
- package/dist/src/commands/automations.d.ts +28 -0
- package/dist/src/commands/automations.d.ts.map +1 -0
- package/dist/src/commands/automations.js +179 -0
- package/dist/src/commands/automations.js.map +1 -0
- package/dist/src/commands/build-manifest-types.d.ts +33 -0
- package/dist/src/commands/build-manifest-types.d.ts.map +1 -0
- package/dist/src/commands/build-manifest-types.js +30 -0
- package/dist/src/commands/build-manifest-types.js.map +1 -0
- package/dist/src/commands/build-tools.d.ts +33 -0
- package/dist/src/commands/build-tools.d.ts.map +1 -0
- package/dist/src/commands/build-tools.js +237 -0
- package/dist/src/commands/build-tools.js.map +1 -0
- package/dist/src/commands/build.d.ts +23 -0
- package/dist/src/commands/build.d.ts.map +1 -0
- package/dist/src/commands/build.js +120 -0
- package/dist/src/commands/build.js.map +1 -0
- package/dist/src/commands/chat.d.ts +26 -0
- package/dist/src/commands/chat.d.ts.map +1 -0
- package/dist/src/commands/chat.js +123 -0
- package/dist/src/commands/chat.js.map +1 -0
- package/dist/src/commands/connect.d.ts +18 -0
- package/dist/src/commands/connect.d.ts.map +1 -0
- package/dist/src/commands/connect.js +198 -0
- package/dist/src/commands/connect.js.map +1 -0
- package/dist/src/commands/deploy.d.ts +20 -0
- package/dist/src/commands/deploy.d.ts.map +1 -0
- package/dist/src/commands/deploy.js +137 -0
- package/dist/src/commands/deploy.js.map +1 -0
- package/dist/src/commands/deployments.d.ts +17 -0
- package/dist/src/commands/deployments.d.ts.map +1 -0
- package/dist/src/commands/deployments.js +77 -0
- package/dist/src/commands/deployments.js.map +1 -0
- package/dist/src/commands/dev.d.ts +17 -0
- package/dist/src/commands/dev.d.ts.map +1 -0
- package/dist/src/commands/dev.js +109 -0
- package/dist/src/commands/dev.js.map +1 -0
- package/dist/src/commands/diff.d.ts +19 -0
- package/dist/src/commands/diff.d.ts.map +1 -0
- package/dist/src/commands/diff.js +120 -0
- package/dist/src/commands/diff.js.map +1 -0
- package/dist/src/commands/docker.d.ts +21 -0
- package/dist/src/commands/docker.d.ts.map +1 -0
- package/dist/src/commands/docker.js +215 -0
- package/dist/src/commands/docker.js.map +1 -0
- package/dist/src/commands/eval.d.ts +20 -0
- package/dist/src/commands/eval.d.ts.map +1 -0
- package/dist/src/commands/eval.js +236 -0
- package/dist/src/commands/eval.js.map +1 -0
- package/dist/src/commands/experiment.d.ts +21 -0
- package/dist/src/commands/experiment.d.ts.map +1 -0
- package/dist/src/commands/experiment.js +133 -0
- package/dist/src/commands/experiment.js.map +1 -0
- package/dist/src/commands/index.d.ts +10 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +75 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +73 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/inspect.d.ts +22 -0
- package/dist/src/commands/inspect.d.ts.map +1 -0
- package/dist/src/commands/inspect.js +131 -0
- package/dist/src/commands/inspect.js.map +1 -0
- package/dist/src/commands/install-pkg.d.ts +29 -0
- package/dist/src/commands/install-pkg.d.ts.map +1 -0
- package/dist/src/commands/install-pkg.js +202 -0
- package/dist/src/commands/install-pkg.js.map +1 -0
- package/dist/src/commands/link.d.ts +32 -0
- package/dist/src/commands/link.d.ts.map +1 -0
- package/dist/src/commands/link.js +227 -0
- package/dist/src/commands/link.js.map +1 -0
- package/dist/src/commands/list.d.ts +19 -0
- package/dist/src/commands/list.d.ts.map +1 -0
- package/dist/src/commands/list.js +78 -0
- package/dist/src/commands/list.js.map +1 -0
- package/dist/src/commands/login.d.ts +31 -0
- package/dist/src/commands/login.d.ts.map +1 -0
- package/dist/src/commands/login.js +205 -0
- package/dist/src/commands/login.js.map +1 -0
- package/dist/src/commands/promote.d.ts +16 -0
- package/dist/src/commands/promote.d.ts.map +1 -0
- package/dist/src/commands/promote.js +55 -0
- package/dist/src/commands/promote.js.map +1 -0
- package/dist/src/commands/publish.d.ts +18 -0
- package/dist/src/commands/publish.d.ts.map +1 -0
- package/dist/src/commands/publish.js +122 -0
- package/dist/src/commands/publish.js.map +1 -0
- package/dist/src/commands/rollback.d.ts +17 -0
- package/dist/src/commands/rollback.d.ts.map +1 -0
- package/dist/src/commands/rollback.js +62 -0
- package/dist/src/commands/rollback.js.map +1 -0
- package/dist/src/commands/search.d.ts +20 -0
- package/dist/src/commands/search.d.ts.map +1 -0
- package/dist/src/commands/search.js +133 -0
- package/dist/src/commands/search.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +20 -0
- package/dist/src/commands/secrets.d.ts.map +1 -0
- package/dist/src/commands/secrets.js +137 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/serve.d.ts +23 -0
- package/dist/src/commands/serve.d.ts.map +1 -0
- package/dist/src/commands/serve.js +144 -0
- package/dist/src/commands/serve.js.map +1 -0
- package/dist/src/commands/status.d.ts +16 -0
- package/dist/src/commands/status.d.ts.map +1 -0
- package/dist/src/commands/status.js +83 -0
- package/dist/src/commands/status.js.map +1 -0
- package/dist/src/commands/sync.d.ts +21 -0
- package/dist/src/commands/sync.d.ts.map +1 -0
- package/dist/src/commands/sync.js +94 -0
- package/dist/src/commands/sync.js.map +1 -0
- package/dist/src/commands/test-query.d.ts +19 -0
- package/dist/src/commands/test-query.d.ts.map +1 -0
- package/dist/src/commands/test-query.js +116 -0
- package/dist/src/commands/test-query.js.map +1 -0
- package/dist/src/commands/uninstall.d.ts +19 -0
- package/dist/src/commands/uninstall.d.ts.map +1 -0
- package/dist/src/commands/uninstall.js +84 -0
- package/dist/src/commands/uninstall.js.map +1 -0
- package/dist/src/commands/update.d.ts +21 -0
- package/dist/src/commands/update.d.ts.map +1 -0
- package/dist/src/commands/update.js +145 -0
- package/dist/src/commands/update.js.map +1 -0
- package/dist/src/commands/validate.d.ts +19 -0
- package/dist/src/commands/validate.d.ts.map +1 -0
- package/dist/src/commands/validate.js +114 -0
- package/dist/src/commands/validate.js.map +1 -0
- package/dist/src/fixtures/incident-response.d.ts +91 -0
- package/dist/src/fixtures/incident-response.d.ts.map +1 -0
- package/dist/src/fixtures/incident-response.js +208 -0
- package/dist/src/fixtures/incident-response.js.map +1 -0
- package/dist/src/main.d.ts +8 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +30 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/shared/platform-client.d.ts +92 -0
- package/dist/src/shared/platform-client.d.ts.map +1 -0
- package/dist/src/shared/platform-client.js +155 -0
- package/dist/src/shared/platform-client.js.map +1 -0
- package/dist/src/shared/repo-discovery.d.ts +11 -0
- package/dist/src/shared/repo-discovery.d.ts.map +1 -0
- package/dist/src/shared/repo-discovery.js +33 -0
- package/dist/src/shared/repo-discovery.js.map +1 -0
- package/dist/src/templates/compose-template.d.ts +10 -0
- package/dist/src/templates/compose-template.d.ts.map +1 -0
- package/dist/src/templates/compose-template.js +30 -0
- package/dist/src/templates/compose-template.js.map +1 -0
- package/dist/src/templates/config-template.d.ts +14 -0
- package/dist/src/templates/config-template.d.ts.map +1 -0
- package/dist/src/templates/config-template.js +35 -0
- package/dist/src/templates/config-template.js.map +1 -0
- package/dist/src/templates/dockerfile-template.d.ts +10 -0
- package/dist/src/templates/dockerfile-template.d.ts.map +1 -0
- package/dist/src/templates/dockerfile-template.js +30 -0
- package/dist/src/templates/dockerfile-template.js.map +1 -0
- package/dist/src/templates/env-template.d.ts +12 -0
- package/dist/src/templates/env-template.d.ts.map +1 -0
- package/dist/src/templates/env-template.js +24 -0
- package/dist/src/templates/env-template.js.map +1 -0
- package/dist/src/templates/knowledge-template.d.ts +10 -0
- package/dist/src/templates/knowledge-template.d.ts.map +1 -0
- package/dist/src/templates/knowledge-template.js +24 -0
- package/dist/src/templates/knowledge-template.js.map +1 -0
- package/dist/src/templates/skill-template.d.ts +10 -0
- package/dist/src/templates/skill-template.d.ts.map +1 -0
- package/dist/src/templates/skill-template.js +27 -0
- package/dist/src/templates/skill-template.js.map +1 -0
- package/dist/src/ui/AskUserPrompt.d.ts +14 -0
- package/dist/src/ui/AskUserPrompt.d.ts.map +1 -0
- package/dist/src/ui/AskUserPrompt.js +17 -0
- package/dist/src/ui/AskUserPrompt.js.map +1 -0
- package/dist/src/ui/AssistantMessage.d.ts +14 -0
- package/dist/src/ui/AssistantMessage.d.ts.map +1 -0
- package/dist/src/ui/AssistantMessage.js +8 -0
- package/dist/src/ui/AssistantMessage.js.map +1 -0
- package/dist/src/ui/ChatApp.d.ts +15 -0
- package/dist/src/ui/ChatApp.d.ts.map +1 -0
- package/dist/src/ui/ChatApp.js +144 -0
- package/dist/src/ui/ChatApp.js.map +1 -0
- package/dist/src/ui/ConfirmationPrompt.d.ts +17 -0
- package/dist/src/ui/ConfirmationPrompt.d.ts.map +1 -0
- package/dist/src/ui/ConfirmationPrompt.js +21 -0
- package/dist/src/ui/ConfirmationPrompt.js.map +1 -0
- package/dist/src/ui/DiffRenderer.d.ts +32 -0
- package/dist/src/ui/DiffRenderer.d.ts.map +1 -0
- package/dist/src/ui/DiffRenderer.js +118 -0
- package/dist/src/ui/DiffRenderer.js.map +1 -0
- package/dist/src/ui/ExpandableContent.d.ts +15 -0
- package/dist/src/ui/ExpandableContent.d.ts.map +1 -0
- package/dist/src/ui/ExpandableContent.js +22 -0
- package/dist/src/ui/ExpandableContent.js.map +1 -0
- package/dist/src/ui/ExploreIndicator.d.ts +13 -0
- package/dist/src/ui/ExploreIndicator.d.ts.map +1 -0
- package/dist/src/ui/ExploreIndicator.js +14 -0
- package/dist/src/ui/ExploreIndicator.js.map +1 -0
- package/dist/src/ui/Footer.d.ts +19 -0
- package/dist/src/ui/Footer.d.ts.map +1 -0
- package/dist/src/ui/Footer.js +57 -0
- package/dist/src/ui/Footer.js.map +1 -0
- package/dist/src/ui/FullScreenLayout.d.ts +18 -0
- package/dist/src/ui/FullScreenLayout.d.ts.map +1 -0
- package/dist/src/ui/FullScreenLayout.js +14 -0
- package/dist/src/ui/FullScreenLayout.js.map +1 -0
- package/dist/src/ui/Header.d.ts +14 -0
- package/dist/src/ui/Header.d.ts.map +1 -0
- package/dist/src/ui/Header.js +11 -0
- package/dist/src/ui/Header.js.map +1 -0
- package/dist/src/ui/InputBar.d.ts +17 -0
- package/dist/src/ui/InputBar.d.ts.map +1 -0
- package/dist/src/ui/InputBar.js +49 -0
- package/dist/src/ui/InputBar.js.map +1 -0
- package/dist/src/ui/MessageList.d.ts +18 -0
- package/dist/src/ui/MessageList.d.ts.map +1 -0
- package/dist/src/ui/MessageList.js +9 -0
- package/dist/src/ui/MessageList.js.map +1 -0
- package/dist/src/ui/NotificationBar.d.ts +14 -0
- package/dist/src/ui/NotificationBar.d.ts.map +1 -0
- package/dist/src/ui/NotificationBar.js +38 -0
- package/dist/src/ui/NotificationBar.js.map +1 -0
- package/dist/src/ui/ScrollableMessageList.d.ts +27 -0
- package/dist/src/ui/ScrollableMessageList.d.ts.map +1 -0
- package/dist/src/ui/ScrollableMessageList.js +16 -0
- package/dist/src/ui/ScrollableMessageList.js.map +1 -0
- package/dist/src/ui/SessionBrowser.d.ts +20 -0
- package/dist/src/ui/SessionBrowser.d.ts.map +1 -0
- package/dist/src/ui/SessionBrowser.js +93 -0
- package/dist/src/ui/SessionBrowser.js.map +1 -0
- package/dist/src/ui/StatusMessage.d.ts +13 -0
- package/dist/src/ui/StatusMessage.d.ts.map +1 -0
- package/dist/src/ui/StatusMessage.js +17 -0
- package/dist/src/ui/StatusMessage.js.map +1 -0
- package/dist/src/ui/StreamingView.d.ts +19 -0
- package/dist/src/ui/StreamingView.d.ts.map +1 -0
- package/dist/src/ui/StreamingView.js +18 -0
- package/dist/src/ui/StreamingView.js.map +1 -0
- package/dist/src/ui/SubagentDisplay.d.ts +13 -0
- package/dist/src/ui/SubagentDisplay.d.ts.map +1 -0
- package/dist/src/ui/SubagentDisplay.js +22 -0
- package/dist/src/ui/SubagentDisplay.js.map +1 -0
- package/dist/src/ui/ThinkingDisplay.d.ts +13 -0
- package/dist/src/ui/ThinkingDisplay.d.ts.map +1 -0
- package/dist/src/ui/ThinkingDisplay.js +15 -0
- package/dist/src/ui/ThinkingDisplay.js.map +1 -0
- package/dist/src/ui/ToolCallDisplay.d.ts +16 -0
- package/dist/src/ui/ToolCallDisplay.d.ts.map +1 -0
- package/dist/src/ui/ToolCallDisplay.js +136 -0
- package/dist/src/ui/ToolCallDisplay.js.map +1 -0
- package/dist/src/ui/UserMessage.d.ts +12 -0
- package/dist/src/ui/UserMessage.d.ts.map +1 -0
- package/dist/src/ui/UserMessage.js +5 -0
- package/dist/src/ui/UserMessage.js.map +1 -0
- package/dist/src/ui/commands/clear.d.ts +7 -0
- package/dist/src/ui/commands/clear.d.ts.map +1 -0
- package/dist/src/ui/commands/clear.js +13 -0
- package/dist/src/ui/commands/clear.js.map +1 -0
- package/dist/src/ui/commands/help.d.ts +7 -0
- package/dist/src/ui/commands/help.d.ts.map +1 -0
- package/dist/src/ui/commands/help.js +26 -0
- package/dist/src/ui/commands/help.js.map +1 -0
- package/dist/src/ui/commands/index.d.ts +14 -0
- package/dist/src/ui/commands/index.d.ts.map +1 -0
- package/dist/src/ui/commands/index.js +15 -0
- package/dist/src/ui/commands/index.js.map +1 -0
- package/dist/src/ui/commands/model.d.ts +7 -0
- package/dist/src/ui/commands/model.d.ts.map +1 -0
- package/dist/src/ui/commands/model.js +16 -0
- package/dist/src/ui/commands/model.js.map +1 -0
- package/dist/src/ui/commands/registry.d.ts +30 -0
- package/dist/src/ui/commands/registry.d.ts.map +1 -0
- package/dist/src/ui/commands/registry.js +45 -0
- package/dist/src/ui/commands/registry.js.map +1 -0
- package/dist/src/ui/commands/sessions.d.ts +7 -0
- package/dist/src/ui/commands/sessions.d.ts.map +1 -0
- package/dist/src/ui/commands/sessions.js +13 -0
- package/dist/src/ui/commands/sessions.js.map +1 -0
- package/dist/src/ui/commands/stats.d.ts +7 -0
- package/dist/src/ui/commands/stats.d.ts.map +1 -0
- package/dist/src/ui/commands/stats.js +33 -0
- package/dist/src/ui/commands/stats.js.map +1 -0
- package/dist/src/ui/commands/theme.d.ts +7 -0
- package/dist/src/ui/commands/theme.d.ts.map +1 -0
- package/dist/src/ui/commands/theme.js +35 -0
- package/dist/src/ui/commands/theme.js.map +1 -0
- package/dist/src/ui/markdown/CodeBlock.d.ts +14 -0
- package/dist/src/ui/markdown/CodeBlock.d.ts.map +1 -0
- package/dist/src/ui/markdown/CodeBlock.js +55 -0
- package/dist/src/ui/markdown/CodeBlock.js.map +1 -0
- package/dist/src/ui/markdown/InlineRenderer.d.ts +12 -0
- package/dist/src/ui/markdown/InlineRenderer.d.ts.map +1 -0
- package/dist/src/ui/markdown/InlineRenderer.js +70 -0
- package/dist/src/ui/markdown/InlineRenderer.js.map +1 -0
- package/dist/src/ui/markdown/MarkdownDisplay.d.ts +17 -0
- package/dist/src/ui/markdown/MarkdownDisplay.d.ts.map +1 -0
- package/dist/src/ui/markdown/MarkdownDisplay.js +142 -0
- package/dist/src/ui/markdown/MarkdownDisplay.js.map +1 -0
- package/dist/src/ui/markdown/Table.d.ts +14 -0
- package/dist/src/ui/markdown/Table.d.ts.map +1 -0
- package/dist/src/ui/markdown/Table.js +31 -0
- package/dist/src/ui/markdown/Table.js.map +1 -0
- package/dist/src/ui/theme.d.ts +39 -0
- package/dist/src/ui/theme.d.ts.map +1 -0
- package/dist/src/ui/theme.js +39 -0
- package/dist/src/ui/theme.js.map +1 -0
- package/dist/src/ui/themes/index.d.ts +45 -0
- package/dist/src/ui/themes/index.d.ts.map +1 -0
- package/dist/src/ui/themes/index.js +73 -0
- package/dist/src/ui/themes/index.js.map +1 -0
- package/dist/src/ui/themes/light.d.ts +8 -0
- package/dist/src/ui/themes/light.d.ts.map +1 -0
- package/dist/src/ui/themes/light.js +37 -0
- package/dist/src/ui/themes/light.js.map +1 -0
- package/dist/src/ui/themes/monochrome.d.ts +8 -0
- package/dist/src/ui/themes/monochrome.d.ts.map +1 -0
- package/dist/src/ui/themes/monochrome.js +37 -0
- package/dist/src/ui/themes/monochrome.js.map +1 -0
- package/dist/src/ui/types.d.ts +191 -0
- package/dist/src/ui/types.d.ts.map +1 -0
- package/dist/src/ui/types.js +7 -0
- package/dist/src/ui/types.js.map +1 -0
- package/dist/src/ui/useAlternateBuffer.d.ts +11 -0
- package/dist/src/ui/useAlternateBuffer.d.ts.map +1 -0
- package/dist/src/ui/useAlternateBuffer.js +25 -0
- package/dist/src/ui/useAlternateBuffer.js.map +1 -0
- package/dist/src/ui/useChat.d.ts +18 -0
- package/dist/src/ui/useChat.d.ts.map +1 -0
- package/dist/src/ui/useChat.js +599 -0
- package/dist/src/ui/useChat.js.map +1 -0
- package/dist/src/ui/useElapsedTime.d.ts +11 -0
- package/dist/src/ui/useElapsedTime.d.ts.map +1 -0
- package/dist/src/ui/useElapsedTime.js +39 -0
- package/dist/src/ui/useElapsedTime.js.map +1 -0
- package/dist/src/ui/useResponsiveLayout.d.ts +16 -0
- package/dist/src/ui/useResponsiveLayout.d.ts.map +1 -0
- package/dist/src/ui/useResponsiveLayout.js +24 -0
- package/dist/src/ui/useResponsiveLayout.js.map +1 -0
- package/dist/src/ui/useScroll.d.ts +20 -0
- package/dist/src/ui/useScroll.d.ts.map +1 -0
- package/dist/src/ui/useScroll.js +64 -0
- package/dist/src/ui/useScroll.js.map +1 -0
- package/dist/src/ui/useSessionResume.d.ts +20 -0
- package/dist/src/ui/useSessionResume.d.ts.map +1 -0
- package/dist/src/ui/useSessionResume.js +77 -0
- package/dist/src/ui/useSessionResume.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +60 -0
- package/src/auth/index.ts +13 -0
- package/src/auth/oauth2.test.ts +305 -0
- package/src/auth/oauth2.ts +269 -0
- package/src/auth/prompt.test.ts +205 -0
- package/src/auth/prompt.ts +111 -0
- package/src/auth/test-connection.test.ts +224 -0
- package/src/auth/test-connection.ts +196 -0
- package/src/auth/types.ts +34 -0
- package/src/commands/audit.test.ts +92 -0
- package/src/commands/audit.ts +113 -0
- package/src/commands/automations.test.ts +85 -0
- package/src/commands/automations.ts +205 -0
- package/src/commands/build-manifest-types.ts +35 -0
- package/src/commands/build-tools.ts +281 -0
- package/src/commands/build.test.ts +63 -0
- package/src/commands/build.ts +135 -0
- package/src/commands/chat.ts +147 -0
- package/src/commands/command-exports.test.ts +88 -0
- package/src/commands/connect.test.ts +343 -0
- package/src/commands/connect.ts +237 -0
- package/src/commands/deploy.test.ts +124 -0
- package/src/commands/deploy.ts +153 -0
- package/src/commands/deployments.ts +90 -0
- package/src/commands/dev.test.ts +63 -0
- package/src/commands/dev.ts +124 -0
- package/src/commands/diff.test.ts +183 -0
- package/src/commands/diff.ts +143 -0
- package/src/commands/docker.ts +232 -0
- package/src/commands/eval.test.ts +88 -0
- package/src/commands/eval.ts +268 -0
- package/src/commands/experiment.test.ts +125 -0
- package/src/commands/experiment.ts +153 -0
- package/src/commands/index.ts +76 -0
- package/src/commands/init.test.ts +109 -0
- package/src/commands/init.ts +98 -0
- package/src/commands/inspect.test.ts +234 -0
- package/src/commands/inspect.ts +157 -0
- package/src/commands/install-pkg.test.ts +265 -0
- package/src/commands/install-pkg.ts +234 -0
- package/src/commands/link.ts +270 -0
- package/src/commands/list.test.ts +152 -0
- package/src/commands/list.ts +95 -0
- package/src/commands/login.test.ts +195 -0
- package/src/commands/login.ts +258 -0
- package/src/commands/promote.ts +64 -0
- package/src/commands/publish.test.ts +203 -0
- package/src/commands/publish.ts +142 -0
- package/src/commands/rollback.ts +72 -0
- package/src/commands/search.test.ts +174 -0
- package/src/commands/search.ts +154 -0
- package/src/commands/secrets.test.ts +168 -0
- package/src/commands/secrets.ts +163 -0
- package/src/commands/serve.ts +166 -0
- package/src/commands/status.ts +94 -0
- package/src/commands/sync.test.ts +130 -0
- package/src/commands/sync.ts +119 -0
- package/src/commands/test-query.test.ts +42 -0
- package/src/commands/test-query.ts +129 -0
- package/src/commands/uninstall.test.ts +162 -0
- package/src/commands/uninstall.ts +107 -0
- package/src/commands/update.test.ts +281 -0
- package/src/commands/update.ts +180 -0
- package/src/commands/validate.test.ts +260 -0
- package/src/commands/validate.ts +139 -0
- package/src/e2e-automations.test.ts +305 -0
- package/src/e2e-commands.test.ts +587 -0
- package/src/e2e-incident-response.test.ts +345 -0
- package/src/e2e-plugin-connections.test.ts +415 -0
- package/src/e2e-plugins.test.ts +492 -0
- package/src/e2e.test.ts +602 -0
- package/src/fixtures/incident-response.ts +232 -0
- package/src/main.ts +35 -0
- package/src/shared/platform-client.test.ts +106 -0
- package/src/shared/platform-client.ts +193 -0
- package/src/shared/repo-discovery.test.ts +56 -0
- package/src/shared/repo-discovery.ts +40 -0
- package/src/templates/compose-template.ts +30 -0
- package/src/templates/config-template.ts +44 -0
- package/src/templates/deployment-templates.test.ts +99 -0
- package/src/templates/dockerfile-template.ts +30 -0
- package/src/templates/env-template.ts +27 -0
- package/src/templates/knowledge-template.ts +24 -0
- package/src/templates/skill-template.ts +27 -0
- package/src/ui/AskUserPrompt.tsx +58 -0
- package/src/ui/AssistantMessage.tsx +51 -0
- package/src/ui/ChatApp.tsx +283 -0
- package/src/ui/ConfirmationPrompt.tsx +75 -0
- package/src/ui/DiffRenderer.test.ts +104 -0
- package/src/ui/DiffRenderer.tsx +188 -0
- package/src/ui/ExpandableContent.tsx +68 -0
- package/src/ui/ExploreIndicator.tsx +44 -0
- package/src/ui/Footer.tsx +87 -0
- package/src/ui/FullScreenLayout.tsx +45 -0
- package/src/ui/Header.tsx +50 -0
- package/src/ui/InputBar.tsx +105 -0
- package/src/ui/MessageList.tsx +31 -0
- package/src/ui/NotificationBar.tsx +64 -0
- package/src/ui/ScrollableMessageList.tsx +82 -0
- package/src/ui/SessionBrowser.test.ts +49 -0
- package/src/ui/SessionBrowser.tsx +179 -0
- package/src/ui/StatusMessage.tsx +35 -0
- package/src/ui/StreamingView.tsx +87 -0
- package/src/ui/SubagentDisplay.tsx +57 -0
- package/src/ui/ThinkingDisplay.tsx +45 -0
- package/src/ui/ToolCallDisplay.tsx +268 -0
- package/src/ui/UserMessage.tsx +22 -0
- package/src/ui/chat-e2e.test.ts +581 -0
- package/src/ui/commands/clear.ts +15 -0
- package/src/ui/commands/help.ts +31 -0
- package/src/ui/commands/index.ts +22 -0
- package/src/ui/commands/model.ts +19 -0
- package/src/ui/commands/registry.test.ts +76 -0
- package/src/ui/commands/registry.ts +66 -0
- package/src/ui/commands/sessions.ts +16 -0
- package/src/ui/commands/stats.ts +35 -0
- package/src/ui/commands/theme.ts +41 -0
- package/src/ui/markdown/CodeBlock.tsx +118 -0
- package/src/ui/markdown/InlineRenderer.tsx +115 -0
- package/src/ui/markdown/MarkdownDisplay.tsx +223 -0
- package/src/ui/markdown/Table.tsx +75 -0
- package/src/ui/theme.ts +39 -0
- package/src/ui/themes/index.ts +113 -0
- package/src/ui/themes/light.ts +39 -0
- package/src/ui/themes/monochrome.ts +39 -0
- package/src/ui/types.ts +157 -0
- package/src/ui/useAlternateBuffer.ts +27 -0
- package/src/ui/useChat.test.ts +492 -0
- package/src/ui/useChat.ts +693 -0
- package/src/ui/useElapsedTime.test.ts +33 -0
- package/src/ui/useElapsedTime.ts +43 -0
- package/src/ui/useResponsiveLayout.test.ts +54 -0
- package/src/ui/useResponsiveLayout.ts +32 -0
- package/src/ui/useScroll.test.ts +99 -0
- package/src/ui/useScroll.ts +97 -0
- package/src/ui/useSessionResume.test.ts +80 -0
- package/src/ui/useSessionResume.ts +102 -0
- package/tsconfig.json +17 -0
- package/vitest.config.ts +20 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Fixture data for the incident response e2e test.
|
|
9
|
+
*
|
|
10
|
+
* Four content types:
|
|
11
|
+
* 1. Connection: statuspage API (mock)
|
|
12
|
+
* 2. Skill: incident triage methodology
|
|
13
|
+
* 3. Knowledge: oncall runbook
|
|
14
|
+
* 4. Automation: daily health check
|
|
15
|
+
*
|
|
16
|
+
* The mock API returns deterministic data so we can assert on the
|
|
17
|
+
* agent's response content.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import http from 'node:http';
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// amodal.json
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
export const CONFIG = {
|
|
27
|
+
name: 'incident-response-agent',
|
|
28
|
+
version: '1.0.0',
|
|
29
|
+
description: 'Monitors services and triages incidents',
|
|
30
|
+
models: {
|
|
31
|
+
main: {provider: 'anthropic', model: 'claude-sonnet-4-20250514'},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Connection: statuspage
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
export const STATUSPAGE_SPEC = {
|
|
40
|
+
source: 'https://statuspage.example.com/api/v1/openapi.json',
|
|
41
|
+
format: 'openapi' as const,
|
|
42
|
+
auth: {
|
|
43
|
+
type: 'bearer',
|
|
44
|
+
header: 'Authorization',
|
|
45
|
+
prefix: 'Bearer',
|
|
46
|
+
token: 'env:STATUSPAGE_TOKEN',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const STATUSPAGE_ACCESS = {
|
|
51
|
+
endpoints: {
|
|
52
|
+
'GET /components': {returns: ['id', 'name', 'status', 'updated_at']},
|
|
53
|
+
'GET /incidents': {returns: ['id', 'name', 'status', 'impact', 'created_at']},
|
|
54
|
+
'GET /incidents/:id': {returns: ['id', 'name', 'status', 'impact', 'body', 'components']},
|
|
55
|
+
'POST /incidents': {returns: ['id'], confirm: 'review' as const},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const STATUSPAGE_SURFACE = `## Included
|
|
60
|
+
|
|
61
|
+
### GET /components
|
|
62
|
+
List all monitored components and their current status
|
|
63
|
+
|
|
64
|
+
### GET /incidents
|
|
65
|
+
List recent incidents
|
|
66
|
+
|
|
67
|
+
### GET /incidents/:id
|
|
68
|
+
Get incident details
|
|
69
|
+
|
|
70
|
+
## Excluded
|
|
71
|
+
|
|
72
|
+
### POST /incidents
|
|
73
|
+
Create a new incident (requires confirmation)
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Skill: incident-triage
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
export const TRIAGE_SKILL = `---
|
|
81
|
+
name: incident-triage
|
|
82
|
+
description: Methodology for triaging service incidents based on component status
|
|
83
|
+
trigger: When the user asks about service health, incidents, or outages
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Incident Triage
|
|
87
|
+
|
|
88
|
+
Follow this methodology when assessing service health:
|
|
89
|
+
|
|
90
|
+
1. **Check component status** — Query GET /components to see current state of all services
|
|
91
|
+
2. **Identify degraded components** — Any component not in "operational" status needs attention
|
|
92
|
+
3. **Assess severity** — Use the severity matrix from the oncall runbook
|
|
93
|
+
4. **Check recent incidents** — Query GET /incidents for correlated issues
|
|
94
|
+
5. **Recommend action** — Based on severity, recommend the appropriate response from the runbook
|
|
95
|
+
|
|
96
|
+
Always report the exact component names and their statuses. Never fabricate status data.
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Knowledge: oncall-runbook
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
export const ONCALL_RUNBOOK = `# On-Call Runbook
|
|
104
|
+
|
|
105
|
+
## Severity Matrix
|
|
106
|
+
|
|
107
|
+
| Level | Criteria | Response Time | Escalation |
|
|
108
|
+
|-------|----------|---------------|------------|
|
|
109
|
+
| SEV1 | Multiple components down | 5 min | Page on-call lead immediately |
|
|
110
|
+
| SEV2 | Single component degraded | 15 min | Notify #incidents channel |
|
|
111
|
+
| SEV3 | Performance degradation | 1 hour | Create ticket |
|
|
112
|
+
| SEV4 | Cosmetic or minor | Next business day | Log for review |
|
|
113
|
+
|
|
114
|
+
## Key Contacts
|
|
115
|
+
|
|
116
|
+
- **On-call lead**: Alice (alice@example.com)
|
|
117
|
+
- **Platform team**: Bob (bob@example.com)
|
|
118
|
+
- **Database team**: Charlie (charlie@example.com)
|
|
119
|
+
|
|
120
|
+
## Components
|
|
121
|
+
|
|
122
|
+
- **api-gateway**: Main API entry point. SEV1 if down.
|
|
123
|
+
- **auth-service**: Authentication. SEV1 if down.
|
|
124
|
+
- **database-primary**: Primary Postgres. SEV1 if down.
|
|
125
|
+
- **worker-pool**: Background jobs. SEV2 if degraded.
|
|
126
|
+
- **cdn**: Static assets. SEV3 if degraded.
|
|
127
|
+
`;
|
|
128
|
+
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// Automation: health-check
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
export const HEALTH_CHECK_AUTOMATION = `# Automation: Daily Health Check
|
|
134
|
+
|
|
135
|
+
Schedule: 0 8 * * *
|
|
136
|
+
|
|
137
|
+
## Check
|
|
138
|
+
Query the statuspage API for current component status. Report any components not in "operational" state.
|
|
139
|
+
|
|
140
|
+
## Output
|
|
141
|
+
Summary of component statuses with severity assessment per the oncall runbook.
|
|
142
|
+
|
|
143
|
+
## Delivery
|
|
144
|
+
Post to #ops-daily channel.
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Mock StatusPage API
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
/** Deterministic mock data the API returns. */
|
|
152
|
+
export const MOCK_COMPONENTS = [
|
|
153
|
+
{id: 'comp-1', name: 'api-gateway', status: 'operational', updated_at: '2026-03-18T08:00:00Z'},
|
|
154
|
+
{id: 'comp-2', name: 'auth-service', status: 'operational', updated_at: '2026-03-18T08:00:00Z'},
|
|
155
|
+
{id: 'comp-3', name: 'database-primary', status: 'degraded_performance', updated_at: '2026-03-18T09:15:00Z'},
|
|
156
|
+
{id: 'comp-4', name: 'worker-pool', status: 'operational', updated_at: '2026-03-18T08:00:00Z'},
|
|
157
|
+
{id: 'comp-5', name: 'cdn', status: 'operational', updated_at: '2026-03-18T08:00:00Z'},
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
export const MOCK_INCIDENTS = [
|
|
161
|
+
{
|
|
162
|
+
id: 'inc-42',
|
|
163
|
+
name: 'Database latency spike',
|
|
164
|
+
status: 'investigating',
|
|
165
|
+
impact: 'minor',
|
|
166
|
+
created_at: '2026-03-18T09:10:00Z',
|
|
167
|
+
body: 'We are investigating elevated query latency on the primary database cluster.',
|
|
168
|
+
components: ['database-primary'],
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create a mock StatusPage API server that returns deterministic data.
|
|
174
|
+
* Returns a handle with start/stop methods.
|
|
175
|
+
*/
|
|
176
|
+
export function createMockStatusPageApi() {
|
|
177
|
+
const requests: Array<{method: string; url: string}> = [];
|
|
178
|
+
|
|
179
|
+
const server = http.createServer((req, res) => {
|
|
180
|
+
const url = req.url ?? '';
|
|
181
|
+
const method = req.method ?? '';
|
|
182
|
+
requests.push({method, url});
|
|
183
|
+
|
|
184
|
+
const json = (data: unknown) => {
|
|
185
|
+
res.writeHead(200, {'Content-Type': 'application/json'});
|
|
186
|
+
res.end(JSON.stringify(data));
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
if (method === 'GET' && url === '/components') {
|
|
190
|
+
json(MOCK_COMPONENTS);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (method === 'GET' && url === '/incidents') {
|
|
195
|
+
json(MOCK_INCIDENTS);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const incidentMatch = /^\/incidents\/([^/]+)$/.exec(url);
|
|
200
|
+
if (method === 'GET' && incidentMatch) {
|
|
201
|
+
const incident = MOCK_INCIDENTS.find((i) => i.id === incidentMatch[1]);
|
|
202
|
+
if (incident) {
|
|
203
|
+
json(incident);
|
|
204
|
+
} else {
|
|
205
|
+
res.writeHead(404);
|
|
206
|
+
res.end(JSON.stringify({error: 'Not found'}));
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
res.writeHead(404);
|
|
212
|
+
res.end(JSON.stringify({error: 'Not found'}));
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
let port = 0;
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
server,
|
|
219
|
+
requests,
|
|
220
|
+
get port() { return port; },
|
|
221
|
+
start: () => new Promise<number>((resolve) => {
|
|
222
|
+
server.listen(0, '127.0.0.1', () => {
|
|
223
|
+
const addr = server.address();
|
|
224
|
+
port = typeof addr === 'object' && addr ? addr.port : 0;
|
|
225
|
+
resolve(port);
|
|
226
|
+
});
|
|
227
|
+
}),
|
|
228
|
+
stop: () => new Promise<void>((resolve, reject) => {
|
|
229
|
+
server.close((err) => (err ? reject(err) : resolve()));
|
|
230
|
+
}),
|
|
231
|
+
};
|
|
232
|
+
}
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
5
|
+
* SPDX-License-Identifier: MIT
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {readFileSync} from 'node:fs';
|
|
9
|
+
import yargs from 'yargs';
|
|
10
|
+
import {hideBin} from 'yargs/helpers';
|
|
11
|
+
import {amodalCommands} from './commands/index.js';
|
|
12
|
+
|
|
13
|
+
const raw: unknown = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf-8'));
|
|
14
|
+
if (typeof raw !== 'object' || raw === null || !('version' in raw) || typeof raw.version !== 'string') {
|
|
15
|
+
throw new Error('Failed to read version from package.json');
|
|
16
|
+
}
|
|
17
|
+
const pkgVersion = raw.version;
|
|
18
|
+
|
|
19
|
+
const cli = yargs(hideBin(process.argv))
|
|
20
|
+
.scriptName('amodal')
|
|
21
|
+
.usage('$0 <command> [options]');
|
|
22
|
+
|
|
23
|
+
for (const cmd of amodalCommands) {
|
|
24
|
+
cli.command(cmd);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
cli
|
|
28
|
+
.demandCommand(1, 'Run amodal <command> --help for usage')
|
|
29
|
+
.strict()
|
|
30
|
+
.help()
|
|
31
|
+
.alias('h', 'help')
|
|
32
|
+
.version(process.env['CLI_VERSION'] ?? pkgVersion)
|
|
33
|
+
.alias('v', 'version');
|
|
34
|
+
|
|
35
|
+
void cli.parse();
|
|
@@ -0,0 +1,106 @@
|
|
|
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 {PlatformClient} from './platform-client.js';
|
|
9
|
+
|
|
10
|
+
describe('PlatformClient', () => {
|
|
11
|
+
const originalFetch = globalThis.fetch;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.restoreAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
globalThis.fetch = originalFetch;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('throws if PLATFORM_API_URL not set', () => {
|
|
22
|
+
const origUrl = process.env['PLATFORM_API_URL'];
|
|
23
|
+
const origKey = process.env['PLATFORM_API_KEY'];
|
|
24
|
+
delete process.env['PLATFORM_API_URL'];
|
|
25
|
+
delete process.env['PLATFORM_API_KEY'];
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
expect(() => new PlatformClient()).toThrow('Platform URL not found');
|
|
29
|
+
} finally {
|
|
30
|
+
if (origUrl) process.env['PLATFORM_API_URL'] = origUrl;
|
|
31
|
+
if (origKey) process.env['PLATFORM_API_KEY'] = origKey;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('throws if PLATFORM_API_KEY not set', () => {
|
|
36
|
+
expect(() => new PlatformClient({url: 'http://localhost:4000'})).toThrow('Platform auth not found');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('creates client with explicit options', () => {
|
|
40
|
+
const client = new PlatformClient({url: 'http://localhost:4000', apiKey: 'test-key'});
|
|
41
|
+
expect(client).toBeDefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('uploads snapshot via POST', async () => {
|
|
45
|
+
const mockResponse = {
|
|
46
|
+
id: 'deploy-abc1234',
|
|
47
|
+
environment: 'production',
|
|
48
|
+
isActive: true,
|
|
49
|
+
createdAt: new Date().toISOString(),
|
|
50
|
+
createdBy: 'test',
|
|
51
|
+
source: 'cli',
|
|
52
|
+
snapshotSize: 1024,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
56
|
+
ok: true,
|
|
57
|
+
json: () => Promise.resolve(mockResponse),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const client = new PlatformClient({url: 'http://localhost:4000', apiKey: 'key'});
|
|
61
|
+
const result = await client.uploadSnapshot({
|
|
62
|
+
deployId: 'deploy-abc1234',
|
|
63
|
+
createdAt: new Date().toISOString(),
|
|
64
|
+
createdBy: 'test',
|
|
65
|
+
source: 'cli',
|
|
66
|
+
config: {name: 'test', version: '1.0', models: {main: {provider: 'a', model: 'b'}}},
|
|
67
|
+
connections: {},
|
|
68
|
+
skills: [],
|
|
69
|
+
automations: [],
|
|
70
|
+
knowledge: [],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(result.id).toBe('deploy-abc1234');
|
|
74
|
+
|
|
75
|
+
const fetchCall = (globalThis.fetch as ReturnType<typeof vi.fn>).mock.calls[0] as [string, RequestInit];
|
|
76
|
+
expect(fetchCall[0]).toBe('http://localhost:4000/api/snapshot-deployments');
|
|
77
|
+
expect(fetchCall[1].method).toBe('POST');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('lists deployments via GET', async () => {
|
|
81
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
82
|
+
ok: true,
|
|
83
|
+
json: () => Promise.resolve([]),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const client = new PlatformClient({url: 'http://localhost:4000', apiKey: 'key'});
|
|
87
|
+
const result = await client.listDeployments({environment: 'staging', limit: 5});
|
|
88
|
+
|
|
89
|
+
expect(result).toEqual([]);
|
|
90
|
+
|
|
91
|
+
const fetchCall = (globalThis.fetch as ReturnType<typeof vi.fn>).mock.calls[0] as [string];
|
|
92
|
+
expect(fetchCall[0]).toContain('environment=staging');
|
|
93
|
+
expect(fetchCall[0]).toContain('limit=5');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('throws on non-ok response', async () => {
|
|
97
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
98
|
+
ok: false,
|
|
99
|
+
status: 401,
|
|
100
|
+
json: () => Promise.resolve({error: 'Unauthorized'}),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const client = new PlatformClient({url: 'http://localhost:4000', apiKey: 'bad-key'});
|
|
104
|
+
await expect(client.listDeployments()).rejects.toThrow('failed (401)');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {DeploySnapshot} from '@amodalai/core';
|
|
8
|
+
import {readProjectLink} from '../commands/link.js';
|
|
9
|
+
import {readRcFile} from '../commands/login.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Metadata returned for a snapshot deployment.
|
|
13
|
+
*/
|
|
14
|
+
export interface SnapshotDeploymentMeta {
|
|
15
|
+
id: string;
|
|
16
|
+
environment: string;
|
|
17
|
+
isActive: boolean;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
createdBy: string;
|
|
20
|
+
source: string;
|
|
21
|
+
commitSha?: string;
|
|
22
|
+
branch?: string;
|
|
23
|
+
message?: string;
|
|
24
|
+
snapshotSize: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolve platform URL and API key from multiple sources:
|
|
29
|
+
* 1. Explicit options (flags)
|
|
30
|
+
* 2. .amodal/project.json (platformUrl from `amodal link`)
|
|
31
|
+
* 3. ~/.amodalrc (auth token from `amodal login`)
|
|
32
|
+
* 4. Env vars (fallback)
|
|
33
|
+
*/
|
|
34
|
+
export async function resolvePlatformConfig(options?: {
|
|
35
|
+
url?: string;
|
|
36
|
+
apiKey?: string;
|
|
37
|
+
}): Promise<{url: string; apiKey: string}> {
|
|
38
|
+
let url = options?.url;
|
|
39
|
+
let apiKey = options?.apiKey;
|
|
40
|
+
|
|
41
|
+
// Try project link for URL
|
|
42
|
+
if (!url) {
|
|
43
|
+
const link = await readProjectLink();
|
|
44
|
+
if (link?.platformUrl) {
|
|
45
|
+
url = link.platformUrl;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Try rc file for auth token
|
|
50
|
+
if (!apiKey) {
|
|
51
|
+
const rc = await readRcFile();
|
|
52
|
+
if (rc.platform?.token) {
|
|
53
|
+
apiKey = rc.platform.token;
|
|
54
|
+
// Also use the URL from rc if still missing
|
|
55
|
+
if (!url && rc.platform.url) {
|
|
56
|
+
url = rc.platform.url;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Env vars as fallback
|
|
62
|
+
if (!url) url = process.env['PLATFORM_API_URL'];
|
|
63
|
+
if (!apiKey) apiKey = process.env['PLATFORM_API_KEY'];
|
|
64
|
+
|
|
65
|
+
if (!url) throw new Error('Platform URL not found. Run `amodal login` + `amodal link`, or set PLATFORM_API_URL.');
|
|
66
|
+
if (!apiKey) throw new Error('Platform auth not found. Run `amodal login`, or set PLATFORM_API_KEY.');
|
|
67
|
+
|
|
68
|
+
return {url: url.replace(/\/$/, ''), apiKey};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Platform API client for snapshot deployments.
|
|
73
|
+
*
|
|
74
|
+
* Resolves credentials from: explicit options → project link → rc file → env vars.
|
|
75
|
+
* Use `PlatformClient.create()` for async auto-discovery, or `new PlatformClient()` for sync usage.
|
|
76
|
+
*/
|
|
77
|
+
export class PlatformClient {
|
|
78
|
+
private readonly baseUrl: string;
|
|
79
|
+
private readonly apiKey: string;
|
|
80
|
+
|
|
81
|
+
constructor(options?: {url?: string; apiKey?: string}) {
|
|
82
|
+
const url = options?.url ?? process.env['PLATFORM_API_URL'];
|
|
83
|
+
const apiKey = options?.apiKey ?? process.env['PLATFORM_API_KEY'];
|
|
84
|
+
if (!url) throw new Error('Platform URL not found. Run `amodal login` + `amodal link`, or set PLATFORM_API_URL.');
|
|
85
|
+
if (!apiKey) throw new Error('Platform auth not found. Run `amodal login`, or set PLATFORM_API_KEY.');
|
|
86
|
+
this.baseUrl = url.replace(/\/$/, '');
|
|
87
|
+
this.apiKey = apiKey;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create a PlatformClient with auto-discovery of credentials.
|
|
92
|
+
* Resolves from: explicit options → project link → rc file → env vars.
|
|
93
|
+
*/
|
|
94
|
+
static async create(options?: {url?: string; apiKey?: string}): Promise<PlatformClient> {
|
|
95
|
+
const config = await resolvePlatformConfig(options);
|
|
96
|
+
return new PlatformClient(config);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private headers(): Record<string, string> {
|
|
100
|
+
return {
|
|
101
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private async request<T>(method: string, path: string, body?: unknown): Promise<T> {
|
|
107
|
+
const url = `${this.baseUrl}${path}`;
|
|
108
|
+
const resp = await fetch(url, {
|
|
109
|
+
method,
|
|
110
|
+
headers: this.headers(),
|
|
111
|
+
...(body ? {body: JSON.stringify(body)} : {}),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (!resp.ok) {
|
|
115
|
+
let detail = '';
|
|
116
|
+
try {
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
118
|
+
const errBody = await resp.json() as {error?: string};
|
|
119
|
+
detail = errBody.error ? `: ${errBody.error}` : '';
|
|
120
|
+
} catch {
|
|
121
|
+
// ignore parse errors
|
|
122
|
+
}
|
|
123
|
+
throw new Error(`Platform API ${method} ${path} failed (${resp.status})${detail}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
127
|
+
return resp.json() as Promise<T>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Upload a snapshot and deploy it.
|
|
132
|
+
*/
|
|
133
|
+
async uploadSnapshot(snapshot: DeploySnapshot, options: {
|
|
134
|
+
environment?: string;
|
|
135
|
+
} = {}): Promise<SnapshotDeploymentMeta> {
|
|
136
|
+
return this.request<SnapshotDeploymentMeta>('POST', '/api/snapshot-deployments', {
|
|
137
|
+
snapshot,
|
|
138
|
+
environment: options.environment ?? 'production',
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* List deployments for the authenticated tenant.
|
|
144
|
+
*/
|
|
145
|
+
async listDeployments(options: {
|
|
146
|
+
environment?: string;
|
|
147
|
+
limit?: number;
|
|
148
|
+
} = {}): Promise<SnapshotDeploymentMeta[]> {
|
|
149
|
+
const params = new URLSearchParams();
|
|
150
|
+
if (options.environment) params.set('environment', options.environment);
|
|
151
|
+
if (options.limit) params.set('limit', String(options.limit));
|
|
152
|
+
const qs = params.toString();
|
|
153
|
+
return this.request<SnapshotDeploymentMeta[]>('GET', `/api/snapshot-deployments${qs ? `?${qs}` : ''}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Rollback to a previous deployment.
|
|
158
|
+
*/
|
|
159
|
+
async rollback(options: {
|
|
160
|
+
deployId?: string;
|
|
161
|
+
environment?: string;
|
|
162
|
+
} = {}): Promise<SnapshotDeploymentMeta> {
|
|
163
|
+
return this.request<SnapshotDeploymentMeta>('POST', '/api/snapshot-deployments/rollback', {
|
|
164
|
+
deployId: options.deployId,
|
|
165
|
+
environment: options.environment ?? 'production',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Promote a deployment from one environment to another.
|
|
171
|
+
*/
|
|
172
|
+
async promote(fromEnv: string, toEnv: string = 'production'): Promise<SnapshotDeploymentMeta> {
|
|
173
|
+
return this.request<SnapshotDeploymentMeta>('POST', '/api/snapshot-deployments/promote', {
|
|
174
|
+
fromEnvironment: fromEnv,
|
|
175
|
+
toEnvironment: toEnv,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get status of a specific deployment.
|
|
181
|
+
*/
|
|
182
|
+
async getStatus(deployId: string): Promise<SnapshotDeploymentMeta> {
|
|
183
|
+
return this.request<SnapshotDeploymentMeta>('GET', `/api/snapshot-deployments/${deployId}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get the active snapshot for an environment.
|
|
188
|
+
*/
|
|
189
|
+
async getActiveSnapshot(environment: string = 'production'): Promise<DeploySnapshot> {
|
|
190
|
+
const params = new URLSearchParams({environment});
|
|
191
|
+
return this.request<DeploySnapshot>('GET', `/api/snapshot-deployments/active?${params.toString()}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
import {findRepoRoot} from './repo-discovery.js';
|
|
9
|
+
|
|
10
|
+
vi.mock('node:fs', () => ({
|
|
11
|
+
existsSync: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
describe('findRepoRoot', () => {
|
|
15
|
+
let existsSync: ReturnType<typeof vi.fn>;
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
const fs = await import('node:fs');
|
|
19
|
+
existsSync = vi.mocked(fs.existsSync);
|
|
20
|
+
existsSync.mockReset();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should find repo root when config is in current directory', () => {
|
|
24
|
+
existsSync.mockImplementation((path: string) =>
|
|
25
|
+
path === '/projects/myapp/amodal.json',
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const result = findRepoRoot('/projects/myapp');
|
|
29
|
+
expect(result).toBe('/projects/myapp');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should find repo root in parent directory', () => {
|
|
33
|
+
existsSync.mockImplementation((path: string) =>
|
|
34
|
+
path === '/projects/myapp/amodal.json',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const result = findRepoRoot('/projects/myapp/src/lib');
|
|
38
|
+
expect(result).toBe('/projects/myapp');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should throw when config is not found', () => {
|
|
42
|
+
existsSync.mockReturnValue(false);
|
|
43
|
+
|
|
44
|
+
expect(() => findRepoRoot('/some/deep/path')).toThrow(
|
|
45
|
+
'Could not find amodal.json',
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should handle root directory without infinite loop', () => {
|
|
50
|
+
existsSync.mockReturnValue(false);
|
|
51
|
+
|
|
52
|
+
expect(() => findRepoRoot('/')).toThrow(
|
|
53
|
+
'Could not find amodal.json',
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {existsSync} from 'node:fs';
|
|
8
|
+
import {join, resolve, dirname} from 'node:path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Walks up from `startDir` (or cwd) looking for a directory containing
|
|
12
|
+
* `amodal.json`. Throws if not found.
|
|
13
|
+
*/
|
|
14
|
+
export function findRepoRoot(startDir?: string): string {
|
|
15
|
+
let dir = resolve(startDir ?? process.cwd());
|
|
16
|
+
|
|
17
|
+
// Safety limit to prevent infinite loops
|
|
18
|
+
const maxDepth = 100;
|
|
19
|
+
let depth = 0;
|
|
20
|
+
|
|
21
|
+
while (depth < maxDepth) {
|
|
22
|
+
const configPath = join(dir, 'amodal.json');
|
|
23
|
+
if (existsSync(configPath)) {
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const parent = dirname(dir);
|
|
28
|
+
if (parent === dir) {
|
|
29
|
+
// Reached filesystem root
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
dir = parent;
|
|
33
|
+
depth++;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw new Error(
|
|
37
|
+
'Could not find amodal.json in any parent directory. ' +
|
|
38
|
+
'Run `amodal init` to create a new project, or change to a directory containing an amodal.json file.',
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a docker-compose.yml for local/staging deployment.
|
|
9
|
+
*/
|
|
10
|
+
export function generateCompose(serviceName: string): string {
|
|
11
|
+
const safeName = serviceName.replace(/[^a-z0-9-]/gi, '-').toLowerCase();
|
|
12
|
+
return `# Docker Compose for amodal runtime
|
|
13
|
+
# Generated by: amodal deploy init
|
|
14
|
+
|
|
15
|
+
services:
|
|
16
|
+
${safeName}:
|
|
17
|
+
build: .
|
|
18
|
+
ports:
|
|
19
|
+
- "3847:3847"
|
|
20
|
+
env_file:
|
|
21
|
+
- .env.production
|
|
22
|
+
restart: unless-stopped
|
|
23
|
+
healthcheck:
|
|
24
|
+
test: ["CMD", "curl", "-f", "http://localhost:3847/health"]
|
|
25
|
+
interval: 30s
|
|
26
|
+
timeout: 10s
|
|
27
|
+
retries: 3
|
|
28
|
+
start_period: 10s
|
|
29
|
+
`;
|
|
30
|
+
}
|