@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,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ConfigTemplateOptions {
|
|
8
|
+
name: string;
|
|
9
|
+
provider: 'anthropic' | 'openai' | 'google';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generates the default config.json content for a new project.
|
|
14
|
+
*/
|
|
15
|
+
export function generateConfigTemplate(options: ConfigTemplateOptions): string {
|
|
16
|
+
const modelMap: Record<string, string> = {
|
|
17
|
+
anthropic: 'claude-sonnet-4-20250514',
|
|
18
|
+
openai: 'gpt-4o',
|
|
19
|
+
google: 'gemini-2.0-flash',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const envKeyMap: Record<string, string> = {
|
|
23
|
+
anthropic: 'ANTHROPIC_API_KEY',
|
|
24
|
+
openai: 'OPENAI_API_KEY',
|
|
25
|
+
google: 'GOOGLE_API_KEY',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const model = modelMap[options.provider] ?? modelMap['anthropic'];
|
|
29
|
+
const envKey = envKeyMap[options.provider] ?? envKeyMap['anthropic'];
|
|
30
|
+
|
|
31
|
+
const config = {
|
|
32
|
+
name: options.name,
|
|
33
|
+
version: '1.0.0',
|
|
34
|
+
models: {
|
|
35
|
+
main: {
|
|
36
|
+
provider: options.provider,
|
|
37
|
+
model,
|
|
38
|
+
apiKey: `\${${envKey}}`,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return JSON.stringify(config, null, 2) + '\n';
|
|
44
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {describe, it, expect} from 'vitest';
|
|
8
|
+
import {generateDockerfile} from './dockerfile-template.js';
|
|
9
|
+
import {generateCompose} from './compose-template.js';
|
|
10
|
+
import {extractEnvVars} from './env-template.js';
|
|
11
|
+
|
|
12
|
+
describe('generateDockerfile', () => {
|
|
13
|
+
it('should generate valid Dockerfile', () => {
|
|
14
|
+
const content = generateDockerfile();
|
|
15
|
+
expect(content).toContain('FROM node:20-slim AS builder');
|
|
16
|
+
expect(content).toContain('FROM node:20-slim AS production');
|
|
17
|
+
expect(content).toContain('EXPOSE 3847');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should include multi-stage build', () => {
|
|
21
|
+
const content = generateDockerfile();
|
|
22
|
+
expect(content).toContain('AS builder');
|
|
23
|
+
expect(content).toContain('AS production');
|
|
24
|
+
expect(content).toContain('COPY --from=builder');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should set NODE_ENV', () => {
|
|
28
|
+
const content = generateDockerfile();
|
|
29
|
+
expect(content).toContain('NODE_ENV=production');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('generateCompose', () => {
|
|
34
|
+
it('should use service name', () => {
|
|
35
|
+
const content = generateCompose('my-agent');
|
|
36
|
+
expect(content).toContain('my-agent:');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should sanitize special characters in service name', () => {
|
|
40
|
+
const content = generateCompose('My Agent v2.0');
|
|
41
|
+
expect(content).toContain('my-agent-v2-0:');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should include health check', () => {
|
|
45
|
+
const content = generateCompose('test');
|
|
46
|
+
expect(content).toContain('healthcheck:');
|
|
47
|
+
expect(content).toContain('/health');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should reference .env.production', () => {
|
|
51
|
+
const content = generateCompose('test');
|
|
52
|
+
expect(content).toContain('.env.production');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should expose port 3847', () => {
|
|
56
|
+
const content = generateCompose('test');
|
|
57
|
+
expect(content).toContain('3847:3847');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('extractEnvVars', () => {
|
|
62
|
+
it('should extract env:VAR_NAME references', () => {
|
|
63
|
+
const json = '{"key": "env:MY_API_KEY", "model": "env:MODEL_NAME"}';
|
|
64
|
+
const vars = extractEnvVars(json);
|
|
65
|
+
expect(vars).toEqual(['MODEL_NAME', 'MY_API_KEY']);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should deduplicate vars', () => {
|
|
69
|
+
const json = '{"a": "env:MY_KEY", "b": "env:MY_KEY"}';
|
|
70
|
+
const vars = extractEnvVars(json);
|
|
71
|
+
expect(vars).toEqual(['MY_KEY']);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should return empty for no env refs', () => {
|
|
75
|
+
const json = '{"key": "literal-value"}';
|
|
76
|
+
expect(extractEnvVars(json)).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle complex nested JSON', () => {
|
|
80
|
+
const json = JSON.stringify({
|
|
81
|
+
models: {
|
|
82
|
+
main: {provider: 'env:PROVIDER', model: 'env:MODEL'},
|
|
83
|
+
},
|
|
84
|
+
platform: {apiKey: 'env:API_KEY'},
|
|
85
|
+
});
|
|
86
|
+
const vars = extractEnvVars(json);
|
|
87
|
+
expect(vars).toEqual(['API_KEY', 'MODEL', 'PROVIDER']);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should sort results alphabetically', () => {
|
|
91
|
+
const json = '{"z": "env:ZEBRA", "a": "env:ALPHA"}';
|
|
92
|
+
const vars = extractEnvVars(json);
|
|
93
|
+
expect(vars).toEqual(['ALPHA', 'ZEBRA']);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should handle empty string', () => {
|
|
97
|
+
expect(extractEnvVars('')).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a production Dockerfile for amodal runtime.
|
|
9
|
+
*/
|
|
10
|
+
export function generateDockerfile(): string {
|
|
11
|
+
return `# Multi-stage build for amodal runtime
|
|
12
|
+
# Generated by: amodal deploy init
|
|
13
|
+
|
|
14
|
+
# Stage 1: Build
|
|
15
|
+
FROM node:20-slim AS builder
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
COPY package.json pnpm-lock.yaml* package-lock.json* ./
|
|
18
|
+
RUN corepack enable && corepack prepare pnpm@latest --activate 2>/dev/null || npm install
|
|
19
|
+
COPY . .
|
|
20
|
+
RUN if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else npm ci; fi
|
|
21
|
+
|
|
22
|
+
# Stage 2: Production
|
|
23
|
+
FROM node:20-slim AS production
|
|
24
|
+
WORKDIR /app
|
|
25
|
+
ENV NODE_ENV=production
|
|
26
|
+
COPY --from=builder /app .
|
|
27
|
+
EXPOSE 3847
|
|
28
|
+
CMD ["node", "node_modules/@amodalai/runtime/dist/src/index.js"]
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ENV_PATTERN = /env:([A-Z_][A-Z0-9_]*)/g;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extract all env:VAR_NAME references from JSON config strings.
|
|
11
|
+
*
|
|
12
|
+
* Returns a deduplicated list of environment variable names.
|
|
13
|
+
*/
|
|
14
|
+
export function extractEnvVars(jsonString: string): string[] {
|
|
15
|
+
const vars = new Set<string>();
|
|
16
|
+
let match: RegExpExecArray | null;
|
|
17
|
+
|
|
18
|
+
// Reset regex state
|
|
19
|
+
ENV_PATTERN.lastIndex = 0;
|
|
20
|
+
while ((match = ENV_PATTERN.exec(jsonString)) !== null) {
|
|
21
|
+
if (match[1]) {
|
|
22
|
+
vars.add(match[1]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return [...vars].sort();
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a starter knowledge.md.
|
|
9
|
+
*/
|
|
10
|
+
export function generateKnowledgeTemplate(): string {
|
|
11
|
+
return `---
|
|
12
|
+
title: Domain Knowledge
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Getting Started
|
|
16
|
+
|
|
17
|
+
Add domain-specific knowledge here. Good knowledge documents include:
|
|
18
|
+
|
|
19
|
+
- **Terminology**: Define domain-specific terms the agent should understand
|
|
20
|
+
- **Baselines**: What "normal" looks like for key metrics
|
|
21
|
+
- **Common patterns**: Recurring scenarios the agent should recognize
|
|
22
|
+
- **Decision frameworks**: How to prioritize or categorize findings
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a starter SKILL.md.
|
|
9
|
+
*/
|
|
10
|
+
export function generateSkillTemplate(): string {
|
|
11
|
+
return `---
|
|
12
|
+
name: general-analysis
|
|
13
|
+
description: General-purpose analysis skill — customize for your domain
|
|
14
|
+
trigger: When the user asks for investigation or analysis
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Analysis
|
|
18
|
+
|
|
19
|
+
Customize this skill for your specific domain. A good skill tells the agent:
|
|
20
|
+
|
|
21
|
+
1. **What to investigate** — the scope and constraints
|
|
22
|
+
2. **How to gather data** — which connections and endpoints to use
|
|
23
|
+
3. **How to reason** — the analytical framework to apply
|
|
24
|
+
4. **How to present findings** — the format and level of detail
|
|
25
|
+
5. **What to avoid** — common pitfalls and anti-patterns
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type React from 'react';
|
|
8
|
+
import {useState, useCallback} from 'react';
|
|
9
|
+
import {Box, Text} from 'ink';
|
|
10
|
+
import TextInput from 'ink-text-input';
|
|
11
|
+
import {theme} from './theme.js';
|
|
12
|
+
import type {AskUserQuestion} from './types.js';
|
|
13
|
+
|
|
14
|
+
interface AskUserPromptProps {
|
|
15
|
+
question: AskUserQuestion;
|
|
16
|
+
onRespond: (askId: string, answer: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const AskUserPrompt: React.FC<AskUserPromptProps> = ({question, onRespond}) => {
|
|
20
|
+
const [value, setValue] = useState('');
|
|
21
|
+
|
|
22
|
+
const handleSubmit = useCallback(
|
|
23
|
+
(text: string) => {
|
|
24
|
+
const trimmed = text.trim();
|
|
25
|
+
if (!trimmed) return;
|
|
26
|
+
onRespond(question.askId, trimmed);
|
|
27
|
+
setValue('');
|
|
28
|
+
},
|
|
29
|
+
[onRespond, question.askId],
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Box
|
|
34
|
+
flexDirection="column"
|
|
35
|
+
marginTop={1}
|
|
36
|
+
borderStyle="round"
|
|
37
|
+
borderColor={theme.text.accent}
|
|
38
|
+
paddingLeft={1}
|
|
39
|
+
paddingRight={1}
|
|
40
|
+
>
|
|
41
|
+
<Text color={theme.text.accent} bold>
|
|
42
|
+
Agent Question
|
|
43
|
+
</Text>
|
|
44
|
+
<Text wrap="wrap">{question.text}</Text>
|
|
45
|
+
<Box marginTop={1}>
|
|
46
|
+
<Text color={theme.text.accent} bold>
|
|
47
|
+
{'\u203A '}
|
|
48
|
+
</Text>
|
|
49
|
+
<TextInput
|
|
50
|
+
value={value}
|
|
51
|
+
onChange={setValue}
|
|
52
|
+
onSubmit={handleSubmit}
|
|
53
|
+
placeholder="Type your answer..."
|
|
54
|
+
/>
|
|
55
|
+
</Box>
|
|
56
|
+
</Box>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type React from 'react';
|
|
8
|
+
import {Box, Text} from 'ink';
|
|
9
|
+
import {theme} from './theme.js';
|
|
10
|
+
import {MarkdownDisplay} from './markdown/MarkdownDisplay.js';
|
|
11
|
+
import {ToolCallDisplay} from './ToolCallDisplay.js';
|
|
12
|
+
import {ThinkingDisplay} from './ThinkingDisplay.js';
|
|
13
|
+
import type {ChatMessage} from './types.js';
|
|
14
|
+
|
|
15
|
+
interface AssistantMessageProps {
|
|
16
|
+
message: ChatMessage;
|
|
17
|
+
width?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const AssistantMessage: React.FC<AssistantMessageProps> = ({
|
|
21
|
+
message,
|
|
22
|
+
width,
|
|
23
|
+
}) => (
|
|
24
|
+
<Box flexDirection="column" marginTop={1}>
|
|
25
|
+
{/* Skills activated */}
|
|
26
|
+
{message.skills?.map((skill, i) => (
|
|
27
|
+
<Text key={i} color={theme.status.warning}>
|
|
28
|
+
{' \u26A1 '}
|
|
29
|
+
{skill}
|
|
30
|
+
</Text>
|
|
31
|
+
))}
|
|
32
|
+
|
|
33
|
+
{/* Collapsed thinking */}
|
|
34
|
+
{message.thinking ? <ThinkingDisplay text={message.thinking} collapsed /> : null}
|
|
35
|
+
|
|
36
|
+
{/* Tool calls — inline before text (matches actual execution order) */}
|
|
37
|
+
{message.toolCalls?.map((tool) => (
|
|
38
|
+
<ToolCallDisplay key={tool.toolId} tool={tool} width={width} compact />
|
|
39
|
+
))}
|
|
40
|
+
|
|
41
|
+
{/* Main text with markdown */}
|
|
42
|
+
{message.text ? (
|
|
43
|
+
<Box>
|
|
44
|
+
<Text color={theme.text.accent}>{'\u25C6 '}</Text>
|
|
45
|
+
<Box flexDirection="column" width={width ? width - 4 : undefined}>
|
|
46
|
+
<MarkdownDisplay text={message.text} width={width ? width - 4 : undefined} />
|
|
47
|
+
</Box>
|
|
48
|
+
</Box>
|
|
49
|
+
) : null}
|
|
50
|
+
</Box>
|
|
51
|
+
);
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type React from 'react';
|
|
8
|
+
import {useCallback, useEffect} from 'react';
|
|
9
|
+
import {Box, Text, useApp, useInput, useStdout} from 'ink';
|
|
10
|
+
import {useChat} from './useChat.js';
|
|
11
|
+
import {ScrollableMessageList} from './ScrollableMessageList.js';
|
|
12
|
+
import {InputBar} from './InputBar.js';
|
|
13
|
+
import {Header} from './Header.js';
|
|
14
|
+
import {Footer} from './Footer.js';
|
|
15
|
+
import {NotificationBar} from './NotificationBar.js';
|
|
16
|
+
import {AskUserPrompt} from './AskUserPrompt.js';
|
|
17
|
+
import {ConfirmationPrompt} from './ConfirmationPrompt.js';
|
|
18
|
+
import {StatusMessage} from './StatusMessage.js';
|
|
19
|
+
import {SessionBrowser} from './SessionBrowser.js';
|
|
20
|
+
import {FullScreenLayout} from './FullScreenLayout.js';
|
|
21
|
+
import {theme} from './theme.js';
|
|
22
|
+
import {useScroll} from './useScroll.js';
|
|
23
|
+
import {useElapsedTime} from './useElapsedTime.js';
|
|
24
|
+
import {useSessionResume} from './useSessionResume.js';
|
|
25
|
+
import {getResponsiveLayout} from './useResponsiveLayout.js';
|
|
26
|
+
import {getCommand} from './commands/index.js';
|
|
27
|
+
|
|
28
|
+
interface ChatAppProps {
|
|
29
|
+
baseUrl: string;
|
|
30
|
+
tenantId: string;
|
|
31
|
+
resumeSessionId?: string;
|
|
32
|
+
fullscreen?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Approximate row counts for layout calculation
|
|
36
|
+
const HEADER_ROWS = 2;
|
|
37
|
+
const FOOTER_ROWS = 3;
|
|
38
|
+
const INPUT_ROWS = 2;
|
|
39
|
+
|
|
40
|
+
export const ChatApp: React.FC<ChatAppProps> = ({
|
|
41
|
+
baseUrl,
|
|
42
|
+
tenantId,
|
|
43
|
+
resumeSessionId,
|
|
44
|
+
fullscreen,
|
|
45
|
+
}) => {
|
|
46
|
+
const {state, sendMessage, respondToQuestion, respondToConfirmation, dismissNotification, dispatch} =
|
|
47
|
+
useChat(baseUrl, tenantId);
|
|
48
|
+
const {exit} = useApp();
|
|
49
|
+
const {stdout} = useStdout();
|
|
50
|
+
const width = stdout?.columns ?? 80;
|
|
51
|
+
const rows = stdout?.rows ?? 24;
|
|
52
|
+
|
|
53
|
+
const layout = getResponsiveLayout(width);
|
|
54
|
+
const elapsed = useElapsedTime(state.isStreaming);
|
|
55
|
+
|
|
56
|
+
// Scroll management
|
|
57
|
+
const viewportHeight = Math.max(rows - HEADER_ROWS - FOOTER_ROWS - INPUT_ROWS, 5);
|
|
58
|
+
const scroll = useScroll(true);
|
|
59
|
+
|
|
60
|
+
// Update viewport height
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
scroll.setViewportHeight(viewportHeight);
|
|
63
|
+
}, [viewportHeight, scroll]);
|
|
64
|
+
|
|
65
|
+
// Auto-scroll when messages or streaming content changes
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
// Estimate content height as number of messages * ~3 lines each + streaming
|
|
68
|
+
const estimatedHeight = state.messages.length * 3 +
|
|
69
|
+
(state.isStreaming ? 5 : 0) +
|
|
70
|
+
state.activeToolCalls.length * 4;
|
|
71
|
+
scroll.setContentHeight(estimatedHeight);
|
|
72
|
+
}, [state.messages.length, state.isStreaming, state.activeToolCalls.length, scroll]);
|
|
73
|
+
|
|
74
|
+
// Session resume
|
|
75
|
+
const resume = useSessionResume(resumeSessionId ?? null, baseUrl);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (resume.messages && resumeSessionId) {
|
|
78
|
+
dispatch({
|
|
79
|
+
type: 'RESUME_SESSION',
|
|
80
|
+
sessionId: resumeSessionId,
|
|
81
|
+
messages: resume.messages,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}, [resume.messages, resumeSessionId, dispatch]);
|
|
85
|
+
|
|
86
|
+
// Keyboard navigation for scrolling
|
|
87
|
+
const canScroll = !state.isStreaming && !state.pendingQuestion && !state.pendingConfirmation && !state.showSessionBrowser;
|
|
88
|
+
useInput((_input, key) => {
|
|
89
|
+
if (key.ctrl && _input === 'c') {
|
|
90
|
+
exit();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!canScroll) return;
|
|
95
|
+
|
|
96
|
+
// j/k line scroll
|
|
97
|
+
if (_input === 'j') {
|
|
98
|
+
scroll.scrollBy(1);
|
|
99
|
+
} else if (_input === 'k') {
|
|
100
|
+
scroll.scrollBy(-1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Page up/down
|
|
104
|
+
if (key.pageUp) {
|
|
105
|
+
scroll.scrollBy(-viewportHeight);
|
|
106
|
+
} else if (key.pageDown) {
|
|
107
|
+
scroll.scrollBy(viewportHeight);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Home/End (map to Meta+< and Meta+>)
|
|
111
|
+
if (key.home) {
|
|
112
|
+
scroll.scrollToTop();
|
|
113
|
+
} else if (key.end) {
|
|
114
|
+
scroll.scrollToBottom();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Slash command handler
|
|
119
|
+
const handleSlashCommand = useCallback(
|
|
120
|
+
(name: string, args: string) => {
|
|
121
|
+
const cmd = getCommand(name);
|
|
122
|
+
if (!cmd) {
|
|
123
|
+
dispatch({type: 'LOCAL_MESSAGE', text: `Unknown command: /${name}. Type /help for available commands.`});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const result = cmd.execute(args, state);
|
|
127
|
+
switch (result.type) {
|
|
128
|
+
case 'message':
|
|
129
|
+
dispatch({type: 'LOCAL_MESSAGE', text: result.text ?? ''});
|
|
130
|
+
break;
|
|
131
|
+
case 'clear':
|
|
132
|
+
dispatch({type: 'CLEAR_HISTORY'});
|
|
133
|
+
break;
|
|
134
|
+
case 'noop':
|
|
135
|
+
break;
|
|
136
|
+
default:
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
[state, dispatch],
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Confirmation queue handlers
|
|
144
|
+
const handleApproveAll = useCallback(() => {
|
|
145
|
+
for (let i = 0; i < state.confirmationQueue.length; i++) {
|
|
146
|
+
respondToConfirmation(true);
|
|
147
|
+
}
|
|
148
|
+
}, [state.confirmationQueue.length, respondToConfirmation]);
|
|
149
|
+
|
|
150
|
+
const handleRejectAll = useCallback(() => {
|
|
151
|
+
for (let i = 0; i < state.confirmationQueue.length; i++) {
|
|
152
|
+
respondToConfirmation(false);
|
|
153
|
+
}
|
|
154
|
+
}, [state.confirmationQueue.length, respondToConfirmation]);
|
|
155
|
+
|
|
156
|
+
// Session browser handlers
|
|
157
|
+
const handleSessionSelect = useCallback(
|
|
158
|
+
(sessionId: string) => {
|
|
159
|
+
dispatch({type: 'HIDE_SESSION_BROWSER'});
|
|
160
|
+
// Trigger resume by re-mounting — for now just dispatch
|
|
161
|
+
dispatch({type: 'LOCAL_MESSAGE', text: `Resuming session ${sessionId}...`});
|
|
162
|
+
},
|
|
163
|
+
[dispatch],
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const handleSessionBrowserClose = useCallback(() => {
|
|
167
|
+
dispatch({type: 'HIDE_SESSION_BROWSER'});
|
|
168
|
+
}, [dispatch]);
|
|
169
|
+
|
|
170
|
+
// Get first running tool name for InputBar
|
|
171
|
+
const activeToolName = state.activeToolCalls.find((t) => t.status === 'running')?.toolName;
|
|
172
|
+
const exploreQuery = state.explorePhase?.active ? state.explorePhase.query : undefined;
|
|
173
|
+
const cwd = process.cwd();
|
|
174
|
+
|
|
175
|
+
const currentConfirmation = state.confirmationQueue[0] ?? state.pendingConfirmation;
|
|
176
|
+
|
|
177
|
+
const headerEl = (
|
|
178
|
+
<Header sessionId={state.sessionId} isStreaming={state.isStreaming} isNarrow={layout.isNarrow} />
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const footerEl = (
|
|
182
|
+
<Footer
|
|
183
|
+
isStreaming={state.isStreaming}
|
|
184
|
+
hasPendingQuestion={!!state.pendingQuestion}
|
|
185
|
+
hasPendingConfirmation={!!currentConfirmation}
|
|
186
|
+
tokenUsage={state.tokenUsage}
|
|
187
|
+
cwd={cwd}
|
|
188
|
+
modelName={state.tokenUsage.model ?? undefined}
|
|
189
|
+
isNarrow={layout.isNarrow}
|
|
190
|
+
/>
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const content = (
|
|
194
|
+
<>
|
|
195
|
+
{/* Resume loading indicator */}
|
|
196
|
+
{resume.loading ? (
|
|
197
|
+
<Box marginBottom={1}>
|
|
198
|
+
<StatusMessage type="info">Resuming session...</StatusMessage>
|
|
199
|
+
</Box>
|
|
200
|
+
) : null}
|
|
201
|
+
{resume.error ? (
|
|
202
|
+
<Box marginBottom={1}>
|
|
203
|
+
<StatusMessage type="error">Resume failed: {resume.error}</StatusMessage>
|
|
204
|
+
</Box>
|
|
205
|
+
) : null}
|
|
206
|
+
|
|
207
|
+
{/* Scrollable message viewport */}
|
|
208
|
+
<ScrollableMessageList
|
|
209
|
+
messages={state.messages}
|
|
210
|
+
width={width}
|
|
211
|
+
viewportHeight={viewportHeight}
|
|
212
|
+
scrollTop={scroll.scrollTop}
|
|
213
|
+
isStreaming={state.isStreaming}
|
|
214
|
+
streamingText={state.streamingText}
|
|
215
|
+
thinkingText={state.thinkingText}
|
|
216
|
+
toolCalls={state.activeToolCalls}
|
|
217
|
+
skills={state.activatedSkills}
|
|
218
|
+
explore={state.explorePhase}
|
|
219
|
+
error={state.error}
|
|
220
|
+
/>
|
|
221
|
+
|
|
222
|
+
{/* Scroll position indicator */}
|
|
223
|
+
{!scroll.isAtBottom && !state.isStreaming ? (
|
|
224
|
+
<Box justifyContent="center">
|
|
225
|
+
<Text color={theme.ui.dim}>{'\u2193'} more below</Text>
|
|
226
|
+
</Box>
|
|
227
|
+
) : null}
|
|
228
|
+
|
|
229
|
+
{/* Notifications */}
|
|
230
|
+
<NotificationBar notifications={state.notifications} onDismiss={dismissNotification} />
|
|
231
|
+
|
|
232
|
+
{/* Session Browser overlay */}
|
|
233
|
+
{state.showSessionBrowser ? (
|
|
234
|
+
<SessionBrowser
|
|
235
|
+
baseUrl={baseUrl}
|
|
236
|
+
onSelect={handleSessionSelect}
|
|
237
|
+
onClose={handleSessionBrowserClose}
|
|
238
|
+
/>
|
|
239
|
+
) : null}
|
|
240
|
+
|
|
241
|
+
{/* Input area — conditional on pending prompts */}
|
|
242
|
+
{!state.showSessionBrowser ? (
|
|
243
|
+
currentConfirmation ? (
|
|
244
|
+
<ConfirmationPrompt
|
|
245
|
+
request={currentConfirmation}
|
|
246
|
+
queueSize={state.confirmationQueue.length}
|
|
247
|
+
onRespond={respondToConfirmation}
|
|
248
|
+
onApproveAll={handleApproveAll}
|
|
249
|
+
onRejectAll={handleRejectAll}
|
|
250
|
+
/>
|
|
251
|
+
) : state.pendingQuestion ? (
|
|
252
|
+
<AskUserPrompt question={state.pendingQuestion} onRespond={respondToQuestion} />
|
|
253
|
+
) : (
|
|
254
|
+
<InputBar
|
|
255
|
+
onSubmit={sendMessage}
|
|
256
|
+
onSlashCommand={handleSlashCommand}
|
|
257
|
+
isStreaming={state.isStreaming}
|
|
258
|
+
elapsed={elapsed}
|
|
259
|
+
exploreQuery={exploreQuery}
|
|
260
|
+
activeToolName={activeToolName}
|
|
261
|
+
/>
|
|
262
|
+
)
|
|
263
|
+
) : null}
|
|
264
|
+
</>
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
if (fullscreen) {
|
|
268
|
+
return (
|
|
269
|
+
<FullScreenLayout header={headerEl} footer={footerEl}>
|
|
270
|
+
{content}
|
|
271
|
+
</FullScreenLayout>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<Box flexDirection="column" width={width}>
|
|
277
|
+
{headerEl}
|
|
278
|
+
{content}
|
|
279
|
+
{footerEl}
|
|
280
|
+
</Box>
|
|
281
|
+
);
|
|
282
|
+
};
|
|
283
|
+
|