agentstudio 0.2.9 → 0.3.1
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/.dockerignore +53 -0
- package/.mcp.json +8 -0
- package/CLAUDE.md +359 -0
- package/DOCKER.md +270 -0
- package/Dockerfile +42 -0
- package/JSONL_TOOLS_README.md +301 -0
- package/LICENSE +603 -0
- package/QUICKSTART.md +253 -0
- package/README.md +176 -24
- package/README.zh-CN.md +200 -0
- package/SOLUTION_SUMMARY.md +249 -0
- package/backend/comprehensive-session-check.js +142 -0
- package/backend/debug-sessions.js +60 -0
- package/backend/docs/chat-clean-1.svg +1 -0
- package/backend/docs/chat-clean.md +60 -0
- package/backend/docs/chat-comprehensive-1.svg +1 -0
- package/backend/docs/chat-comprehensive.md +166 -0
- package/backend/docs/chat_api_sequence_diagram.md +58 -0
- package/backend/docs/command-detection-logic.md +306 -0
- package/backend/docs/command-detection-sequence.md +186 -0
- package/backend/eslint.config.js +25 -0
- package/backend/package.json +103 -0
- package/backend/scripts/README.md +156 -0
- package/backend/scripts/fix-project-names.js +113 -0
- package/backend/scripts/migrate-projects.js +159 -0
- package/backend/src/bin/agentstudio.ts +318 -0
- package/backend/src/bin/serviceManager.ts +469 -0
- package/backend/src/config/index.ts +184 -0
- package/backend/src/config/paths.ts +105 -0
- package/backend/src/config/sdkConfig.ts +126 -0
- package/backend/src/index.ts +434 -0
- package/backend/src/jobs/taskTimeoutMonitor.ts +106 -0
- package/backend/src/middleware/a2aAuth.ts +159 -0
- package/backend/src/middleware/auth.ts +39 -0
- package/backend/src/middleware/httpsOnly.ts +205 -0
- package/backend/src/middleware/rateLimiting.ts +130 -0
- package/backend/src/routes/__tests__/a2a.integration.test.ts +377 -0
- package/backend/src/routes/__tests__/a2a.test.ts +677 -0
- package/backend/src/routes/__tests__/agents.test.ts +327 -0
- package/backend/src/routes/__tests__/sessions.test.ts +345 -0
- package/backend/src/routes/a2a.streaming.test.ts +185 -0
- package/backend/src/routes/a2a.ts +840 -0
- package/backend/src/routes/a2aManagement.ts +545 -0
- package/backend/src/routes/agents.ts +1176 -0
- package/backend/src/routes/auth.ts +151 -0
- package/backend/src/routes/cloudflareTunnel.ts +306 -0
- package/backend/src/routes/commands.ts +524 -0
- package/backend/src/routes/config.ts +193 -0
- package/backend/src/routes/files.ts +375 -0
- package/backend/src/routes/mcp.ts +866 -0
- package/backend/src/routes/mcpAdmin.ts +369 -0
- package/backend/src/routes/mcpAdminManagement.ts +338 -0
- package/backend/src/routes/media.ts +140 -0
- package/backend/src/routes/mediaAuth.ts +150 -0
- package/backend/src/routes/network.ts +68 -0
- package/backend/src/routes/plugins.ts +368 -0
- package/backend/src/routes/projects.ts +1100 -0
- package/backend/src/routes/scheduledTasks.ts +442 -0
- package/backend/src/routes/sessions.ts +1054 -0
- package/backend/src/routes/settings.ts +552 -0
- package/backend/src/routes/skills.ts +319 -0
- package/backend/src/routes/slack.ts +193 -0
- package/backend/src/routes/slides.ts +166 -0
- package/backend/src/routes/subagents.ts +366 -0
- package/backend/src/routes/taskExecutor.ts +243 -0
- package/backend/src/routes/tunnel.ts +317 -0
- package/backend/src/routes/version.ts +239 -0
- package/backend/src/schemas/a2a.ts +352 -0
- package/backend/src/services/__tests__/pluginInstaller.test.ts +316 -0
- package/backend/src/services/__tests__/pluginParser.test.ts +285 -0
- package/backend/src/services/__tests__/pluginPaths.test.ts +212 -0
- package/backend/src/services/__tests__/pluginScanner.test.ts +287 -0
- package/backend/src/services/__tests__/pluginSymlink.test.ts +340 -0
- package/backend/src/services/__tests__/projectMetadataStorage.test.ts +158 -0
- package/backend/src/services/__tests__/sessionConcurrency.test.ts +132 -0
- package/backend/src/services/__tests__/slackAIService.test.ts +561 -0
- package/backend/src/services/__tests__/slackThreadMapper.test.ts +228 -0
- package/backend/src/services/a2a/__tests__/a2aClientTool.integration.test.ts +347 -0
- package/backend/src/services/a2a/__tests__/a2aClientTool.test.ts +710 -0
- package/backend/src/services/a2a/__tests__/a2aConfigService.test.ts +526 -0
- package/backend/src/services/a2a/__tests__/a2aConfigServicePath.test.ts +55 -0
- package/backend/src/services/a2a/__tests__/a2aSdkMcp.test.ts +254 -0
- package/backend/src/services/a2a/__tests__/agentCardService.test.ts +357 -0
- package/backend/src/services/a2a/__tests__/apiKeyService.test.ts +378 -0
- package/backend/src/services/a2a/__tests__/buildQueryOptionsIntegration.test.ts +41 -0
- package/backend/src/services/a2a/__tests__/dynamic_config_verification.test.ts +71 -0
- package/backend/src/services/a2a/__tests__/integrateA2AMcpServer.test.ts +97 -0
- package/backend/src/services/a2a/__tests__/taskManager.integration.test.ts +417 -0
- package/backend/src/services/a2a/__tests__/taskManager.test.ts +511 -0
- package/backend/src/services/a2a/__tests__/webhookService.test.ts +258 -0
- package/backend/src/services/a2a/a2aClientTool.ts +723 -0
- package/backend/src/services/a2a/a2aConfigService.ts +194 -0
- package/backend/src/services/a2a/a2aHistoryService.ts +111 -0
- package/backend/src/services/a2a/a2aIntegration.ts +40 -0
- package/backend/src/services/a2a/a2aQueryService.ts +275 -0
- package/backend/src/services/a2a/a2aSdkMcp.ts +208 -0
- package/backend/src/services/a2a/a2aStreamEvents.ts +166 -0
- package/backend/src/services/a2a/agentCardService.ts +256 -0
- package/backend/src/services/a2a/agentMappingService.ts +202 -0
- package/backend/src/services/a2a/apiKeyService.ts +361 -0
- package/backend/src/services/a2a/taskCleanup.ts +199 -0
- package/backend/src/services/a2a/taskManager.ts +327 -0
- package/backend/src/services/a2a/webhookService.ts +161 -0
- package/backend/src/services/agentStorage.ts +506 -0
- package/backend/src/services/askUserQuestion/askUserQuestionIntegration.ts +68 -0
- package/backend/src/services/askUserQuestion/askUserQuestionMcp.ts +173 -0
- package/backend/src/services/askUserQuestion/index.ts +48 -0
- package/backend/src/services/askUserQuestion/init.ts +53 -0
- package/backend/src/services/askUserQuestion/notificationChannel.ts +218 -0
- package/backend/src/services/askUserQuestion/slackNotificationChannel.ts +150 -0
- package/backend/src/services/askUserQuestion/sseNotificationChannel.ts +102 -0
- package/backend/src/services/askUserQuestion/userInputRegistry.ts +307 -0
- package/backend/src/services/claudeSession.ts +421 -0
- package/backend/src/services/claudeVersionStorage.ts +389 -0
- package/backend/src/services/mcpAdmin/__tests__/adminApiKeyService.test.ts +385 -0
- package/backend/src/services/mcpAdmin/__tests__/mcpAdminRoutes.test.ts +356 -0
- package/backend/src/services/mcpAdmin/__tests__/mcpAdminServer.test.ts +541 -0
- package/backend/src/services/mcpAdmin/__tests__/providerTools.test.ts +347 -0
- package/backend/src/services/mcpAdmin/__tests__/tools.test.ts +463 -0
- package/backend/src/services/mcpAdmin/adminApiKeyService.ts +329 -0
- package/backend/src/services/mcpAdmin/index.ts +19 -0
- package/backend/src/services/mcpAdmin/mcpAdminServer.ts +318 -0
- package/backend/src/services/mcpAdmin/tools/agentTools.ts +390 -0
- package/backend/src/services/mcpAdmin/tools/index.ts +29 -0
- package/backend/src/services/mcpAdmin/tools/mcpServerTools.ts +368 -0
- package/backend/src/services/mcpAdmin/tools/projectTools.ts +415 -0
- package/backend/src/services/mcpAdmin/tools/providerTools.ts +649 -0
- package/backend/src/services/mcpAdmin/tools/systemTools.ts +254 -0
- package/backend/src/services/mcpAdmin/types.ts +155 -0
- package/backend/src/services/messageQueue.ts +80 -0
- package/backend/src/services/pluginInstaller.ts +329 -0
- package/backend/src/services/pluginParser.ts +441 -0
- package/backend/src/services/pluginPaths.ts +270 -0
- package/backend/src/services/pluginScanner.ts +245 -0
- package/backend/src/services/pluginSymlink.ts +241 -0
- package/backend/src/services/projectMetadataStorage.ts +871 -0
- package/backend/src/services/scheduledTaskStorage.ts +377 -0
- package/backend/src/services/schedulerService.ts +668 -0
- package/backend/src/services/sessionManager.ts +738 -0
- package/backend/src/services/skillStorage.ts +521 -0
- package/backend/src/services/slackAIService.ts +1395 -0
- package/backend/src/services/slackClient.ts +110 -0
- package/backend/src/services/slackSessionLock.ts +364 -0
- package/backend/src/services/slackThreadMapper.ts +170 -0
- package/backend/src/services/taskExecutor/BuiltinExecutor.ts +611 -0
- package/backend/src/services/taskExecutor/__tests__/a2a-tasks.test.ts +382 -0
- package/backend/src/services/taskExecutor/__tests__/e2e-workflows.test.ts +528 -0
- package/backend/src/services/taskExecutor/__tests__/error-handling.test.ts +458 -0
- package/backend/src/services/taskExecutor/__tests__/stress.test.ts +400 -0
- package/backend/src/services/taskExecutor/__tests__/taskExecutor.integration.test.ts +240 -0
- package/backend/src/services/taskExecutor/__tests__/timeout-cancellation.test.ts +384 -0
- package/backend/src/services/taskExecutor/index.ts +168 -0
- package/backend/src/services/taskExecutor/taskWorker.ts +222 -0
- package/backend/src/services/taskExecutor/types.ts +179 -0
- package/backend/src/services/telemetry.ts +234 -0
- package/backend/src/services/tunnelService.ts +614 -0
- package/backend/src/types/a2a.ts +372 -0
- package/backend/src/types/agents.ts +161 -0
- package/backend/src/types/claude-history.ts +81 -0
- package/backend/src/types/claude-versions.ts +39 -0
- package/backend/src/types/commands.ts +63 -0
- package/backend/src/types/plugins.ts +157 -0
- package/backend/src/types/projects.ts +64 -0
- package/backend/src/types/scheduledTasks.ts +214 -0
- package/backend/src/types/skills.ts +130 -0
- package/backend/src/types/slack.ts +112 -0
- package/backend/src/types/streaming.ts +13 -0
- package/backend/src/types/subagents.ts +29 -0
- package/backend/src/utils/__tests__/claudeUtils.test.ts +312 -0
- package/backend/src/utils/__tests__/configResolver.test.ts +255 -0
- package/backend/src/utils/__tests__/sessionUtils.test.ts +384 -0
- package/backend/src/utils/agentCardCache.ts +245 -0
- package/backend/src/utils/claudeUtils.ts +377 -0
- package/backend/src/utils/configResolver.ts +175 -0
- package/backend/src/utils/fileUtils.ts +5 -0
- package/backend/src/utils/jwt.ts +104 -0
- package/backend/src/utils/networkUtils.ts +68 -0
- package/backend/src/utils/sessionUtils.ts +303 -0
- package/backend/tsconfig.json +25 -0
- package/backend/vitest.config.ts +29 -0
- package/docker-compose.traefik.yml +59 -0
- package/docker-compose.yml +38 -0
- package/docker-entrypoint.sh +30 -0
- package/docs/CLOUDFLARE_TUNNEL.md +233 -0
- package/docs/CLOUDFLARE_TUNNEL_ARCHITECTURE.md +406 -0
- package/docs/LAVS-IMPLEMENTATION.md +1973 -0
- package/docs/LAVS-SPEC.md +951 -0
- package/docs/QUICK_START_CLOUDFLARE_TUNNEL.md +304 -0
- package/docs/SCHEDULER_CONTROL.md +142 -0
- package/docs/SCHEDULER_STATUS_DISPLAY.md +86 -0
- package/docs/USER_MANUAL.md +1726 -0
- package/docs/USER_MANUAL_EN.md +1408 -0
- package/docs/VERSION_COMPATIBILITY.md +616 -0
- package/docs/api/a2a-endpoints.md +891 -0
- package/docs/guides/unified-task-executor-summary.md +365 -0
- package/docs/guides/unified-task-executor.md +304 -0
- package/docs/screenshots/01-homepage.png +0 -0
- package/docs/screenshots/02-dashboard.png +0 -0
- package/docs/screenshots/03-projects.png +0 -0
- package/docs/screenshots/04-agents.png +0 -0
- package/docs/screenshots/05-mcp-services.png +0 -0
- package/docs/screenshots/06-commands.png +0 -0
- package/docs/screenshots/07-chat.png +0 -0
- package/docs/screenshots/08-skills.png +0 -0
- package/docs/screenshots/09-settings.png +0 -0
- package/docs/screenshots/10-suppliers.png +0 -0
- package/docs/screenshots/11-plugins.png +0 -0
- package/docs/screenshots/agent-create-dialog.png +0 -0
- package/docs/screenshots/agent-edit-dialog.png +0 -0
- package/docs/screenshots/agent-list-overview.png +0 -0
- package/docs/screenshots/agent-tools-selection.png +0 -0
- package/docs/screenshots/agents-management.png +0 -0
- package/docs/screenshots/auto-compacted-session.png +0 -0
- package/docs/screenshots/chat-interface.png +0 -0
- package/docs/screenshots/chat-session-debug.png +0 -0
- package/docs/screenshots/chat-session-history.png +0 -0
- package/docs/screenshots/chat-tools-selection.png +0 -0
- package/docs/screenshots/commands-create-dialog.png +0 -0
- package/docs/screenshots/commands-overview.png +0 -0
- package/docs/screenshots/create-project-dialog.png +0 -0
- package/docs/screenshots/dashboard-overview.png +0 -0
- package/docs/screenshots/file-browser-interface.png +0 -0
- package/docs/screenshots/import-project-dialog.png +0 -0
- package/docs/screenshots/mcp-add-service-dialog.png +0 -0
- package/docs/screenshots/mcp-admin-settings.png +0 -0
- package/docs/screenshots/mcp-import-claude-code.png +0 -0
- package/docs/screenshots/mcp-list-overview.png +0 -0
- package/docs/screenshots/mcp-services-page.png +0 -0
- package/docs/screenshots/password-management-modal.png +0 -0
- package/docs/screenshots/plugins-add-market.png +0 -0
- package/docs/screenshots/plugins-browse.png +0 -0
- package/docs/screenshots/plugins-overview.png +0 -0
- package/docs/screenshots/ppt-editor-chat-interface.png +0 -0
- package/docs/screenshots/project-commands-dialog.png +0 -0
- package/docs/screenshots/project-list-overview.png +0 -0
- package/docs/screenshots/project-memory-dialog.png +0 -0
- package/docs/screenshots/project-settings-dialog.png +0 -0
- package/docs/screenshots/project-subagent-dialog.png +0 -0
- package/docs/screenshots/projects-management.png +0 -0
- package/docs/screenshots/projects-overview.png +0 -0
- package/docs/screenshots/scheduled-tasks-create-dialog.png +0 -0
- package/docs/screenshots/scheduled-tasks-execution-history.png +0 -0
- package/docs/screenshots/scheduled-tasks-overview.png +0 -0
- package/docs/screenshots/session-display-issue.png +0 -0
- package/docs/screenshots/session-messages-fix.png +0 -0
- package/docs/screenshots/session-messages-loaded.png +0 -0
- package/docs/screenshots/settings-general.png +0 -0
- package/docs/screenshots/settings-memory.png +0 -0
- package/docs/screenshots/skills-create-dialog.png +0 -0
- package/docs/screenshots/skills-list-overview.png +0 -0
- package/docs/screenshots/skills-view-detail.png +0 -0
- package/docs/screenshots/slide-preview-after-fix.png +0 -0
- package/docs/screenshots/storybook-basetool-full.png +0 -0
- package/docs/screenshots/storybook-fixed.png +0 -0
- package/docs/screenshots/storybook-tasktool.png +0 -0
- package/docs/screenshots/supplier-add-dialog.png +0 -0
- package/docs/screenshots/supplier-edit-dialog.png +0 -0
- package/docs/screenshots/suppliers-overview.png +0 -0
- package/docs/screenshots/telemetry-settings.png +0 -0
- package/docs/screenshots/version-management-page.png +0 -0
- package/docs-site/.vitepress/cache/deps/@theme_index.js +275 -0
- package/docs-site/.vitepress/cache/deps/@theme_index.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/_metadata.json +58 -0
- package/docs-site/.vitepress/cache/deps/chunk-CN42XFKG.js +12824 -0
- package/docs-site/.vitepress/cache/deps/chunk-CN42XFKG.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/chunk-Y3A3J5YD.js +9719 -0
- package/docs-site/.vitepress/cache/deps/chunk-Y3A3J5YD.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/package.json +3 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4505 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vueuse_core.js +583 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1352 -0
- package/docs-site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1665 -0
- package/docs-site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/vitepress___minisearch.js +1813 -0
- package/docs-site/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
- package/docs-site/.vitepress/cache/deps/vue.js +347 -0
- package/docs-site/.vitepress/cache/deps/vue.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/_metadata.json +52 -0
- package/docs-site/src/.vitepress/cache/deps/chunk-CN42XFKG.js +12824 -0
- package/docs-site/src/.vitepress/cache/deps/chunk-CN42XFKG.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/chunk-Y3A3J5YD.js +9719 -0
- package/docs-site/src/.vitepress/cache/deps/chunk-Y3A3J5YD.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/package.json +3 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4505 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vueuse_core.js +583 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1352 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1665 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___minisearch.js +1813 -0
- package/docs-site/src/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
- package/docs-site/src/.vitepress/cache/deps/vue.js +347 -0
- package/docs-site/src/.vitepress/cache/deps/vue.js.map +7 -0
- package/frontend/.storybook/main.ts +22 -0
- package/frontend/.storybook/preview.ts +27 -0
- package/frontend/.storybook/vitest.setup.ts +7 -0
- package/frontend/README.md +69 -0
- package/frontend/components.json +17 -0
- package/frontend/eslint.config.js +26 -0
- package/frontend/index.html +62 -0
- package/frontend/package-lock.json +7922 -0
- package/frontend/package.json +90 -0
- package/frontend/pnpm-lock.yaml +4714 -0
- package/frontend/postcss.config.js +6 -0
- package/frontend/scripts/extract-chinese.js +146 -0
- package/frontend/src/App.css +42 -0
- package/frontend/src/App.tsx +201 -0
- package/frontend/src/__tests__/smoke.test.tsx +15 -0
- package/frontend/src/agents/README.md +136 -0
- package/frontend/src/agents/chat/index.ts +17 -0
- package/frontend/src/agents/registry.ts +22 -0
- package/frontend/src/agents/slides/components/SlidePreview.tsx +287 -0
- package/frontend/src/agents/slides/components/SlidePreviewPanel.tsx +120 -0
- package/frontend/src/agents/slides/hooks/useSlides.ts +245 -0
- package/frontend/src/agents/slides/index.ts +17 -0
- package/frontend/src/agents/slides/stores/useSlidesStore.ts +56 -0
- package/frontend/src/agents/types.ts +18 -0
- package/frontend/src/api/skills.ts +184 -0
- package/frontend/src/assets/react.svg +1 -0
- package/frontend/src/components/AgentChatPanel.tsx +901 -0
- package/frontend/src/components/ApiSettingsModal.tsx +267 -0
- package/frontend/src/components/BackendOnboardingWizard.tsx +255 -0
- package/frontend/src/components/BackendServiceSwitcher.tsx +356 -0
- package/frontend/src/components/CSVPreview.tsx +465 -0
- package/frontend/src/components/ChatMessageRenderer.tsx +279 -0
- package/frontend/src/components/CommandForm.tsx +560 -0
- package/frontend/src/components/CommandSelector.tsx +218 -0
- package/frontend/src/components/CompactSummary.tsx +52 -0
- package/frontend/src/components/ConfirmDialog.tsx +69 -0
- package/frontend/src/components/DiffViewer.css +78 -0
- package/frontend/src/components/DiffViewer.tsx +89 -0
- package/frontend/src/components/EnvVarsConfig.tsx +113 -0
- package/frontend/src/components/ErrorBoundary.tsx +100 -0
- package/frontend/src/components/ErrorMessage.tsx +197 -0
- package/frontend/src/components/FileBrowser.tsx +480 -0
- package/frontend/src/components/FileContentViewer.tsx +155 -0
- package/frontend/src/components/FileExplorer/FileIcon.tsx +32 -0
- package/frontend/src/components/FileExplorer/FilePreview.tsx +130 -0
- package/frontend/src/components/FileExplorer/FileTabs.tsx +104 -0
- package/frontend/src/components/FileExplorer/FileTreeToolbar.tsx +30 -0
- package/frontend/src/components/FileExplorer/ImagePreview.tsx +86 -0
- package/frontend/src/components/FileExplorer/REFACTOR_SUMMARY.md +117 -0
- package/frontend/src/components/FileExplorer/TabDropdown.tsx +59 -0
- package/frontend/src/components/FileExplorer/TreeNode.tsx +73 -0
- package/frontend/src/components/FileExplorer/constants.ts +16 -0
- package/frontend/src/components/FileExplorer/fileTypes.ts +156 -0
- package/frontend/src/components/FileExplorer/hooks/index.ts +2 -0
- package/frontend/src/components/FileExplorer/hooks/useFileTabs.ts +120 -0
- package/frontend/src/components/FileExplorer/hooks/useLazyFileTree.ts +260 -0
- package/frontend/src/components/FileExplorer/index.ts +15 -0
- package/frontend/src/components/FileExplorer.tsx +1124 -0
- package/frontend/src/components/FloatingToggle.tsx +66 -0
- package/frontend/src/components/ImagePreview.tsx +369 -0
- package/frontend/src/components/JSONLPreview.tsx +421 -0
- package/frontend/src/components/LanguageSwitcher.tsx +32 -0
- package/frontend/src/components/Layout.tsx +57 -0
- package/frontend/src/components/MarkdownMessage.tsx +136 -0
- package/frontend/src/components/McpStatusModal.tsx +272 -0
- package/frontend/src/components/MermaidDiagram.tsx +423 -0
- package/frontend/src/components/MobileChatInput.tsx +158 -0
- package/frontend/src/components/MobileChatToolbar.tsx +164 -0
- package/frontend/src/components/MobileNavigation.tsx +101 -0
- package/frontend/src/components/MobileSettingsModal.tsx +272 -0
- package/frontend/src/components/MobileSidebar.tsx +56 -0
- package/frontend/src/components/PanelToggle.tsx +69 -0
- package/frontend/src/components/ProjectA2AModal.tsx +1430 -0
- package/frontend/src/components/ProjectCommandsModal.tsx +453 -0
- package/frontend/src/components/ProjectMemoryModal.tsx +178 -0
- package/frontend/src/components/ProjectSelector.tsx +498 -0
- package/frontend/src/components/ProjectSettingsModal.tsx +210 -0
- package/frontend/src/components/ProjectSubAgentsModal.tsx +421 -0
- package/frontend/src/components/ProjectTable.tsx +387 -0
- package/frontend/src/components/ProtectedRoute.tsx +123 -0
- package/frontend/src/components/RecentActivity.tsx +145 -0
- package/frontend/src/components/ResponsiveTable.tsx +164 -0
- package/frontend/src/components/RightPanelHeader.tsx +87 -0
- package/frontend/src/components/RightPanelWrapper.tsx +74 -0
- package/frontend/src/components/ScheduledTaskEditor.tsx +718 -0
- package/frontend/src/components/ServiceManagementModal.tsx +794 -0
- package/frontend/src/components/ServiceStatusIndicator.tsx +334 -0
- package/frontend/src/components/SessionsDashboard.tsx +295 -0
- package/frontend/src/components/SessionsDropdown.tsx +168 -0
- package/frontend/src/components/SettingsDropdown.tsx +236 -0
- package/frontend/src/components/SettingsLayout.tsx +16 -0
- package/frontend/src/components/Sidebar.tsx +283 -0
- package/frontend/src/components/SplitLayout.tsx +261 -0
- package/frontend/src/components/SubagentForm.tsx +468 -0
- package/frontend/src/components/SwipeActions.tsx +413 -0
- package/frontend/src/components/SystemPromptEditor.tsx +126 -0
- package/frontend/src/components/TaskExecutionHistory.tsx +373 -0
- package/frontend/src/components/TelemetryProvider.tsx +157 -0
- package/frontend/src/components/ToolUsage.tsx +34 -0
- package/frontend/src/components/ToolsList.tsx +86 -0
- package/frontend/src/components/UnifiedToolSelector.tsx +508 -0
- package/frontend/src/components/UpdateNotification.tsx +105 -0
- package/frontend/src/components/agentChat/AgentChatInput.tsx +249 -0
- package/frontend/src/components/agentChat/AgentChatMobileInput.tsx +266 -0
- package/frontend/src/components/agentChat/AgentCommandSelector.tsx +226 -0
- package/frontend/src/components/agentChat/AgentInputArea.tsx +573 -0
- package/frontend/src/components/agentChat/ChatMessageList.tsx +125 -0
- package/frontend/src/components/agentChat/index.ts +7 -0
- package/frontend/src/components/onboarding/BackendDetectingStep.tsx +42 -0
- package/frontend/src/components/onboarding/BackendFoundStep.tsx +75 -0
- package/frontend/src/components/onboarding/BackendNotFoundStep.tsx +249 -0
- package/frontend/src/components/onboarding/OnboardingCompleteStep.tsx +90 -0
- package/frontend/src/components/onboarding/WelcomeStep.tsx +93 -0
- package/frontend/src/components/plugins/AddMarketplaceModal.tsx +186 -0
- package/frontend/src/components/plugins/BrowsePluginsTab.tsx +262 -0
- package/frontend/src/components/plugins/InstalledPluginsTab.tsx +246 -0
- package/frontend/src/components/plugins/MarketplacesTab.tsx +168 -0
- package/frontend/src/components/plugins/PluginDetailModal.tsx +307 -0
- package/frontend/src/components/settings/version/ClaudeVersionForm.tsx +266 -0
- package/frontend/src/components/settings/version/ClaudeVersionList.tsx +61 -0
- package/frontend/src/components/settings/version/EnvironmentVariablesSection.tsx +173 -0
- package/frontend/src/components/settings/version/ModelConfigSection.tsx +129 -0
- package/frontend/src/components/settings/version/VersionListItem.tsx +133 -0
- package/frontend/src/components/settings/version/VersionTemplateSelector.tsx +53 -0
- package/frontend/src/components/skills/CreateSkillModal.tsx +702 -0
- package/frontend/src/components/skills/SkillDetailModal.tsx +180 -0
- package/frontend/src/components/skills/SkillFileBrowserModal.tsx +67 -0
- package/frontend/src/components/skills/SkillPreview.tsx +150 -0
- package/frontend/src/components/skills/SkillsPage.tsx +329 -0
- package/frontend/src/components/skills/index.ts +4 -0
- package/frontend/src/components/tools/A2ACallTool.tsx +733 -0
- package/frontend/src/components/tools/AskUserQuestionTool.stories.tsx +223 -0
- package/frontend/src/components/tools/AskUserQuestionTool.tsx +546 -0
- package/frontend/src/components/tools/BaseToolComponent.stories.tsx +316 -0
- package/frontend/src/components/tools/BaseToolComponent.tsx +226 -0
- package/frontend/src/components/tools/BashOutputTool.stories.tsx +106 -0
- package/frontend/src/components/tools/BashOutputTool.tsx +198 -0
- package/frontend/src/components/tools/BashTool.stories.tsx +163 -0
- package/frontend/src/components/tools/BashTool.tsx +80 -0
- package/frontend/src/components/tools/EditTool.stories.tsx +109 -0
- package/frontend/src/components/tools/EditTool.tsx +60 -0
- package/frontend/src/components/tools/ExitPlanModeTool.stories.tsx +118 -0
- package/frontend/src/components/tools/ExitPlanModeTool.tsx +34 -0
- package/frontend/src/components/tools/GlobTool.stories.tsx +122 -0
- package/frontend/src/components/tools/GlobTool.tsx +50 -0
- package/frontend/src/components/tools/GrepTool.stories.tsx +125 -0
- package/frontend/src/components/tools/GrepTool.tsx +87 -0
- package/frontend/src/components/tools/KillBashTool.stories.tsx +120 -0
- package/frontend/src/components/tools/KillBashTool.tsx +112 -0
- package/frontend/src/components/tools/LSTool.stories.tsx +132 -0
- package/frontend/src/components/tools/LSTool.tsx +41 -0
- package/frontend/src/components/tools/ListMcpResourcesTool.stories.tsx +125 -0
- package/frontend/src/components/tools/ListMcpResourcesTool.tsx +84 -0
- package/frontend/src/components/tools/McpTool.stories.tsx +140 -0
- package/frontend/src/components/tools/McpTool.tsx +266 -0
- package/frontend/src/components/tools/MultiEditTool.stories.tsx +127 -0
- package/frontend/src/components/tools/MultiEditTool.tsx +59 -0
- package/frontend/src/components/tools/NotebookEditTool.stories.tsx +137 -0
- package/frontend/src/components/tools/NotebookEditTool.tsx +57 -0
- package/frontend/src/components/tools/NotebookReadTool.stories.tsx +134 -0
- package/frontend/src/components/tools/NotebookReadTool.tsx +25 -0
- package/frontend/src/components/tools/README.md +677 -0
- package/frontend/src/components/tools/ReadMcpResourceTool.stories.tsx +125 -0
- package/frontend/src/components/tools/ReadMcpResourceTool.tsx +126 -0
- package/frontend/src/components/tools/ReadTool.stories.tsx +116 -0
- package/frontend/src/components/tools/ReadTool.tsx +37 -0
- package/frontend/src/components/tools/SkillTool.tsx +91 -0
- package/frontend/src/components/tools/SubAgentMessageFlow.tsx +172 -0
- package/frontend/src/components/tools/TaskTool.stories.tsx +483 -0
- package/frontend/src/components/tools/TaskTool.tsx +199 -0
- package/frontend/src/components/tools/TimeMachineTool.stories.tsx +254 -0
- package/frontend/src/components/tools/TimeMachineTool.tsx +126 -0
- package/frontend/src/components/tools/TodoWriteTool.stories.tsx +128 -0
- package/frontend/src/components/tools/TodoWriteTool.tsx +74 -0
- package/frontend/src/components/tools/ToolRenderer.stories.tsx +460 -0
- package/frontend/src/components/tools/ToolRenderer.tsx +147 -0
- package/frontend/src/components/tools/WebFetchTool.stories.tsx +114 -0
- package/frontend/src/components/tools/WebFetchTool.tsx +50 -0
- package/frontend/src/components/tools/WebSearchTool.stories.tsx +124 -0
- package/frontend/src/components/tools/WebSearchTool.tsx +67 -0
- package/frontend/src/components/tools/WriteTool.stories.tsx +115 -0
- package/frontend/src/components/tools/WriteTool.tsx +41 -0
- package/frontend/src/components/tools/__mocks__/toolTestData.ts +557 -0
- package/frontend/src/components/tools/customMcpTools.tsx +17 -0
- package/frontend/src/components/tools/index.stories.tsx +107 -0
- package/frontend/src/components/tools/index.ts +24 -0
- package/frontend/src/components/tools/mcpUtils.ts +27 -0
- package/frontend/src/components/tools/sdk-types.ts +327 -0
- package/frontend/src/components/tools/types.ts +218 -0
- package/frontend/src/components/ui/Button.tsx +39 -0
- package/frontend/src/components/ui/Input.tsx +24 -0
- package/frontend/src/components/ui/Textarea.tsx +23 -0
- package/frontend/src/components/ui/VersionInfo.tsx +116 -0
- package/frontend/src/components/ui/dialog.tsx +90 -0
- package/frontend/src/components/ui/index.ts +4 -0
- package/frontend/src/components/ui/label.tsx +19 -0
- package/frontend/src/components/ui/select.tsx +121 -0
- package/frontend/src/components/ui/table.tsx +117 -0
- package/frontend/src/components/ui/tabs.tsx +124 -0
- package/frontend/src/components/ui/toast.tsx +127 -0
- package/frontend/src/components/ui/toaster.tsx +33 -0
- package/frontend/src/contexts/MobileContext.tsx +109 -0
- package/frontend/src/hooks/__tests__/useAIStreamHandler.test.ts +1198 -0
- package/frontend/src/hooks/agentChat/index.ts +10 -0
- package/frontend/src/hooks/agentChat/useAIStreamHandler.ts +1594 -0
- package/frontend/src/hooks/agentChat/useClaudeVersionManager.ts +99 -0
- package/frontend/src/hooks/agentChat/useCommandCompletion.ts +253 -0
- package/frontend/src/hooks/agentChat/useImageUpload.ts +176 -0
- package/frontend/src/hooks/agentChat/useMessageSender.ts +391 -0
- package/frontend/src/hooks/agentChat/useScrollManagement.ts +66 -0
- package/frontend/src/hooks/agentChat/useSessionManager.ts +110 -0
- package/frontend/src/hooks/agentChat/useToolSelector.ts +82 -0
- package/frontend/src/hooks/agentChat/useUIState.ts +103 -0
- package/frontend/src/hooks/index.ts +3 -0
- package/frontend/src/hooks/use-toast.ts +194 -0
- package/frontend/src/hooks/useA2AConfig.ts +224 -0
- package/frontend/src/hooks/useA2AManagement.ts +456 -0
- package/frontend/src/hooks/useAI.ts +264 -0
- package/frontend/src/hooks/useAgents.ts +411 -0
- package/frontend/src/hooks/useApiBase.ts +31 -0
- package/frontend/src/hooks/useAuth.ts +454 -0
- package/frontend/src/hooks/useBackendServices.ts +58 -0
- package/frontend/src/hooks/useClaudeVersions.ts +128 -0
- package/frontend/src/hooks/useCommands.ts +312 -0
- package/frontend/src/hooks/useDashboardStats.ts +61 -0
- package/frontend/src/hooks/useFileSystem.ts +349 -0
- package/frontend/src/hooks/useFiles.ts +80 -0
- package/frontend/src/hooks/useMarketplaces.ts +120 -0
- package/frontend/src/hooks/useMobile.tsx +110 -0
- package/frontend/src/hooks/usePlugins.ts +239 -0
- package/frontend/src/hooks/useProjects.ts +45 -0
- package/frontend/src/hooks/useResponsiveSettings.tsx +22 -0
- package/frontend/src/hooks/useScheduledTasks.ts +483 -0
- package/frontend/src/hooks/useSessionHeartbeat.ts +173 -0
- package/frontend/src/hooks/useSessionHeartbeatOnSuccess.ts +80 -0
- package/frontend/src/hooks/useSessions.ts +96 -0
- package/frontend/src/hooks/useSkills.ts +197 -0
- package/frontend/src/hooks/useSubagents.ts +274 -0
- package/frontend/src/hooks/useTabNotification.ts +155 -0
- package/frontend/src/hooks/useVersionCheck.ts +164 -0
- package/frontend/src/i18n/index.ts +66 -0
- package/frontend/src/i18n/locales/en-US/agents.json +85 -0
- package/frontend/src/i18n/locales/en-US/common.json +155 -0
- package/frontend/src/i18n/locales/en-US/components.json +1197 -0
- package/frontend/src/i18n/locales/en-US/errors.json +56 -0
- package/frontend/src/i18n/locales/en-US/home.json +27 -0
- package/frontend/src/i18n/locales/en-US/onboarding.json +122 -0
- package/frontend/src/i18n/locales/en-US/pages.json +1409 -0
- package/frontend/src/i18n/locales/en-US/skills.json +120 -0
- package/frontend/src/i18n/locales/zh-CN/agents.json +85 -0
- package/frontend/src/i18n/locales/zh-CN/common.json +155 -0
- package/frontend/src/i18n/locales/zh-CN/components.json +1199 -0
- package/frontend/src/i18n/locales/zh-CN/errors.json +56 -0
- package/frontend/src/i18n/locales/zh-CN/home.json +27 -0
- package/frontend/src/i18n/locales/zh-CN/onboarding.json +122 -0
- package/frontend/src/i18n/locales/zh-CN/pages.json +1540 -0
- package/frontend/src/i18n/locales/zh-CN/pages.json.tmp +0 -0
- package/frontend/src/i18n/locales/zh-CN/pages_new.json +0 -0
- package/frontend/src/i18n/locales/zh-CN/skills.json +120 -0
- package/frontend/src/i18n/types.ts +19 -0
- package/frontend/src/index.css +112 -0
- package/frontend/src/lib/authFetch.ts +183 -0
- package/frontend/src/lib/config.ts +120 -0
- package/frontend/src/lib/utils.ts +6 -0
- package/frontend/src/main.tsx +13 -0
- package/frontend/src/pages/AgentsPage.tsx +781 -0
- package/frontend/src/pages/AnalyticsPage.tsx +363 -0
- package/frontend/src/pages/ChatPage.tsx +286 -0
- package/frontend/src/pages/CommandsPage.tsx +445 -0
- package/frontend/src/pages/DashboardPage.tsx +519 -0
- package/frontend/src/pages/HomePage.tsx +223 -0
- package/frontend/src/pages/LandingPage.tsx +607 -0
- package/frontend/src/pages/LoginPage.tsx +510 -0
- package/frontend/src/pages/McpPage.tsx +1049 -0
- package/frontend/src/pages/PluginsPage.tsx +98 -0
- package/frontend/src/pages/ProjectSettings/A2AConfigTab.tsx +468 -0
- package/frontend/src/pages/ProjectsPage.tsx +818 -0
- package/frontend/src/pages/ScheduledTasksPage.tsx +574 -0
- package/frontend/src/pages/SkillsPage.tsx +6 -0
- package/frontend/src/pages/ToastTestPage.tsx +33 -0
- package/frontend/src/pages/index.ts +3 -0
- package/frontend/src/pages/settings/ApiSettingsPage.tsx +240 -0
- package/frontend/src/pages/settings/CloudflareTunnelPage.tsx +730 -0
- package/frontend/src/pages/settings/GeneralSettingsPage.tsx +456 -0
- package/frontend/src/pages/settings/McpAdminSettingsPage.tsx +1088 -0
- package/frontend/src/pages/settings/MemorySettingsPage.tsx +153 -0
- package/frontend/src/pages/settings/SubagentsPage.tsx +412 -0
- package/frontend/src/pages/settings/SystemInfoPage.tsx +268 -0
- package/frontend/src/pages/settings/TelemetrySettingsPage.tsx +175 -0
- package/frontend/src/pages/settings/VersionSettingsPage.tsx +366 -0
- package/frontend/src/pages/settings/WebSocketTunnelPage.tsx +1578 -0
- package/frontend/src/stores/authStore.ts +99 -0
- package/frontend/src/stores/useAgentStore.ts +426 -0
- package/frontend/src/stores/useSubAgentStore.ts +207 -0
- package/frontend/src/styles/mobile.css +156 -0
- package/frontend/src/test/setup.ts +64 -0
- package/frontend/src/types/agents.ts +109 -0
- package/frontend/src/types/backendServices.ts +20 -0
- package/frontend/src/types/claude-versions.ts +45 -0
- package/frontend/src/types/commands.ts +63 -0
- package/frontend/src/types/index.ts +171 -0
- package/frontend/src/types/plugins.ts +128 -0
- package/frontend/src/types/scheduledTasks.ts +140 -0
- package/frontend/src/types/skills.ts +161 -0
- package/frontend/src/types/subagents.ts +48 -0
- package/frontend/src/types/versionTemplates.ts +270 -0
- package/frontend/src/utils/authHelpers.ts +89 -0
- package/frontend/src/utils/backendServiceStorage.ts +100 -0
- package/frontend/src/utils/commandFormatter.ts +100 -0
- package/frontend/src/utils/commandGenerator.ts +72 -0
- package/frontend/src/utils/commandHandler.ts +205 -0
- package/frontend/src/utils/dateFormat.ts +35 -0
- package/frontend/src/utils/eventBus.ts +53 -0
- package/frontend/src/utils/index.ts +34 -0
- package/frontend/src/utils/onboardingStorage.ts +40 -0
- package/frontend/src/utils/smartNavigation.ts +244 -0
- package/frontend/src/utils/streamReader.ts +32 -0
- package/frontend/src/utils/systemCommands.ts +49 -0
- package/frontend/src/utils/tabManager.ts +816 -0
- package/frontend/src/utils/toast.ts +49 -0
- package/frontend/src/utils/toolMapping.ts +83 -0
- package/frontend/src/vite-env.d.ts +3 -0
- package/frontend/tailwind.config.js +119 -0
- package/frontend/tsconfig.app.json +33 -0
- package/frontend/tsconfig.json +7 -0
- package/frontend/tsconfig.node.json +25 -0
- package/frontend/vite.config.ts +73 -0
- package/frontend/vitest.config.ts +39 -0
- package/frontend/vitest.shims.d.ts +1 -0
- package/nginx.conf +153 -0
- package/package.json +38 -49
- package/pnpm-workspace.yaml +3 -0
- package/scripts/API_KEY_GENERATION_README.md +181 -0
- package/scripts/README-nginx.md +327 -0
- package/scripts/README.md +259 -0
- package/scripts/build-complete.js +98 -0
- package/scripts/build-npm.js +251 -0
- package/scripts/check-system.sh +153 -0
- package/scripts/cloudflare_tunnel.py +292 -0
- package/scripts/deploy-feature.sh +265 -0
- package/scripts/generate-api-key.ts +59 -0
- package/scripts/install-linux.sh +1507 -0
- package/scripts/install-macos.sh +1194 -0
- package/scripts/remote-install.sh +244 -0
- package/scripts/remove-feature.sh +214 -0
- package/scripts/remove.sh +390 -0
- package/scripts/requirements.txt +1 -0
- package/scripts/restore.sh +331 -0
- package/scripts/setup-nginx-ssl.sh +242 -0
- package/scripts/setup_nginx.sh +110 -0
- package/scripts/windows-install-simple.bat +277 -0
- package/scripts/windows-install.ps1 +620 -0
- package/tsconfig.json +30 -0
- package/vercel.json +44 -0
- package/bin/agentstudio.d.ts +0 -3
- package/bin/agentstudio.d.ts.map +0 -1
- package/bin/agentstudio.js +0 -327
- package/bin/agentstudio.js.map +0 -1
- package/bin/serviceManager.d.ts +0 -16
- package/bin/serviceManager.d.ts.map +0 -1
- package/bin/serviceManager.js +0 -434
- package/bin/serviceManager.js.map +0 -1
- package/config/index.d.ts +0 -74
- package/config/index.d.ts.map +0 -1
- package/config/index.js +0 -166
- package/config/index.js.map +0 -1
- package/config/paths.d.ts +0 -81
- package/config/paths.d.ts.map +0 -1
- package/config/paths.js +0 -98
- package/config/paths.js.map +0 -1
- package/index.d.ts +0 -4
- package/index.d.ts.map +0 -1
- package/index.js +0 -423
- package/index.js.map +0 -1
- package/jobs/taskTimeoutMonitor.d.ts +0 -25
- package/jobs/taskTimeoutMonitor.d.ts.map +0 -1
- package/jobs/taskTimeoutMonitor.js +0 -94
- package/jobs/taskTimeoutMonitor.js.map +0 -1
- package/middleware/a2aAuth.d.ts +0 -38
- package/middleware/a2aAuth.d.ts.map +0 -1
- package/middleware/a2aAuth.js +0 -134
- package/middleware/a2aAuth.js.map +0 -1
- package/middleware/auth.d.ts +0 -9
- package/middleware/auth.d.ts.map +0 -1
- package/middleware/auth.js +0 -35
- package/middleware/auth.js.map +0 -1
- package/middleware/httpsOnly.d.ts +0 -75
- package/middleware/httpsOnly.d.ts.map +0 -1
- package/middleware/httpsOnly.js +0 -189
- package/middleware/httpsOnly.js.map +0 -1
- package/middleware/rateLimiting.d.ts +0 -37
- package/middleware/rateLimiting.d.ts.map +0 -1
- package/middleware/rateLimiting.js +0 -118
- package/middleware/rateLimiting.js.map +0 -1
- package/public/assets/AgentsPage-DpXjvy0I.js +0 -10
- package/public/assets/Button-u4yI-WsV.js +0 -1
- package/public/assets/ChatPage-Boj_N_ec.js +0 -471
- package/public/assets/ChatPage-BvQmXfcP.css +0 -1
- package/public/assets/CommandForm-C8RL-p7h.js +0 -7
- package/public/assets/CommandsPage-DJyOtqIu.js +0 -1
- package/public/assets/DashboardPage-CPyJ0iPo.js +0 -1
- package/public/assets/FileBrowser-CXd_LcTz.js +0 -6
- package/public/assets/FileExplorer-DFQ7ynXa.js +0 -1
- package/public/assets/GeneralSettingsPage-BIcZ0Tod.js +0 -1
- package/public/assets/LandingPage-BlWek-wg.js +0 -1
- package/public/assets/LoginPage-j9c0QS1W.js +0 -16
- package/public/assets/McpAdminSettingsPage-Djm1tHK_.js +0 -7
- package/public/assets/McpPage-DjN_N6XO.js +0 -20
- package/public/assets/MemorySettingsPage-C06mG8J-.js +0 -1
- package/public/assets/PluginsPage-C8H1LJqV.js +0 -1
- package/public/assets/ProjectSelector-l8LQCZCe.js +0 -1
- package/public/assets/ProjectsPage-DVGpii1H.js +0 -21
- package/public/assets/ScheduledTasksPage-C9bAZ-8o.js +0 -1
- package/public/assets/SettingsLayout-Bv4IpkB5.js +0 -1
- package/public/assets/SkillsPage-DD-bktLO.js +0 -18
- package/public/assets/SubagentForm-CSRBsxUE.js +0 -7
- package/public/assets/SubagentsPage-BAXwEpQK.js +0 -1
- package/public/assets/SystemInfoPage-41rDcUwB.js +0 -1
- package/public/assets/TelemetrySettingsPage-CyXkNXJH.js +0 -1
- package/public/assets/ToastTestPage-CtcmP941.js +0 -1
- package/public/assets/ToolsList-Ci2lqPin.js +0 -1
- package/public/assets/UnifiedToolSelector-CKjY_qjS.js +0 -1
- package/public/assets/VersionSettingsPage-BLkrL0Ek.js +0 -5
- package/public/assets/WebSocketTunnelPage-McDRE6Ff.js +0 -1
- package/public/assets/_basePickBy-DDGafuFd.js +0 -1
- package/public/assets/_baseUniq-OZ7OoecG.js +0 -1
- package/public/assets/agents-DG431Wop.js +0 -1
- package/public/assets/agents-DwCY2K8p.css +0 -1
- package/public/assets/arc-C2QxosH7.js +0 -1
- package/public/assets/architectureDiagram-VXUJARFQ-gBoRl0vw.js +0 -36
- package/public/assets/blockDiagram-VD42YOAC-DDJh2Okf.js +0 -122
- package/public/assets/c4Diagram-YG6GDRKO-C4b85nLT.js +0 -10
- package/public/assets/channel-4mgiaMWd.js +0 -1
- package/public/assets/chunk-4BX2VUAB--YHjBv7U.js +0 -1
- package/public/assets/chunk-55IACEB6-B2-h5gVj.js +0 -1
- package/public/assets/chunk-B4BG7PRW-DRi5viyb.js +0 -165
- package/public/assets/chunk-DI55MBZ5-Xk-YhQRJ.js +0 -220
- package/public/assets/chunk-FMBD7UC4-DDcnlWsh.js +0 -15
- package/public/assets/chunk-QN33PNHL-OXq0iw2q.js +0 -1
- package/public/assets/chunk-QZHKN3VN-D7P0oOa9.js +0 -1
- package/public/assets/chunk-TZMSLE5B-Cts6I75U.js +0 -1
- package/public/assets/classDiagram-2ON5EDUG-BLM7y3rH.js +0 -1
- package/public/assets/classDiagram-v2-WZHVMYZB-BLM7y3rH.js +0 -1
- package/public/assets/clone-BHGNnQ0D.js +0 -1
- package/public/assets/cose-bilkent-S5V4N54A-6uP92_NU.js +0 -1
- package/public/assets/cytoscape.esm-DtBltrT8.js +0 -331
- package/public/assets/dagre-6UL2VRFP-CK2VJLzv.js +0 -4
- package/public/assets/data-structures-C0h9Oap1.js +0 -27
- package/public/assets/dateFormat-CXa8VnEC.js +0 -1
- package/public/assets/defaultLocale-C4B-KCzX.js +0 -1
- package/public/assets/diagram-PSM6KHXK-C-ZaY5UR.js +0 -24
- package/public/assets/diagram-QEK2KX5R-KM9LoLux.js +0 -43
- package/public/assets/diagram-S2PKOQOG-C8uziTLV.js +0 -24
- package/public/assets/erDiagram-Q2GNP2WA-DHFQ6rZ5.js +0 -60
- package/public/assets/flowDiagram-NV44I4VS-CzNBOu8h.js +0 -162
- package/public/assets/ganttDiagram-LVOFAZNH-vqd0zpgi.js +0 -267
- package/public/assets/gitGraphDiagram-NY62KEGX-BOW5S00P.js +0 -65
- package/public/assets/graph-BP_Rwsef.js +0 -1
- package/public/assets/index-DBxcQY5U.css +0 -1
- package/public/assets/index-h5dd40hU.js +0 -297
- package/public/assets/infoDiagram-F6ZHWCRC-LVLvTvsq.js +0 -2
- package/public/assets/init-Gi6I4Gst.js +0 -1
- package/public/assets/journeyDiagram-XKPGCS4Q-Cf_fvy7_.js +0 -139
- package/public/assets/kanban-definition-3W4ZIXB7-u6UccFfM.js +0 -89
- package/public/assets/katex-qrhCpa0F.js +0 -261
- package/public/assets/layout-sH_TKNrG.js +0 -1
- package/public/assets/linear-BdE0kKFb.js +0 -1
- package/public/assets/mindmap-definition-VGOIOE7T-9d-rVW5A.js +0 -68
- package/public/assets/monaco-editor-DHKm5-VF.js +0 -19
- package/public/assets/ordinal-Cboi1Yqb.js +0 -1
- package/public/assets/pieDiagram-ADFJNKIX-U_y5PbGf.js +0 -30
- package/public/assets/quadrantDiagram-AYHSOK5B-DGb0hrEb.js +0 -7
- package/public/assets/requirementDiagram-UZGBJVZJ-DNTHnK1t.js +0 -64
- package/public/assets/sankeyDiagram-TZEHDZUN-5uBZF1V2.js +0 -10
- package/public/assets/sequenceDiagram-WL72ISMW-AeCHCuPt.js +0 -145
- package/public/assets/stateDiagram-FKZM4ZOC-CXM0ycgk.js +0 -1
- package/public/assets/stateDiagram-v2-4FDKWEC3-FWopaxaM.js +0 -1
- package/public/assets/syntax-highlighting-CnREyncB.js +0 -24
- package/public/assets/table-CUyJSNAf.js +0 -1
- package/public/assets/timeline-definition-IT6M3QCI-BXZLvFn7.js +0 -61
- package/public/assets/tools-C0JOzoE_.js +0 -1
- package/public/assets/treemap-KMMF4GRG-BcB7MUc4.js +0 -128
- package/public/assets/ui-components-CRCmgMKc.js +0 -646
- package/public/assets/useAgents-Bp5Ry-Dk.js +0 -2
- package/public/assets/useClaudeVersions-DYM2HCGW.js +0 -1
- package/public/assets/useCommands-B0s3JzZs.js +0 -1
- package/public/assets/useProjects-DuCnMeYt.js +0 -1
- package/public/assets/useSessions-EknKfdIv.js +0 -1
- package/public/assets/xychartDiagram-PRI3JC2R-BsE7x9kD.js +0 -7
- package/public/index.html +0 -70
- package/routes/__tests__/a2a.integration.test.d.ts +0 -11
- package/routes/__tests__/a2a.integration.test.d.ts.map +0 -1
- package/routes/__tests__/a2a.integration.test.js +0 -314
- package/routes/__tests__/a2a.integration.test.js.map +0 -1
- package/routes/__tests__/a2a.test.d.ts +0 -6
- package/routes/__tests__/a2a.test.d.ts.map +0 -1
- package/routes/__tests__/a2a.test.js +0 -622
- package/routes/__tests__/a2a.test.js.map +0 -1
- package/routes/__tests__/agents.test.d.ts +0 -6
- package/routes/__tests__/agents.test.d.ts.map +0 -1
- package/routes/__tests__/agents.test.js +0 -315
- package/routes/__tests__/agents.test.js.map +0 -1
- package/routes/__tests__/sessions.test.d.ts +0 -7
- package/routes/__tests__/sessions.test.d.ts.map +0 -1
- package/routes/__tests__/sessions.test.js +0 -330
- package/routes/__tests__/sessions.test.js.map +0 -1
- package/routes/a2a.d.ts +0 -18
- package/routes/a2a.d.ts.map +0 -1
- package/routes/a2a.js +0 -717
- package/routes/a2a.js.map +0 -1
- package/routes/a2a.streaming.test.d.ts +0 -2
- package/routes/a2a.streaming.test.d.ts.map +0 -1
- package/routes/a2a.streaming.test.js +0 -167
- package/routes/a2a.streaming.test.js.map +0 -1
- package/routes/a2aManagement.d.ts +0 -21
- package/routes/a2aManagement.d.ts.map +0 -1
- package/routes/a2aManagement.js +0 -466
- package/routes/a2aManagement.js.map +0 -1
- package/routes/agents.d.ts +0 -4
- package/routes/agents.d.ts.map +0 -1
- package/routes/agents.js +0 -1026
- package/routes/agents.js.map +0 -1
- package/routes/auth.d.ts +0 -4
- package/routes/auth.d.ts.map +0 -1
- package/routes/auth.js +0 -135
- package/routes/auth.js.map +0 -1
- package/routes/cloudflareTunnel.d.ts +0 -4
- package/routes/cloudflareTunnel.d.ts.map +0 -1
- package/routes/cloudflareTunnel.js +0 -250
- package/routes/cloudflareTunnel.js.map +0 -1
- package/routes/commands.d.ts +0 -4
- package/routes/commands.d.ts.map +0 -1
- package/routes/commands.js +0 -479
- package/routes/commands.js.map +0 -1
- package/routes/config.d.ts +0 -4
- package/routes/config.d.ts.map +0 -1
- package/routes/config.js +0 -211
- package/routes/config.js.map +0 -1
- package/routes/files.d.ts +0 -4
- package/routes/files.d.ts.map +0 -1
- package/routes/files.js +0 -361
- package/routes/files.js.map +0 -1
- package/routes/mcp.d.ts +0 -26
- package/routes/mcp.d.ts.map +0 -1
- package/routes/mcp.js +0 -796
- package/routes/mcp.js.map +0 -1
- package/routes/mcpAdmin.d.ts +0 -16
- package/routes/mcpAdmin.d.ts.map +0 -1
- package/routes/mcpAdmin.js +0 -308
- package/routes/mcpAdmin.js.map +0 -1
- package/routes/mcpAdminManagement.d.ts +0 -17
- package/routes/mcpAdminManagement.d.ts.map +0 -1
- package/routes/mcpAdminManagement.js +0 -345
- package/routes/mcpAdminManagement.js.map +0 -1
- package/routes/media.d.ts +0 -5
- package/routes/media.d.ts.map +0 -1
- package/routes/media.js +0 -127
- package/routes/media.js.map +0 -1
- package/routes/mediaAuth.d.ts +0 -8
- package/routes/mediaAuth.d.ts.map +0 -1
- package/routes/mediaAuth.js +0 -136
- package/routes/mediaAuth.js.map +0 -1
- package/routes/plugins.d.ts +0 -4
- package/routes/plugins.d.ts.map +0 -1
- package/routes/plugins.js +0 -339
- package/routes/plugins.js.map +0 -1
- package/routes/projects.d.ts +0 -4
- package/routes/projects.d.ts.map +0 -1
- package/routes/projects.js +0 -1000
- package/routes/projects.js.map +0 -1
- package/routes/scheduledTasks.d.ts +0 -9
- package/routes/scheduledTasks.d.ts.map +0 -1
- package/routes/scheduledTasks.js +0 -386
- package/routes/scheduledTasks.js.map +0 -1
- package/routes/sessions.d.ts +0 -4
- package/routes/sessions.d.ts.map +0 -1
- package/routes/sessions.js +0 -966
- package/routes/sessions.js.map +0 -1
- package/routes/settings.d.ts +0 -4
- package/routes/settings.d.ts.map +0 -1
- package/routes/settings.js +0 -499
- package/routes/settings.js.map +0 -1
- package/routes/skills.d.ts +0 -4
- package/routes/skills.d.ts.map +0 -1
- package/routes/skills.js +0 -272
- package/routes/skills.js.map +0 -1
- package/routes/slack.d.ts +0 -10
- package/routes/slack.d.ts.map +0 -1
- package/routes/slack.js +0 -189
- package/routes/slack.js.map +0 -1
- package/routes/slides.d.ts +0 -4
- package/routes/slides.d.ts.map +0 -1
- package/routes/slides.js +0 -148
- package/routes/slides.js.map +0 -1
- package/routes/subagents.d.ts +0 -4
- package/routes/subagents.d.ts.map +0 -1
- package/routes/subagents.js +0 -331
- package/routes/subagents.js.map +0 -1
- package/routes/taskExecutor.d.ts +0 -9
- package/routes/taskExecutor.d.ts.map +0 -1
- package/routes/taskExecutor.js +0 -224
- package/routes/taskExecutor.js.map +0 -1
- package/routes/tunnel.d.ts +0 -10
- package/routes/tunnel.d.ts.map +0 -1
- package/routes/tunnel.js +0 -296
- package/routes/tunnel.js.map +0 -1
- package/routes/version.d.ts +0 -4
- package/routes/version.d.ts.map +0 -1
- package/routes/version.js +0 -216
- package/routes/version.js.map +0 -1
- package/schemas/a2a.d.ts +0 -946
- package/schemas/a2a.d.ts.map +0 -1
- package/schemas/a2a.js +0 -316
- package/schemas/a2a.js.map +0 -1
- package/scripts/postinstall.js +0 -10
- package/services/__tests__/pluginInstaller.test.d.ts +0 -5
- package/services/__tests__/pluginInstaller.test.d.ts.map +0 -1
- package/services/__tests__/pluginInstaller.test.js +0 -290
- package/services/__tests__/pluginInstaller.test.js.map +0 -1
- package/services/__tests__/pluginParser.test.d.ts +0 -5
- package/services/__tests__/pluginParser.test.d.ts.map +0 -1
- package/services/__tests__/pluginParser.test.js +0 -272
- package/services/__tests__/pluginParser.test.js.map +0 -1
- package/services/__tests__/pluginPaths.test.d.ts +0 -5
- package/services/__tests__/pluginPaths.test.d.ts.map +0 -1
- package/services/__tests__/pluginPaths.test.js +0 -221
- package/services/__tests__/pluginPaths.test.js.map +0 -1
- package/services/__tests__/pluginScanner.test.d.ts +0 -5
- package/services/__tests__/pluginScanner.test.d.ts.map +0 -1
- package/services/__tests__/pluginScanner.test.js +0 -272
- package/services/__tests__/pluginScanner.test.js.map +0 -1
- package/services/__tests__/pluginSymlink.test.d.ts +0 -5
- package/services/__tests__/pluginSymlink.test.d.ts.map +0 -1
- package/services/__tests__/pluginSymlink.test.js +0 -318
- package/services/__tests__/pluginSymlink.test.js.map +0 -1
- package/services/__tests__/projectMetadataStorage.test.d.ts +0 -5
- package/services/__tests__/projectMetadataStorage.test.d.ts.map +0 -1
- package/services/__tests__/projectMetadataStorage.test.js +0 -154
- package/services/__tests__/projectMetadataStorage.test.js.map +0 -1
- package/services/__tests__/sessionConcurrency.test.d.ts +0 -7
- package/services/__tests__/sessionConcurrency.test.d.ts.map +0 -1
- package/services/__tests__/sessionConcurrency.test.js +0 -110
- package/services/__tests__/sessionConcurrency.test.js.map +0 -1
- package/services/__tests__/slackAIService.test.d.ts +0 -5
- package/services/__tests__/slackAIService.test.d.ts.map +0 -1
- package/services/__tests__/slackAIService.test.js +0 -479
- package/services/__tests__/slackAIService.test.js.map +0 -1
- package/services/__tests__/slackThreadMapper.test.d.ts +0 -5
- package/services/__tests__/slackThreadMapper.test.d.ts.map +0 -1
- package/services/__tests__/slackThreadMapper.test.js +0 -194
- package/services/__tests__/slackThreadMapper.test.js.map +0 -1
- package/services/a2a/__tests__/a2aClientTool.integration.test.d.ts +0 -6
- package/services/a2a/__tests__/a2aClientTool.integration.test.d.ts.map +0 -1
- package/services/a2a/__tests__/a2aClientTool.integration.test.js +0 -264
- package/services/a2a/__tests__/a2aClientTool.integration.test.js.map +0 -1
- package/services/a2a/__tests__/a2aClientTool.test.d.ts +0 -6
- package/services/a2a/__tests__/a2aClientTool.test.d.ts.map +0 -1
- package/services/a2a/__tests__/a2aClientTool.test.js +0 -592
- package/services/a2a/__tests__/a2aClientTool.test.js.map +0 -1
- package/services/a2a/__tests__/a2aConfigService.test.d.ts +0 -6
- package/services/a2a/__tests__/a2aConfigService.test.d.ts.map +0 -1
- package/services/a2a/__tests__/a2aConfigService.test.js +0 -431
- package/services/a2a/__tests__/a2aConfigService.test.js.map +0 -1
- package/services/a2a/__tests__/a2aConfigServicePath.test.d.ts +0 -2
- package/services/a2a/__tests__/a2aConfigServicePath.test.d.ts.map +0 -1
- package/services/a2a/__tests__/a2aConfigServicePath.test.js +0 -49
- package/services/a2a/__tests__/a2aConfigServicePath.test.js.map +0 -1
- package/services/a2a/__tests__/a2aSdkMcp.test.d.ts +0 -10
- package/services/a2a/__tests__/a2aSdkMcp.test.d.ts.map +0 -1
- package/services/a2a/__tests__/a2aSdkMcp.test.js +0 -239
- package/services/a2a/__tests__/a2aSdkMcp.test.js.map +0 -1
- package/services/a2a/__tests__/agentCardService.test.d.ts +0 -6
- package/services/a2a/__tests__/agentCardService.test.d.ts.map +0 -1
- package/services/a2a/__tests__/agentCardService.test.js +0 -292
- package/services/a2a/__tests__/agentCardService.test.js.map +0 -1
- package/services/a2a/__tests__/apiKeyService.test.d.ts +0 -6
- package/services/a2a/__tests__/apiKeyService.test.d.ts.map +0 -1
- package/services/a2a/__tests__/apiKeyService.test.js +0 -284
- package/services/a2a/__tests__/apiKeyService.test.js.map +0 -1
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.d.ts +0 -2
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.d.ts.map +0 -1
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.js +0 -70
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.js.map +0 -1
- package/services/a2a/__tests__/dynamic_config_verification.test.d.ts +0 -2
- package/services/a2a/__tests__/dynamic_config_verification.test.d.ts.map +0 -1
- package/services/a2a/__tests__/dynamic_config_verification.test.js +0 -67
- package/services/a2a/__tests__/dynamic_config_verification.test.js.map +0 -1
- package/services/a2a/__tests__/integrateA2AMcpServer.test.d.ts +0 -2
- package/services/a2a/__tests__/integrateA2AMcpServer.test.d.ts.map +0 -1
- package/services/a2a/__tests__/integrateA2AMcpServer.test.js +0 -112
- package/services/a2a/__tests__/integrateA2AMcpServer.test.js.map +0 -1
- package/services/a2a/__tests__/taskManager.integration.test.d.ts +0 -7
- package/services/a2a/__tests__/taskManager.integration.test.d.ts.map +0 -1
- package/services/a2a/__tests__/taskManager.integration.test.js +0 -346
- package/services/a2a/__tests__/taskManager.integration.test.js.map +0 -1
- package/services/a2a/__tests__/taskManager.test.d.ts +0 -7
- package/services/a2a/__tests__/taskManager.test.d.ts.map +0 -1
- package/services/a2a/__tests__/taskManager.test.js +0 -423
- package/services/a2a/__tests__/taskManager.test.js.map +0 -1
- package/services/a2a/__tests__/webhookService.test.d.ts +0 -6
- package/services/a2a/__tests__/webhookService.test.d.ts.map +0 -1
- package/services/a2a/__tests__/webhookService.test.js +0 -196
- package/services/a2a/__tests__/webhookService.test.js.map +0 -1
- package/services/a2a/a2aClientTool.d.ts +0 -73
- package/services/a2a/a2aClientTool.d.ts.map +0 -1
- package/services/a2a/a2aClientTool.js +0 -595
- package/services/a2a/a2aClientTool.js.map +0 -1
- package/services/a2a/a2aConfigService.d.ts +0 -50
- package/services/a2a/a2aConfigService.d.ts.map +0 -1
- package/services/a2a/a2aConfigService.js +0 -186
- package/services/a2a/a2aConfigService.js.map +0 -1
- package/services/a2a/a2aHistoryService.d.ts +0 -32
- package/services/a2a/a2aHistoryService.d.ts.map +0 -1
- package/services/a2a/a2aHistoryService.js +0 -108
- package/services/a2a/a2aHistoryService.js.map +0 -1
- package/services/a2a/a2aIntegration.d.ts +0 -10
- package/services/a2a/a2aIntegration.d.ts.map +0 -1
- package/services/a2a/a2aIntegration.js +0 -42
- package/services/a2a/a2aIntegration.js.map +0 -1
- package/services/a2a/a2aQueryService.d.ts +0 -71
- package/services/a2a/a2aQueryService.d.ts.map +0 -1
- package/services/a2a/a2aQueryService.js +0 -209
- package/services/a2a/a2aQueryService.js.map +0 -1
- package/services/a2a/a2aSdkMcp.d.ts +0 -52
- package/services/a2a/a2aSdkMcp.d.ts.map +0 -1
- package/services/a2a/a2aSdkMcp.js +0 -188
- package/services/a2a/a2aSdkMcp.js.map +0 -1
- package/services/a2a/a2aStreamEvents.d.ts +0 -94
- package/services/a2a/a2aStreamEvents.d.ts.map +0 -1
- package/services/a2a/a2aStreamEvents.js +0 -92
- package/services/a2a/a2aStreamEvents.js.map +0 -1
- package/services/a2a/agentCardService.d.ts +0 -34
- package/services/a2a/agentCardService.d.ts.map +0 -1
- package/services/a2a/agentCardService.js +0 -228
- package/services/a2a/agentCardService.js.map +0 -1
- package/services/a2a/agentMappingService.d.ts +0 -53
- package/services/a2a/agentMappingService.d.ts.map +0 -1
- package/services/a2a/agentMappingService.js +0 -185
- package/services/a2a/agentMappingService.js.map +0 -1
- package/services/a2a/apiKeyService.d.ts +0 -101
- package/services/a2a/apiKeyService.d.ts.map +0 -1
- package/services/a2a/apiKeyService.js +0 -314
- package/services/a2a/apiKeyService.js.map +0 -1
- package/services/a2a/taskCleanup.d.ts +0 -30
- package/services/a2a/taskCleanup.d.ts.map +0 -1
- package/services/a2a/taskCleanup.js +0 -184
- package/services/a2a/taskCleanup.js.map +0 -1
- package/services/a2a/taskManager.d.ts +0 -87
- package/services/a2a/taskManager.d.ts.map +0 -1
- package/services/a2a/taskManager.js +0 -265
- package/services/a2a/taskManager.js.map +0 -1
- package/services/a2a/webhookService.d.ts +0 -30
- package/services/a2a/webhookService.d.ts.map +0 -1
- package/services/a2a/webhookService.js +0 -113
- package/services/a2a/webhookService.js.map +0 -1
- package/services/agentStorage.d.ts +0 -27
- package/services/agentStorage.d.ts.map +0 -1
- package/services/agentStorage.js +0 -487
- package/services/agentStorage.js.map +0 -1
- package/services/askUserQuestion/askUserQuestionIntegration.d.ts +0 -24
- package/services/askUserQuestion/askUserQuestionIntegration.d.ts.map +0 -1
- package/services/askUserQuestion/askUserQuestionIntegration.js +0 -52
- package/services/askUserQuestion/askUserQuestionIntegration.js.map +0 -1
- package/services/askUserQuestion/askUserQuestionMcp.d.ts +0 -103
- package/services/askUserQuestion/askUserQuestionMcp.d.ts.map +0 -1
- package/services/askUserQuestion/askUserQuestionMcp.js +0 -129
- package/services/askUserQuestion/askUserQuestionMcp.js.map +0 -1
- package/services/askUserQuestion/index.d.ts +0 -13
- package/services/askUserQuestion/index.d.ts.map +0 -1
- package/services/askUserQuestion/index.js +0 -35
- package/services/askUserQuestion/index.js.map +0 -1
- package/services/askUserQuestion/init.d.ts +0 -17
- package/services/askUserQuestion/init.d.ts.map +0 -1
- package/services/askUserQuestion/init.js +0 -47
- package/services/askUserQuestion/init.js.map +0 -1
- package/services/askUserQuestion/notificationChannel.d.ts +0 -97
- package/services/askUserQuestion/notificationChannel.d.ts.map +0 -1
- package/services/askUserQuestion/notificationChannel.js +0 -147
- package/services/askUserQuestion/notificationChannel.js.map +0 -1
- package/services/askUserQuestion/slackNotificationChannel.d.ts +0 -35
- package/services/askUserQuestion/slackNotificationChannel.d.ts.map +0 -1
- package/services/askUserQuestion/slackNotificationChannel.js +0 -129
- package/services/askUserQuestion/slackNotificationChannel.js.map +0 -1
- package/services/askUserQuestion/sseNotificationChannel.d.ts +0 -36
- package/services/askUserQuestion/sseNotificationChannel.d.ts.map +0 -1
- package/services/askUserQuestion/sseNotificationChannel.js +0 -88
- package/services/askUserQuestion/sseNotificationChannel.js.map +0 -1
- package/services/askUserQuestion/userInputRegistry.d.ts +0 -107
- package/services/askUserQuestion/userInputRegistry.d.ts.map +0 -1
- package/services/askUserQuestion/userInputRegistry.js +0 -253
- package/services/askUserQuestion/userInputRegistry.js.map +0 -1
- package/services/claudeSession.d.ts +0 -113
- package/services/claudeSession.d.ts.map +0 -1
- package/services/claudeSession.js +0 -375
- package/services/claudeSession.js.map +0 -1
- package/services/claudeVersionStorage.d.ts +0 -20
- package/services/claudeVersionStorage.d.ts.map +0 -1
- package/services/claudeVersionStorage.js +0 -331
- package/services/claudeVersionStorage.js.map +0 -1
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts +0 -5
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts.map +0 -1
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js +0 -289
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js.map +0 -1
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts +0 -5
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts.map +0 -1
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js +0 -345
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js.map +0 -1
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts +0 -5
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts.map +0 -1
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js +0 -453
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js.map +0 -1
- package/services/mcpAdmin/__tests__/providerTools.test.d.ts +0 -7
- package/services/mcpAdmin/__tests__/providerTools.test.d.ts.map +0 -1
- package/services/mcpAdmin/__tests__/providerTools.test.js +0 -258
- package/services/mcpAdmin/__tests__/providerTools.test.js.map +0 -1
- package/services/mcpAdmin/__tests__/tools.test.d.ts +0 -5
- package/services/mcpAdmin/__tests__/tools.test.d.ts.map +0 -1
- package/services/mcpAdmin/__tests__/tools.test.js +0 -389
- package/services/mcpAdmin/__tests__/tools.test.js.map +0 -1
- package/services/mcpAdmin/adminApiKeyService.d.ts +0 -61
- package/services/mcpAdmin/adminApiKeyService.d.ts.map +0 -1
- package/services/mcpAdmin/adminApiKeyService.js +0 -270
- package/services/mcpAdmin/adminApiKeyService.js.map +0 -1
- package/services/mcpAdmin/index.d.ts +0 -10
- package/services/mcpAdmin/index.d.ts.map +0 -1
- package/services/mcpAdmin/index.js +0 -43
- package/services/mcpAdmin/index.js.map +0 -1
- package/services/mcpAdmin/mcpAdminServer.d.ts +0 -76
- package/services/mcpAdmin/mcpAdminServer.d.ts.map +0 -1
- package/services/mcpAdmin/mcpAdminServer.js +0 -243
- package/services/mcpAdmin/mcpAdminServer.js.map +0 -1
- package/services/mcpAdmin/tools/agentTools.d.ts +0 -27
- package/services/mcpAdmin/tools/agentTools.d.ts.map +0 -1
- package/services/mcpAdmin/tools/agentTools.js +0 -352
- package/services/mcpAdmin/tools/agentTools.js.map +0 -1
- package/services/mcpAdmin/tools/index.d.ts +0 -16
- package/services/mcpAdmin/tools/index.d.ts.map +0 -1
- package/services/mcpAdmin/tools/index.js +0 -34
- package/services/mcpAdmin/tools/index.js.map +0 -1
- package/services/mcpAdmin/tools/mcpServerTools.d.ts +0 -27
- package/services/mcpAdmin/tools/mcpServerTools.d.ts.map +0 -1
- package/services/mcpAdmin/tools/mcpServerTools.js +0 -334
- package/services/mcpAdmin/tools/mcpServerTools.js.map +0 -1
- package/services/mcpAdmin/tools/projectTools.d.ts +0 -27
- package/services/mcpAdmin/tools/projectTools.d.ts.map +0 -1
- package/services/mcpAdmin/tools/projectTools.js +0 -382
- package/services/mcpAdmin/tools/projectTools.js.map +0 -1
- package/services/mcpAdmin/tools/providerTools.d.ts +0 -40
- package/services/mcpAdmin/tools/providerTools.d.ts.map +0 -1
- package/services/mcpAdmin/tools/providerTools.js +0 -581
- package/services/mcpAdmin/tools/providerTools.js.map +0 -1
- package/services/mcpAdmin/tools/systemTools.d.ts +0 -23
- package/services/mcpAdmin/tools/systemTools.d.ts.map +0 -1
- package/services/mcpAdmin/tools/systemTools.js +0 -241
- package/services/mcpAdmin/tools/systemTools.js.map +0 -1
- package/services/mcpAdmin/types.d.ts +0 -124
- package/services/mcpAdmin/types.d.ts.map +0 -1
- package/services/mcpAdmin/types.js +0 -18
- package/services/mcpAdmin/types.js.map +0 -1
- package/services/messageQueue.d.ts +0 -31
- package/services/messageQueue.d.ts.map +0 -1
- package/services/messageQueue.js +0 -80
- package/services/messageQueue.js.map +0 -1
- package/services/pluginInstaller.d.ts +0 -58
- package/services/pluginInstaller.d.ts.map +0 -1
- package/services/pluginInstaller.js +0 -321
- package/services/pluginInstaller.js.map +0 -1
- package/services/pluginParser.d.ts +0 -45
- package/services/pluginParser.d.ts.map +0 -1
- package/services/pluginParser.js +0 -437
- package/services/pluginParser.js.map +0 -1
- package/services/pluginPaths.d.ts +0 -80
- package/services/pluginPaths.d.ts.map +0 -1
- package/services/pluginPaths.js +0 -274
- package/services/pluginPaths.js.map +0 -1
- package/services/pluginScanner.d.ts +0 -36
- package/services/pluginScanner.d.ts.map +0 -1
- package/services/pluginScanner.js +0 -251
- package/services/pluginScanner.js.map +0 -1
- package/services/pluginSymlink.d.ts +0 -54
- package/services/pluginSymlink.d.ts.map +0 -1
- package/services/pluginSymlink.js +0 -223
- package/services/pluginSymlink.js.map +0 -1
- package/services/projectMetadataStorage.d.ts +0 -121
- package/services/projectMetadataStorage.d.ts.map +0 -1
- package/services/projectMetadataStorage.js +0 -808
- package/services/projectMetadataStorage.js.map +0 -1
- package/services/scheduledTaskStorage.d.ts +0 -63
- package/services/scheduledTaskStorage.d.ts.map +0 -1
- package/services/scheduledTaskStorage.js +0 -351
- package/services/scheduledTaskStorage.js.map +0 -1
- package/services/schedulerService.d.ts +0 -91
- package/services/schedulerService.d.ts.map +0 -1
- package/services/schedulerService.js +0 -590
- package/services/schedulerService.js.map +0 -1
- package/services/sessionManager.d.ts +0 -176
- package/services/sessionManager.d.ts.map +0 -1
- package/services/sessionManager.js +0 -647
- package/services/sessionManager.js.map +0 -1
- package/services/skillStorage.d.ts +0 -60
- package/services/skillStorage.d.ts.map +0 -1
- package/services/skillStorage.js +0 -398
- package/services/skillStorage.js.map +0 -1
- package/services/slackAIService.d.ts +0 -81
- package/services/slackAIService.d.ts.map +0 -1
- package/services/slackAIService.js +0 -1137
- package/services/slackAIService.js.map +0 -1
- package/services/slackClient.d.ts +0 -46
- package/services/slackClient.d.ts.map +0 -1
- package/services/slackClient.js +0 -85
- package/services/slackClient.js.map +0 -1
- package/services/slackSessionLock.d.ts +0 -79
- package/services/slackSessionLock.d.ts.map +0 -1
- package/services/slackSessionLock.js +0 -353
- package/services/slackSessionLock.js.map +0 -1
- package/services/slackThreadMapper.d.ts +0 -57
- package/services/slackThreadMapper.d.ts.map +0 -1
- package/services/slackThreadMapper.js +0 -140
- package/services/slackThreadMapper.js.map +0 -1
- package/services/taskExecutor/BuiltinExecutor.d.ts +0 -44
- package/services/taskExecutor/BuiltinExecutor.d.ts.map +0 -1
- package/services/taskExecutor/BuiltinExecutor.js +0 -513
- package/services/taskExecutor/BuiltinExecutor.js.map +0 -1
- package/services/taskExecutor/__tests__/a2a-tasks.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/a2a-tasks.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/a2a-tasks.test.js +0 -328
- package/services/taskExecutor/__tests__/a2a-tasks.test.js.map +0 -1
- package/services/taskExecutor/__tests__/e2e-workflows.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/e2e-workflows.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/e2e-workflows.test.js +0 -446
- package/services/taskExecutor/__tests__/e2e-workflows.test.js.map +0 -1
- package/services/taskExecutor/__tests__/error-handling.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/error-handling.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/error-handling.test.js +0 -387
- package/services/taskExecutor/__tests__/error-handling.test.js.map +0 -1
- package/services/taskExecutor/__tests__/stress.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/stress.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/stress.test.js +0 -329
- package/services/taskExecutor/__tests__/stress.test.js.map +0 -1
- package/services/taskExecutor/__tests__/taskExecutor.integration.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/taskExecutor.integration.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/taskExecutor.integration.test.js +0 -205
- package/services/taskExecutor/__tests__/taskExecutor.integration.test.js.map +0 -1
- package/services/taskExecutor/__tests__/timeout-cancellation.test.d.ts +0 -7
- package/services/taskExecutor/__tests__/timeout-cancellation.test.d.ts.map +0 -1
- package/services/taskExecutor/__tests__/timeout-cancellation.test.js +0 -319
- package/services/taskExecutor/__tests__/timeout-cancellation.test.js.map +0 -1
- package/services/taskExecutor/index.d.ts +0 -40
- package/services/taskExecutor/index.d.ts.map +0 -1
- package/services/taskExecutor/index.js +0 -166
- package/services/taskExecutor/index.js.map +0 -1
- package/services/taskExecutor/taskWorker.d.ts +0 -11
- package/services/taskExecutor/taskWorker.d.ts.map +0 -1
- package/services/taskExecutor/taskWorker.js +0 -170
- package/services/taskExecutor/taskWorker.js.map +0 -1
- package/services/taskExecutor/types.d.ts +0 -145
- package/services/taskExecutor/types.d.ts.map +0 -1
- package/services/taskExecutor/types.js +0 -9
- package/services/taskExecutor/types.js.map +0 -1
- package/services/telemetry.d.ts +0 -40
- package/services/telemetry.d.ts.map +0 -1
- package/services/telemetry.js +0 -245
- package/services/telemetry.js.map +0 -1
- package/services/tunnelService.d.ts +0 -150
- package/services/tunnelService.d.ts.map +0 -1
- package/services/tunnelService.js +0 -412
- package/services/tunnelService.js.map +0 -1
- package/types/a2a.d.ts +0 -293
- package/types/a2a.d.ts.map +0 -1
- package/types/a2a.js +0 -23
- package/types/a2a.js.map +0 -1
- package/types/agents.d.ts +0 -94
- package/types/agents.d.ts.map +0 -1
- package/types/agents.js +0 -45
- package/types/agents.js.map +0 -1
- package/types/claude-history.d.ts +0 -62
- package/types/claude-history.d.ts.map +0 -1
- package/types/claude-history.js +0 -4
- package/types/claude-history.js.map +0 -1
- package/types/claude-versions.d.ts +0 -36
- package/types/claude-versions.d.ts.map +0 -1
- package/types/claude-versions.js +0 -3
- package/types/claude-versions.js.map +0 -1
- package/types/commands.d.ts +0 -50
- package/types/commands.d.ts.map +0 -1
- package/types/commands.js +0 -23
- package/types/commands.js.map +0 -1
- package/types/plugins.d.ts +0 -144
- package/types/plugins.d.ts.map +0 -1
- package/types/plugins.js +0 -8
- package/types/plugins.js.map +0 -1
- package/types/projects.d.ts +0 -44
- package/types/projects.d.ts.map +0 -1
- package/types/projects.js +0 -4
- package/types/projects.js.map +0 -1
- package/types/scheduledTasks.d.ts +0 -168
- package/types/scheduledTasks.d.ts.map +0 -1
- package/types/scheduledTasks.js +0 -17
- package/types/scheduledTasks.js.map +0 -1
- package/types/skills.d.ts +0 -91
- package/types/skills.d.ts.map +0 -1
- package/types/skills.js +0 -6
- package/types/skills.js.map +0 -1
- package/types/slack.d.ts +0 -97
- package/types/slack.d.ts.map +0 -1
- package/types/slack.js +0 -8
- package/types/slack.js.map +0 -1
- package/types/streaming.d.ts +0 -12
- package/types/streaming.d.ts.map +0 -1
- package/types/streaming.js +0 -8
- package/types/streaming.js.map +0 -1
- package/types/subagents.d.ts +0 -26
- package/types/subagents.d.ts.map +0 -1
- package/types/subagents.js +0 -3
- package/types/subagents.js.map +0 -1
- package/utils/__tests__/claudeUtils.test.d.ts +0 -5
- package/utils/__tests__/claudeUtils.test.d.ts.map +0 -1
- package/utils/__tests__/claudeUtils.test.js +0 -283
- package/utils/__tests__/claudeUtils.test.js.map +0 -1
- package/utils/__tests__/configResolver.test.d.ts +0 -7
- package/utils/__tests__/configResolver.test.d.ts.map +0 -1
- package/utils/__tests__/configResolver.test.js +0 -211
- package/utils/__tests__/configResolver.test.js.map +0 -1
- package/utils/__tests__/sessionUtils.test.d.ts +0 -5
- package/utils/__tests__/sessionUtils.test.d.ts.map +0 -1
- package/utils/__tests__/sessionUtils.test.js +0 -296
- package/utils/__tests__/sessionUtils.test.js.map +0 -1
- package/utils/agentCardCache.d.ts +0 -93
- package/utils/agentCardCache.d.ts.map +0 -1
- package/utils/agentCardCache.js +0 -212
- package/utils/agentCardCache.js.map +0 -1
- package/utils/claudeUtils.d.ts +0 -55
- package/utils/claudeUtils.d.ts.map +0 -1
- package/utils/claudeUtils.js +0 -354
- package/utils/claudeUtils.js.map +0 -1
- package/utils/configResolver.d.ts +0 -57
- package/utils/configResolver.d.ts.map +0 -1
- package/utils/configResolver.js +0 -130
- package/utils/configResolver.js.map +0 -1
- package/utils/fileUtils.d.ts +0 -2
- package/utils/fileUtils.d.ts.map +0 -1
- package/utils/fileUtils.js +0 -11
- package/utils/fileUtils.js.map +0 -1
- package/utils/jwt.d.ts +0 -30
- package/utils/jwt.d.ts.map +0 -1
- package/utils/jwt.js +0 -95
- package/utils/jwt.js.map +0 -1
- package/utils/sessionUtils.d.ts +0 -67
- package/utils/sessionUtils.d.ts.map +0 -1
- package/utils/sessionUtils.js +0 -296
- package/utils/sessionUtils.js.map +0 -1
- /package/{public → frontend/public}/cc-studio.png +0 -0
- /package/{public → frontend/public}/screenshot-chat.png +0 -0
- /package/{public → frontend/public}/screenshot-mcp.png +0 -0
- /package/{public → frontend/public}/vite.svg +0 -0
- /package/{public → frontend/public}/wechat-qr-code.png +0 -0
|
@@ -0,0 +1,1973 @@
|
|
|
1
|
+
# LAVS Implementation Guide
|
|
2
|
+
|
|
3
|
+
**Reference SDK Design and Requirements**
|
|
4
|
+
|
|
5
|
+
## Document Overview
|
|
6
|
+
|
|
7
|
+
This document provides detailed requirements and design specifications for implementing LAVS (Local Agent View Service) reference SDKs. It covers both backend runtime implementations (Python and TypeScript) and frontend client SDK (TypeScript/JavaScript).
|
|
8
|
+
|
|
9
|
+
**Target Audience:** Developers implementing LAVS SDK
|
|
10
|
+
**Version:** 1.0.0-draft
|
|
11
|
+
**Last Updated:** 2025-01-15
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
1. [System Architecture](#1-system-architecture)
|
|
18
|
+
2. [Backend Runtime Requirements](#2-backend-runtime-requirements)
|
|
19
|
+
3. [Frontend Client Requirements](#4-frontend-client-requirements)
|
|
20
|
+
4. [Testing Requirements](#5-testing-requirements)
|
|
21
|
+
5. [Documentation Requirements](#6-documentation-requirements)
|
|
22
|
+
6. [Deployment and Distribution](#7-deployment-and-distribution)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1. System Architecture
|
|
27
|
+
|
|
28
|
+
### 1.1 Component Overview
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
32
|
+
│ LAVS Ecosystem │
|
|
33
|
+
├─────────────────────────────────────────────────────────────┤
|
|
34
|
+
│ │
|
|
35
|
+
│ Frontend (Browser/Desktop App) │
|
|
36
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
37
|
+
│ │ View Component (Web Component) │ │
|
|
38
|
+
│ │ ┌──────────────────────────────────────────────┐ │ │
|
|
39
|
+
│ │ │ @lavs/client (TypeScript SDK) │ │ │
|
|
40
|
+
│ │ │ • call(endpoint, input) │ │ │
|
|
41
|
+
│ │ │ • subscribe(endpoint, callback) │ │ │
|
|
42
|
+
│ │ │ • getManifest() │ │ │
|
|
43
|
+
│ │ └──────────────────────────────────────────────┘ │ │
|
|
44
|
+
│ └─────────────────────┬──────────────────────────────┘ │
|
|
45
|
+
│ │ JSON-RPC 2.0 │
|
|
46
|
+
│ │ (HTTP/WebSocket) │
|
|
47
|
+
│ ▼ │
|
|
48
|
+
│ Backend (Node.js/Python) │
|
|
49
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
50
|
+
│ │ @lavs/runtime (TypeScript) / lavs-py (Python) │ │
|
|
51
|
+
│ │ ┌──────────────────────────────────────────────┐ │ │
|
|
52
|
+
│ │ │ Core Modules: │ │ │
|
|
53
|
+
│ │ │ • Manifest Loader & Validator │ │ │
|
|
54
|
+
│ │ │ • Endpoint Router │ │ │
|
|
55
|
+
│ │ │ • Handler Executor │ │ │
|
|
56
|
+
│ │ │ • Permission Enforcer │ │ │
|
|
57
|
+
│ │ │ • Schema Validator │ │ │
|
|
58
|
+
│ │ │ • HTTP/WebSocket Server │ │ │
|
|
59
|
+
│ │ └──────────────────────────────────────────────┘ │ │
|
|
60
|
+
│ │ │ │ │
|
|
61
|
+
│ │ ▼ │ │
|
|
62
|
+
│ │ ┌──────────────────────────────────────────────┐ │ │
|
|
63
|
+
│ │ │ Handler Implementations: │ │ │
|
|
64
|
+
│ │ │ • Script Handler (exec child process) │ │ │
|
|
65
|
+
│ │ │ • Function Handler (direct call) │ │ │
|
|
66
|
+
│ │ │ • HTTP Handler (proxy to URL) │ │ │
|
|
67
|
+
│ │ │ • MCP Handler (bridge to MCP server) │ │ │
|
|
68
|
+
│ │ └──────────────────────────────────────────────┘ │ │
|
|
69
|
+
│ └────────────────────────────────────────────────────┘ │
|
|
70
|
+
│ │
|
|
71
|
+
└──────────────────────────────────────────────────────────────┘
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 1.2 Data Flow
|
|
75
|
+
|
|
76
|
+
**Query/Mutation Flow:**
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
1. View Component
|
|
80
|
+
└─► client.call('addTodo', { text: 'Buy milk' })
|
|
81
|
+
│
|
|
82
|
+
2. LAVS Client SDK
|
|
83
|
+
└─► Send JSON-RPC request via HTTP POST
|
|
84
|
+
│
|
|
85
|
+
▼
|
|
86
|
+
{
|
|
87
|
+
"jsonrpc": "2.0",
|
|
88
|
+
"id": 1,
|
|
89
|
+
"method": "lavs/call",
|
|
90
|
+
"params": {
|
|
91
|
+
"endpoint": "addTodo",
|
|
92
|
+
"input": { "text": "Buy milk" }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
│
|
|
96
|
+
3. LAVS Runtime
|
|
97
|
+
├─► Parse & validate request
|
|
98
|
+
├─► Load endpoint from manifest
|
|
99
|
+
├─► Check permissions (fileAccess, networkAccess)
|
|
100
|
+
├─► Validate input against schema
|
|
101
|
+
├─► Execute handler (script/function/http/mcp)
|
|
102
|
+
│ │
|
|
103
|
+
│ └─► Script Handler:
|
|
104
|
+
│ • Spawn child process
|
|
105
|
+
│ • Pass input via stdin/args/env
|
|
106
|
+
│ • Capture stdout/stderr
|
|
107
|
+
│ • Parse output as JSON
|
|
108
|
+
│
|
|
109
|
+
├─► Validate output against schema
|
|
110
|
+
└─► Send JSON-RPC response
|
|
111
|
+
│
|
|
112
|
+
▼
|
|
113
|
+
{
|
|
114
|
+
"jsonrpc": "2.0",
|
|
115
|
+
"id": 1,
|
|
116
|
+
"result": { "id": 123, "text": "Buy milk", ... }
|
|
117
|
+
}
|
|
118
|
+
│
|
|
119
|
+
4. LAVS Client SDK
|
|
120
|
+
└─► Resolve promise with result
|
|
121
|
+
│
|
|
122
|
+
5. View Component
|
|
123
|
+
└─► Update UI with new todo
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Subscription Flow:**
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
1. View Component
|
|
130
|
+
└─► client.subscribe('todoUpdates', callback)
|
|
131
|
+
│
|
|
132
|
+
2. LAVS Client SDK
|
|
133
|
+
└─► Open WebSocket connection
|
|
134
|
+
└─► Send subscribe request
|
|
135
|
+
│
|
|
136
|
+
3. LAVS Runtime
|
|
137
|
+
├─► Create subscription
|
|
138
|
+
├─► Start handler (long-running process/function)
|
|
139
|
+
└─► Listen for handler output
|
|
140
|
+
│
|
|
141
|
+
[Handler emits data]
|
|
142
|
+
│
|
|
143
|
+
└─► Send data push to client
|
|
144
|
+
│
|
|
145
|
+
4. LAVS Client SDK
|
|
146
|
+
└─► Invoke callback with data
|
|
147
|
+
│
|
|
148
|
+
5. View Component
|
|
149
|
+
└─► Update UI reactively
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 1.3 File Structure
|
|
153
|
+
|
|
154
|
+
**Backend Runtime (TypeScript):**
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
@lavs/runtime/
|
|
158
|
+
├── src/
|
|
159
|
+
│ ├── index.ts # Main entry point
|
|
160
|
+
│ ├── runtime.ts # LAVSRuntime class
|
|
161
|
+
│ ├── server/
|
|
162
|
+
│ │ ├── http-server.ts # HTTP server implementation
|
|
163
|
+
│ │ └── websocket-server.ts # WebSocket server implementation
|
|
164
|
+
│ ├── manifest/
|
|
165
|
+
│ │ ├── loader.ts # Load & parse lavs.json
|
|
166
|
+
│ │ ├── validator.ts # Validate manifest schema
|
|
167
|
+
│ │ └── types.ts # TypeScript types for manifest
|
|
168
|
+
│ ├── executor/
|
|
169
|
+
│ │ ├── executor.ts # Base executor interface
|
|
170
|
+
│ │ ├── script-executor.ts # Execute script handlers
|
|
171
|
+
│ │ ├── function-executor.ts # Execute function handlers
|
|
172
|
+
│ │ ├── http-executor.ts # Execute HTTP handlers
|
|
173
|
+
│ │ └── mcp-executor.ts # Execute MCP handlers
|
|
174
|
+
│ ├── security/
|
|
175
|
+
│ │ ├── permission-checker.ts # Enforce permissions
|
|
176
|
+
│ │ ├── sandbox.ts # Sandboxing utilities
|
|
177
|
+
│ │ └── input-validator.ts # Validate inputs against schema
|
|
178
|
+
│ ├── subscription/
|
|
179
|
+
│ │ └── subscription-manager.ts # Manage subscriptions
|
|
180
|
+
│ └── utils/
|
|
181
|
+
│ ├── logger.ts # Logging
|
|
182
|
+
│ └── errors.ts # Error types
|
|
183
|
+
├── tests/
|
|
184
|
+
│ ├── unit/
|
|
185
|
+
│ └── integration/
|
|
186
|
+
├── package.json
|
|
187
|
+
└── tsconfig.json
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Backend Runtime (Python):**
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
lavs-py/
|
|
194
|
+
├── lavs/
|
|
195
|
+
│ ├── __init__.py
|
|
196
|
+
│ ├── runtime.py # LAVSRuntime class
|
|
197
|
+
│ ├── server/
|
|
198
|
+
│ │ ├── __init__.py
|
|
199
|
+
│ │ ├── http_server.py # HTTP server (aiohttp)
|
|
200
|
+
│ │ └── websocket_server.py # WebSocket server
|
|
201
|
+
│ ├── manifest/
|
|
202
|
+
│ │ ├── __init__.py
|
|
203
|
+
│ │ ├── loader.py # Load & parse lavs.json
|
|
204
|
+
│ │ ├── validator.py # Validate manifest
|
|
205
|
+
│ │ └── types.py # Pydantic models
|
|
206
|
+
│ ├── executor/
|
|
207
|
+
│ │ ├── __init__.py
|
|
208
|
+
│ │ ├── base.py # Base executor
|
|
209
|
+
│ │ ├── script.py # Script executor
|
|
210
|
+
│ │ ├── function.py # Function executor
|
|
211
|
+
│ │ ├── http.py # HTTP executor
|
|
212
|
+
│ │ └── mcp.py # MCP executor
|
|
213
|
+
│ ├── security/
|
|
214
|
+
│ │ ├── __init__.py
|
|
215
|
+
│ │ ├── permissions.py # Permission enforcer
|
|
216
|
+
│ │ └── validator.py # Schema validator (jsonschema)
|
|
217
|
+
│ ├── subscription/
|
|
218
|
+
│ │ └── manager.py # Subscription manager
|
|
219
|
+
│ └── utils/
|
|
220
|
+
│ ├── logger.py
|
|
221
|
+
│ └── errors.py
|
|
222
|
+
├── tests/
|
|
223
|
+
│ ├── unit/
|
|
224
|
+
│ └── integration/
|
|
225
|
+
├── pyproject.toml
|
|
226
|
+
└── README.md
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Frontend Client (TypeScript):**
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
@lavs/client/
|
|
233
|
+
├── src/
|
|
234
|
+
│ ├── index.ts # Main entry point
|
|
235
|
+
│ ├── client.ts # LAVSClient class
|
|
236
|
+
│ ├── transport/
|
|
237
|
+
│ │ ├── http-transport.ts # HTTP transport
|
|
238
|
+
│ │ └── websocket-transport.ts # WebSocket transport
|
|
239
|
+
│ ├── types.ts # TypeScript types
|
|
240
|
+
│ └── utils/
|
|
241
|
+
│ └── errors.ts # Error handling
|
|
242
|
+
├── tests/
|
|
243
|
+
├── package.json
|
|
244
|
+
└── tsconfig.json
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 2. Backend Runtime Requirements
|
|
250
|
+
|
|
251
|
+
### 2.1 Core Classes and Interfaces
|
|
252
|
+
|
|
253
|
+
#### 2.1.1 LAVSRuntime Class
|
|
254
|
+
|
|
255
|
+
**TypeScript:**
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// src/runtime.ts
|
|
259
|
+
|
|
260
|
+
interface LAVSRuntimeOptions {
|
|
261
|
+
manifestPath?: string; // Path to lavs.json (default: ./lavs.json)
|
|
262
|
+
workdir?: string; // Working directory for handlers
|
|
263
|
+
port?: number; // HTTP server port (default: 5555)
|
|
264
|
+
host?: string; // Server host (default: localhost)
|
|
265
|
+
enableWebSocket?: boolean; // Enable WebSocket for subscriptions
|
|
266
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error';
|
|
267
|
+
|
|
268
|
+
// Security
|
|
269
|
+
enforcePermissions?: boolean; // Enforce manifest permissions (default: true)
|
|
270
|
+
maxConcurrentHandlers?: number; // Max concurrent handler executions
|
|
271
|
+
|
|
272
|
+
// CORS
|
|
273
|
+
cors?: {
|
|
274
|
+
origin: string | string[];
|
|
275
|
+
credentials?: boolean;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export class LAVSRuntime {
|
|
280
|
+
private manifest: LAVSManifest;
|
|
281
|
+
private httpServer: HTTPServer;
|
|
282
|
+
private wsServer?: WebSocketServer;
|
|
283
|
+
private executors: Map<string, Executor>;
|
|
284
|
+
private subscriptionManager: SubscriptionManager;
|
|
285
|
+
|
|
286
|
+
constructor(options?: LAVSRuntimeOptions);
|
|
287
|
+
|
|
288
|
+
// Lifecycle
|
|
289
|
+
async start(): Promise<void>;
|
|
290
|
+
async stop(): Promise<void>;
|
|
291
|
+
|
|
292
|
+
// Endpoint execution
|
|
293
|
+
async call(endpoint: string, input?: any): Promise<any>;
|
|
294
|
+
|
|
295
|
+
// Subscription
|
|
296
|
+
subscribe(
|
|
297
|
+
endpoint: string,
|
|
298
|
+
callback: (data: any) => void
|
|
299
|
+
): () => void; // Returns unsubscribe function
|
|
300
|
+
|
|
301
|
+
// Introspection
|
|
302
|
+
getManifest(): LAVSManifest;
|
|
303
|
+
getEndpoint(id: string): Endpoint | undefined;
|
|
304
|
+
|
|
305
|
+
// Testing helpers
|
|
306
|
+
async executeHandler(
|
|
307
|
+
handler: Handler,
|
|
308
|
+
input?: any
|
|
309
|
+
): Promise<any>;
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Python:**
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
# lavs/runtime.py
|
|
317
|
+
|
|
318
|
+
from typing import Optional, Dict, Callable, Any
|
|
319
|
+
from dataclasses import dataclass
|
|
320
|
+
|
|
321
|
+
@dataclass
|
|
322
|
+
class LAVSRuntimeOptions:
|
|
323
|
+
manifest_path: str = "./lavs.json"
|
|
324
|
+
workdir: str = "."
|
|
325
|
+
port: int = 5555
|
|
326
|
+
host: str = "localhost"
|
|
327
|
+
enable_websocket: bool = True
|
|
328
|
+
log_level: str = "info"
|
|
329
|
+
enforce_permissions: bool = True
|
|
330
|
+
max_concurrent_handlers: int = 10
|
|
331
|
+
cors_origin: str | list[str] = "*"
|
|
332
|
+
|
|
333
|
+
class LAVSRuntime:
|
|
334
|
+
def __init__(self, options: Optional[LAVSRuntimeOptions] = None):
|
|
335
|
+
self.options = options or LAVSRuntimeOptions()
|
|
336
|
+
self.manifest: Optional[LAVSManifest] = None
|
|
337
|
+
self.http_server: Optional[HTTPServer] = None
|
|
338
|
+
self.ws_server: Optional[WebSocketServer] = None
|
|
339
|
+
self.executors: Dict[str, Executor] = {}
|
|
340
|
+
self.subscription_manager = SubscriptionManager()
|
|
341
|
+
|
|
342
|
+
async def start(self) -> None:
|
|
343
|
+
"""Load manifest and start servers"""
|
|
344
|
+
pass
|
|
345
|
+
|
|
346
|
+
async def stop(self) -> None:
|
|
347
|
+
"""Stop servers and cleanup"""
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
async def call(self, endpoint: str, input: Any = None) -> Any:
|
|
351
|
+
"""Execute an endpoint"""
|
|
352
|
+
pass
|
|
353
|
+
|
|
354
|
+
def subscribe(
|
|
355
|
+
self,
|
|
356
|
+
endpoint: str,
|
|
357
|
+
callback: Callable[[Any], None]
|
|
358
|
+
) -> Callable[[], None]:
|
|
359
|
+
"""Subscribe to endpoint, returns unsubscribe function"""
|
|
360
|
+
pass
|
|
361
|
+
|
|
362
|
+
def get_manifest(self) -> LAVSManifest:
|
|
363
|
+
"""Get loaded manifest"""
|
|
364
|
+
pass
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### 2.1.2 Manifest Loader
|
|
368
|
+
|
|
369
|
+
**Requirements:**
|
|
370
|
+
|
|
371
|
+
1. Load `lavs.json` from file system
|
|
372
|
+
2. Parse JSON with error handling
|
|
373
|
+
3. Validate against schema (see LAVS-SPEC.md section 4)
|
|
374
|
+
4. Resolve relative paths (scripts, data files)
|
|
375
|
+
5. Support JSON Schema `$ref` resolution for type definitions
|
|
376
|
+
|
|
377
|
+
**TypeScript:**
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
// src/manifest/loader.ts
|
|
381
|
+
|
|
382
|
+
export class ManifestLoader {
|
|
383
|
+
async load(path: string): Promise<LAVSManifest> {
|
|
384
|
+
// 1. Read file
|
|
385
|
+
const content = await fs.readFile(path, 'utf-8');
|
|
386
|
+
|
|
387
|
+
// 2. Parse JSON
|
|
388
|
+
let parsed: any;
|
|
389
|
+
try {
|
|
390
|
+
parsed = JSON.parse(content);
|
|
391
|
+
} catch (e) {
|
|
392
|
+
throw new ManifestError('Invalid JSON', { cause: e });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// 3. Validate schema
|
|
396
|
+
const validator = new ManifestValidator();
|
|
397
|
+
const errors = validator.validate(parsed);
|
|
398
|
+
if (errors.length > 0) {
|
|
399
|
+
throw new ManifestError('Invalid manifest', { errors });
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 4. Resolve relative paths
|
|
403
|
+
const manifest = this.resolvePaths(parsed, path);
|
|
404
|
+
|
|
405
|
+
return manifest as LAVSManifest;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private resolvePaths(
|
|
409
|
+
manifest: any,
|
|
410
|
+
manifestPath: string
|
|
411
|
+
): any {
|
|
412
|
+
const basedir = dirname(manifestPath);
|
|
413
|
+
|
|
414
|
+
// Resolve script handler paths
|
|
415
|
+
for (const endpoint of manifest.endpoints) {
|
|
416
|
+
if (endpoint.handler.type === 'script') {
|
|
417
|
+
// Convert relative paths to absolute
|
|
418
|
+
if (!isAbsolute(endpoint.handler.command)) {
|
|
419
|
+
endpoint.handler.command = resolve(
|
|
420
|
+
basedir,
|
|
421
|
+
endpoint.handler.command
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Resolve handler.cwd if specified
|
|
426
|
+
if (endpoint.handler.cwd) {
|
|
427
|
+
endpoint.handler.cwd = resolve(
|
|
428
|
+
basedir,
|
|
429
|
+
endpoint.handler.cwd
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (endpoint.handler.type === 'function') {
|
|
435
|
+
endpoint.handler.module = resolve(
|
|
436
|
+
basedir,
|
|
437
|
+
endpoint.handler.module
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Resolve view component paths
|
|
443
|
+
if (manifest.view?.component?.type === 'local') {
|
|
444
|
+
manifest.view.component.path = resolve(
|
|
445
|
+
basedir,
|
|
446
|
+
manifest.view.component.path
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return manifest;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**Python:**
|
|
456
|
+
|
|
457
|
+
```python
|
|
458
|
+
# lavs/manifest/loader.py
|
|
459
|
+
|
|
460
|
+
import json
|
|
461
|
+
from pathlib import Path
|
|
462
|
+
from typing import Any
|
|
463
|
+
from .validator import ManifestValidator
|
|
464
|
+
from .types import LAVSManifest
|
|
465
|
+
|
|
466
|
+
class ManifestLoader:
|
|
467
|
+
def load(self, path: str) -> LAVSManifest:
|
|
468
|
+
"""Load and validate manifest from file"""
|
|
469
|
+
|
|
470
|
+
# 1. Read file
|
|
471
|
+
manifest_path = Path(path)
|
|
472
|
+
content = manifest_path.read_text()
|
|
473
|
+
|
|
474
|
+
# 2. Parse JSON
|
|
475
|
+
try:
|
|
476
|
+
parsed = json.loads(content)
|
|
477
|
+
except json.JSONDecodeError as e:
|
|
478
|
+
raise ManifestError(f"Invalid JSON: {e}")
|
|
479
|
+
|
|
480
|
+
# 3. Validate schema
|
|
481
|
+
validator = ManifestValidator()
|
|
482
|
+
errors = validator.validate(parsed)
|
|
483
|
+
if errors:
|
|
484
|
+
raise ManifestError(f"Invalid manifest: {errors}")
|
|
485
|
+
|
|
486
|
+
# 4. Resolve relative paths
|
|
487
|
+
resolved = self._resolve_paths(parsed, manifest_path)
|
|
488
|
+
|
|
489
|
+
# 5. Convert to Pydantic model
|
|
490
|
+
return LAVSManifest(**resolved)
|
|
491
|
+
|
|
492
|
+
def _resolve_paths(
|
|
493
|
+
self,
|
|
494
|
+
manifest: dict,
|
|
495
|
+
manifest_path: Path
|
|
496
|
+
) -> dict:
|
|
497
|
+
basedir = manifest_path.parent
|
|
498
|
+
|
|
499
|
+
# Resolve script handlers
|
|
500
|
+
for endpoint in manifest.get('endpoints', []):
|
|
501
|
+
handler = endpoint.get('handler', {})
|
|
502
|
+
|
|
503
|
+
if handler.get('type') == 'script':
|
|
504
|
+
# Resolve command path
|
|
505
|
+
cmd = handler['command']
|
|
506
|
+
if not Path(cmd).is_absolute():
|
|
507
|
+
handler['command'] = str(basedir / cmd)
|
|
508
|
+
|
|
509
|
+
# Resolve cwd
|
|
510
|
+
if 'cwd' in handler:
|
|
511
|
+
handler['cwd'] = str(basedir / handler['cwd'])
|
|
512
|
+
|
|
513
|
+
elif handler.get('type') == 'function':
|
|
514
|
+
handler['module'] = str(basedir / handler['module'])
|
|
515
|
+
|
|
516
|
+
# Resolve view component
|
|
517
|
+
if 'view' in manifest:
|
|
518
|
+
component = manifest['view'].get('component', {})
|
|
519
|
+
if component.get('type') == 'local':
|
|
520
|
+
component['path'] = str(basedir / component['path'])
|
|
521
|
+
|
|
522
|
+
return manifest
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
#### 2.1.3 Executor Interface
|
|
526
|
+
|
|
527
|
+
**Base interface for all handler executors:**
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// src/executor/executor.ts
|
|
531
|
+
|
|
532
|
+
export interface Executor {
|
|
533
|
+
// Execute handler with input, return output
|
|
534
|
+
execute(
|
|
535
|
+
handler: Handler,
|
|
536
|
+
input: any,
|
|
537
|
+
context: ExecutionContext
|
|
538
|
+
): Promise<any>;
|
|
539
|
+
|
|
540
|
+
// Check if this executor can handle the given handler
|
|
541
|
+
canHandle(handler: Handler): boolean;
|
|
542
|
+
|
|
543
|
+
// Cleanup resources
|
|
544
|
+
dispose(): Promise<void>;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
export interface ExecutionContext {
|
|
548
|
+
endpointId: string;
|
|
549
|
+
workdir: string;
|
|
550
|
+
permissions: Permissions;
|
|
551
|
+
timeout?: number;
|
|
552
|
+
env?: Record<string, string>;
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
#### 2.1.4 Script Executor
|
|
557
|
+
|
|
558
|
+
**Most complex executor - handles script execution with security.**
|
|
559
|
+
|
|
560
|
+
**Requirements:**
|
|
561
|
+
|
|
562
|
+
1. Spawn child process with handler.command
|
|
563
|
+
2. Pass input via stdin/args/env based on handler.input
|
|
564
|
+
3. Enforce timeout (kill process if exceeded)
|
|
565
|
+
4. Capture stdout (as result) and stderr (as logs)
|
|
566
|
+
5. Validate output is valid JSON
|
|
567
|
+
6. Enforce file access permissions (prevent access to unauthorized paths)
|
|
568
|
+
7. Handle process errors gracefully
|
|
569
|
+
|
|
570
|
+
**TypeScript:**
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
// src/executor/script-executor.ts
|
|
574
|
+
|
|
575
|
+
import { spawn, ChildProcess } from 'child_process';
|
|
576
|
+
|
|
577
|
+
export class ScriptExecutor implements Executor {
|
|
578
|
+
canHandle(handler: Handler): boolean {
|
|
579
|
+
return handler.type === 'script';
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async execute(
|
|
583
|
+
handler: ScriptHandler,
|
|
584
|
+
input: any,
|
|
585
|
+
context: ExecutionContext
|
|
586
|
+
): Promise<any> {
|
|
587
|
+
// 1. Prepare command and args
|
|
588
|
+
const { command, args = [], env = {} } = handler;
|
|
589
|
+
const resolvedArgs = this.resolveArgs(args, input);
|
|
590
|
+
|
|
591
|
+
// 2. Prepare environment
|
|
592
|
+
const processEnv = {
|
|
593
|
+
...process.env,
|
|
594
|
+
...env,
|
|
595
|
+
...(handler.input === 'env' ? this.inputToEnv(input) : {})
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
// 3. Spawn process
|
|
599
|
+
const proc = spawn(command, resolvedArgs, {
|
|
600
|
+
cwd: handler.cwd || context.workdir,
|
|
601
|
+
env: processEnv,
|
|
602
|
+
timeout: context.timeout || handler.timeout || 30000
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
// 4. Send input to stdin if needed
|
|
606
|
+
if (handler.input === 'stdin' && input) {
|
|
607
|
+
proc.stdin.write(JSON.stringify(input));
|
|
608
|
+
proc.stdin.end();
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// 5. Capture output
|
|
612
|
+
let stdout = '';
|
|
613
|
+
let stderr = '';
|
|
614
|
+
|
|
615
|
+
proc.stdout.on('data', (data) => {
|
|
616
|
+
stdout += data.toString();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
proc.stderr.on('data', (data) => {
|
|
620
|
+
stderr += data.toString();
|
|
621
|
+
logger.debug(`[${context.endpointId}] stderr: ${data}`);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
// 6. Wait for completion
|
|
625
|
+
const exitCode = await new Promise<number>((resolve, reject) => {
|
|
626
|
+
proc.on('exit', (code) => resolve(code || 0));
|
|
627
|
+
proc.on('error', reject);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// 7. Handle errors
|
|
631
|
+
if (exitCode !== 0) {
|
|
632
|
+
throw new HandlerError(
|
|
633
|
+
`Script exited with code ${exitCode}`,
|
|
634
|
+
{ stderr, stdout }
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// 8. Parse output
|
|
639
|
+
try {
|
|
640
|
+
return JSON.parse(stdout.trim());
|
|
641
|
+
} catch (e) {
|
|
642
|
+
throw new HandlerError(
|
|
643
|
+
'Invalid JSON output from script',
|
|
644
|
+
{ stdout, stderr }
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
private resolveArgs(args: string[], input: any): string[] {
|
|
650
|
+
// Replace {{placeholders}} in args with input values
|
|
651
|
+
return args.map(arg => {
|
|
652
|
+
return arg.replace(/\{\{([^}]+)\}\}/g, (_, path) => {
|
|
653
|
+
return this.getValueByPath(input, path);
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private getValueByPath(obj: any, path: string): string {
|
|
659
|
+
const value = path.split('.').reduce((o, k) => o?.[k], obj);
|
|
660
|
+
return value != null ? String(value) : '';
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
private inputToEnv(input: any): Record<string, string> {
|
|
664
|
+
// Flatten input object to ENV vars
|
|
665
|
+
const env: Record<string, string> = {};
|
|
666
|
+
for (const [key, value] of Object.entries(input)) {
|
|
667
|
+
env[key.toUpperCase()] = String(value);
|
|
668
|
+
}
|
|
669
|
+
return env;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
async dispose(): Promise<void> {
|
|
673
|
+
// Cleanup any running processes
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**Python:**
|
|
679
|
+
|
|
680
|
+
```python
|
|
681
|
+
# lavs/executor/script.py
|
|
682
|
+
|
|
683
|
+
import subprocess
|
|
684
|
+
import json
|
|
685
|
+
from typing import Any, Dict
|
|
686
|
+
from .base import Executor, ExecutionContext
|
|
687
|
+
|
|
688
|
+
class ScriptExecutor(Executor):
|
|
689
|
+
def can_handle(self, handler: dict) -> bool:
|
|
690
|
+
return handler.get('type') == 'script'
|
|
691
|
+
|
|
692
|
+
async def execute(
|
|
693
|
+
self,
|
|
694
|
+
handler: dict,
|
|
695
|
+
input: Any,
|
|
696
|
+
context: ExecutionContext
|
|
697
|
+
) -> Any:
|
|
698
|
+
command = handler['command']
|
|
699
|
+
args = handler.get('args', [])
|
|
700
|
+
timeout = handler.get('timeout', context.timeout or 30)
|
|
701
|
+
|
|
702
|
+
# Resolve args with input placeholders
|
|
703
|
+
resolved_args = self._resolve_args(args, input)
|
|
704
|
+
|
|
705
|
+
# Prepare environment
|
|
706
|
+
env = dict(os.environ)
|
|
707
|
+
env.update(handler.get('env', {}))
|
|
708
|
+
|
|
709
|
+
if handler.get('input') == 'env':
|
|
710
|
+
env.update(self._input_to_env(input))
|
|
711
|
+
|
|
712
|
+
# Build full command
|
|
713
|
+
full_command = [command] + resolved_args
|
|
714
|
+
|
|
715
|
+
# Prepare stdin
|
|
716
|
+
stdin_data = None
|
|
717
|
+
if handler.get('input') == 'stdin' and input:
|
|
718
|
+
stdin_data = json.dumps(input).encode()
|
|
719
|
+
|
|
720
|
+
# Execute
|
|
721
|
+
try:
|
|
722
|
+
result = subprocess.run(
|
|
723
|
+
full_command,
|
|
724
|
+
input=stdin_data,
|
|
725
|
+
capture_output=True,
|
|
726
|
+
timeout=timeout,
|
|
727
|
+
cwd=handler.get('cwd', context.workdir),
|
|
728
|
+
env=env
|
|
729
|
+
)
|
|
730
|
+
except subprocess.TimeoutExpired:
|
|
731
|
+
raise HandlerError(f"Script timeout after {timeout}s")
|
|
732
|
+
|
|
733
|
+
# Check exit code
|
|
734
|
+
if result.returncode != 0:
|
|
735
|
+
stderr = result.stderr.decode()
|
|
736
|
+
raise HandlerError(
|
|
737
|
+
f"Script exited with code {result.returncode}",
|
|
738
|
+
details={'stderr': stderr}
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
# Parse output
|
|
742
|
+
stdout = result.stdout.decode().strip()
|
|
743
|
+
try:
|
|
744
|
+
return json.loads(stdout)
|
|
745
|
+
except json.JSONDecodeError as e:
|
|
746
|
+
raise HandlerError(
|
|
747
|
+
f"Invalid JSON output: {e}",
|
|
748
|
+
details={'stdout': stdout}
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
def _resolve_args(self, args: list, input: Any) -> list:
|
|
752
|
+
"""Replace {{placeholders}} in args"""
|
|
753
|
+
import re
|
|
754
|
+
|
|
755
|
+
resolved = []
|
|
756
|
+
for arg in args:
|
|
757
|
+
def replace(match):
|
|
758
|
+
path = match.group(1)
|
|
759
|
+
return str(self._get_value_by_path(input, path))
|
|
760
|
+
|
|
761
|
+
resolved.append(
|
|
762
|
+
re.sub(r'\{\{([^}]+)\}\}', replace, arg)
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
return resolved
|
|
766
|
+
|
|
767
|
+
def _get_value_by_path(self, obj: Any, path: str) -> Any:
|
|
768
|
+
"""Get value from nested object by dot path"""
|
|
769
|
+
for key in path.split('.'):
|
|
770
|
+
obj = obj.get(key) if isinstance(obj, dict) else None
|
|
771
|
+
return obj or ''
|
|
772
|
+
|
|
773
|
+
def _input_to_env(self, input: dict) -> dict:
|
|
774
|
+
"""Convert input dict to env vars"""
|
|
775
|
+
return {
|
|
776
|
+
k.upper(): str(v)
|
|
777
|
+
for k, v in input.items()
|
|
778
|
+
}
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
#### 2.1.5 Function Executor
|
|
782
|
+
|
|
783
|
+
**For direct function calls (TypeScript/Python).**
|
|
784
|
+
|
|
785
|
+
**TypeScript:**
|
|
786
|
+
|
|
787
|
+
```typescript
|
|
788
|
+
// src/executor/function-executor.ts
|
|
789
|
+
|
|
790
|
+
export class FunctionExecutor implements Executor {
|
|
791
|
+
private moduleCache = new Map<string, any>();
|
|
792
|
+
|
|
793
|
+
canHandle(handler: Handler): boolean {
|
|
794
|
+
return handler.type === 'function';
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
async execute(
|
|
798
|
+
handler: FunctionHandler,
|
|
799
|
+
input: any,
|
|
800
|
+
context: ExecutionContext
|
|
801
|
+
): Promise<any> {
|
|
802
|
+
// 1. Load module (with caching)
|
|
803
|
+
let module = this.moduleCache.get(handler.module);
|
|
804
|
+
if (!module) {
|
|
805
|
+
module = await import(handler.module);
|
|
806
|
+
this.moduleCache.set(handler.module, module);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// 2. Get function
|
|
810
|
+
const fn = module[handler.function];
|
|
811
|
+
if (typeof fn !== 'function') {
|
|
812
|
+
throw new HandlerError(
|
|
813
|
+
`Function ${handler.function} not found in module`
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// 3. Call function with timeout
|
|
818
|
+
const timeout = context.timeout || 30000;
|
|
819
|
+
const result = await Promise.race([
|
|
820
|
+
fn(input, context),
|
|
821
|
+
new Promise((_, reject) =>
|
|
822
|
+
setTimeout(
|
|
823
|
+
() => reject(new Error('Function timeout')),
|
|
824
|
+
timeout
|
|
825
|
+
)
|
|
826
|
+
)
|
|
827
|
+
]);
|
|
828
|
+
|
|
829
|
+
return result;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
async dispose(): Promise<void> {
|
|
833
|
+
this.moduleCache.clear();
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
**Python:**
|
|
839
|
+
|
|
840
|
+
```python
|
|
841
|
+
# lavs/executor/function.py
|
|
842
|
+
|
|
843
|
+
import importlib.util
|
|
844
|
+
from typing import Any
|
|
845
|
+
|
|
846
|
+
class FunctionExecutor(Executor):
|
|
847
|
+
def __init__(self):
|
|
848
|
+
self.module_cache = {}
|
|
849
|
+
|
|
850
|
+
def can_handle(self, handler: dict) -> bool:
|
|
851
|
+
return handler.get('type') == 'function'
|
|
852
|
+
|
|
853
|
+
async def execute(
|
|
854
|
+
self,
|
|
855
|
+
handler: dict,
|
|
856
|
+
input: Any,
|
|
857
|
+
context: ExecutionContext
|
|
858
|
+
) -> Any:
|
|
859
|
+
# Load module
|
|
860
|
+
module_path = handler['module']
|
|
861
|
+
if module_path not in self.module_cache:
|
|
862
|
+
spec = importlib.util.spec_from_file_location(
|
|
863
|
+
"handler_module",
|
|
864
|
+
module_path
|
|
865
|
+
)
|
|
866
|
+
module = importlib.util.module_from_spec(spec)
|
|
867
|
+
spec.loader.exec_module(module)
|
|
868
|
+
self.module_cache[module_path] = module
|
|
869
|
+
else:
|
|
870
|
+
module = self.module_cache[module_path]
|
|
871
|
+
|
|
872
|
+
# Get function
|
|
873
|
+
fn_name = handler['function']
|
|
874
|
+
fn = getattr(module, fn_name, None)
|
|
875
|
+
if not callable(fn):
|
|
876
|
+
raise HandlerError(f"Function {fn_name} not found")
|
|
877
|
+
|
|
878
|
+
# Call function
|
|
879
|
+
import asyncio
|
|
880
|
+
timeout = context.timeout or 30
|
|
881
|
+
|
|
882
|
+
try:
|
|
883
|
+
result = await asyncio.wait_for(
|
|
884
|
+
fn(input, context),
|
|
885
|
+
timeout=timeout
|
|
886
|
+
)
|
|
887
|
+
return result
|
|
888
|
+
except asyncio.TimeoutError:
|
|
889
|
+
raise HandlerError(f"Function timeout after {timeout}s")
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
#### 2.1.6 Permission Checker
|
|
893
|
+
|
|
894
|
+
**Enforce file access and network permissions.**
|
|
895
|
+
|
|
896
|
+
**TypeScript:**
|
|
897
|
+
|
|
898
|
+
```typescript
|
|
899
|
+
// src/security/permission-checker.ts
|
|
900
|
+
|
|
901
|
+
export class PermissionChecker {
|
|
902
|
+
constructor(private permissions: Permissions) {}
|
|
903
|
+
|
|
904
|
+
checkFileAccess(path: string): boolean {
|
|
905
|
+
if (!this.permissions.fileAccess) {
|
|
906
|
+
return false; // No file access by default
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const patterns = this.permissions.fileAccess;
|
|
910
|
+
|
|
911
|
+
for (const pattern of patterns) {
|
|
912
|
+
if (pattern.startsWith('!')) {
|
|
913
|
+
// Explicit deny
|
|
914
|
+
if (minimatch(path, pattern.slice(1))) {
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
917
|
+
} else {
|
|
918
|
+
// Allow pattern
|
|
919
|
+
if (minimatch(path, pattern)) {
|
|
920
|
+
return true;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
return false;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
checkNetworkAccess(url: string): boolean {
|
|
929
|
+
const { networkAccess } = this.permissions;
|
|
930
|
+
|
|
931
|
+
if (networkAccess === false) {
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
if (networkAccess === true) {
|
|
936
|
+
return true; // Allow all (not recommended)
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (Array.isArray(networkAccess)) {
|
|
940
|
+
const hostname = new URL(url).hostname;
|
|
941
|
+
return networkAccess.some(domain =>
|
|
942
|
+
hostname === domain || hostname.endsWith(`.${domain}`)
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
#### 2.1.7 HTTP Server
|
|
952
|
+
|
|
953
|
+
**Handle JSON-RPC requests over HTTP.**
|
|
954
|
+
|
|
955
|
+
**TypeScript:**
|
|
956
|
+
|
|
957
|
+
```typescript
|
|
958
|
+
// src/server/http-server.ts
|
|
959
|
+
|
|
960
|
+
import express from 'express';
|
|
961
|
+
import cors from 'cors';
|
|
962
|
+
|
|
963
|
+
export class HTTPServer {
|
|
964
|
+
private app: express.Application;
|
|
965
|
+
private server?: any;
|
|
966
|
+
|
|
967
|
+
constructor(
|
|
968
|
+
private runtime: LAVSRuntime,
|
|
969
|
+
private options: LAVSRuntimeOptions
|
|
970
|
+
) {
|
|
971
|
+
this.app = express();
|
|
972
|
+
this.setupMiddleware();
|
|
973
|
+
this.setupRoutes();
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
private setupMiddleware() {
|
|
977
|
+
this.app.use(express.json());
|
|
978
|
+
this.app.use(cors(this.options.cors));
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
private setupRoutes() {
|
|
982
|
+
// Main endpoint
|
|
983
|
+
this.app.post('/rpc', async (req, res) => {
|
|
984
|
+
try {
|
|
985
|
+
const response = await this.handleRequest(req.body);
|
|
986
|
+
res.json(response);
|
|
987
|
+
} catch (error) {
|
|
988
|
+
res.status(500).json({
|
|
989
|
+
jsonrpc: '2.0',
|
|
990
|
+
id: req.body.id,
|
|
991
|
+
error: {
|
|
992
|
+
code: -32603,
|
|
993
|
+
message: error.message
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
// Manifest endpoint
|
|
1000
|
+
this.app.get('/manifest', (req, res) => {
|
|
1001
|
+
res.json(this.runtime.getManifest());
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
private async handleRequest(request: any) {
|
|
1006
|
+
// Validate JSON-RPC format
|
|
1007
|
+
if (request.jsonrpc !== '2.0') {
|
|
1008
|
+
return this.errorResponse(
|
|
1009
|
+
request.id,
|
|
1010
|
+
-32600,
|
|
1011
|
+
'Invalid request: jsonrpc must be "2.0"'
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
const { method, params } = request;
|
|
1016
|
+
|
|
1017
|
+
if (method === 'lavs/call') {
|
|
1018
|
+
const { endpoint, input } = params;
|
|
1019
|
+
|
|
1020
|
+
try {
|
|
1021
|
+
const result = await this.runtime.call(endpoint, input);
|
|
1022
|
+
return {
|
|
1023
|
+
jsonrpc: '2.0',
|
|
1024
|
+
id: request.id,
|
|
1025
|
+
result
|
|
1026
|
+
};
|
|
1027
|
+
} catch (error) {
|
|
1028
|
+
return this.errorResponse(
|
|
1029
|
+
request.id,
|
|
1030
|
+
error.code || -32603,
|
|
1031
|
+
error.message,
|
|
1032
|
+
error.data
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
return this.errorResponse(
|
|
1038
|
+
request.id,
|
|
1039
|
+
-32601,
|
|
1040
|
+
'Method not found'
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
private errorResponse(
|
|
1045
|
+
id: any,
|
|
1046
|
+
code: number,
|
|
1047
|
+
message: string,
|
|
1048
|
+
data?: any
|
|
1049
|
+
) {
|
|
1050
|
+
return {
|
|
1051
|
+
jsonrpc: '2.0',
|
|
1052
|
+
id,
|
|
1053
|
+
error: { code, message, data }
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
async start(): Promise<void> {
|
|
1058
|
+
const { port, host } = this.options;
|
|
1059
|
+
return new Promise((resolve) => {
|
|
1060
|
+
this.server = this.app.listen(port, host, () => {
|
|
1061
|
+
console.log(`LAVS server listening on ${host}:${port}`);
|
|
1062
|
+
resolve();
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
async stop(): Promise<void> {
|
|
1068
|
+
if (this.server) {
|
|
1069
|
+
this.server.close();
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
**Python:**
|
|
1076
|
+
|
|
1077
|
+
```python
|
|
1078
|
+
# lavs/server/http_server.py
|
|
1079
|
+
|
|
1080
|
+
from aiohttp import web
|
|
1081
|
+
import json
|
|
1082
|
+
|
|
1083
|
+
class HTTPServer:
|
|
1084
|
+
def __init__(self, runtime, options):
|
|
1085
|
+
self.runtime = runtime
|
|
1086
|
+
self.options = options
|
|
1087
|
+
self.app = web.Application()
|
|
1088
|
+
self._setup_routes()
|
|
1089
|
+
|
|
1090
|
+
def _setup_routes(self):
|
|
1091
|
+
self.app.router.add_post('/rpc', self.handle_rpc)
|
|
1092
|
+
self.app.router.add_get('/manifest', self.handle_manifest)
|
|
1093
|
+
|
|
1094
|
+
# CORS middleware
|
|
1095
|
+
self.app.middlewares.append(self.cors_middleware)
|
|
1096
|
+
|
|
1097
|
+
async def handle_rpc(self, request):
|
|
1098
|
+
try:
|
|
1099
|
+
data = await request.json()
|
|
1100
|
+
response = await self._handle_request(data)
|
|
1101
|
+
return web.json_response(response)
|
|
1102
|
+
except Exception as e:
|
|
1103
|
+
return web.json_response({
|
|
1104
|
+
'jsonrpc': '2.0',
|
|
1105
|
+
'id': data.get('id'),
|
|
1106
|
+
'error': {
|
|
1107
|
+
'code': -32603,
|
|
1108
|
+
'message': str(e)
|
|
1109
|
+
}
|
|
1110
|
+
}, status=500)
|
|
1111
|
+
|
|
1112
|
+
async def _handle_request(self, request):
|
|
1113
|
+
if request.get('jsonrpc') != '2.0':
|
|
1114
|
+
return self._error_response(
|
|
1115
|
+
request.get('id'),
|
|
1116
|
+
-32600,
|
|
1117
|
+
'Invalid request'
|
|
1118
|
+
)
|
|
1119
|
+
|
|
1120
|
+
method = request.get('method')
|
|
1121
|
+
params = request.get('params', {})
|
|
1122
|
+
|
|
1123
|
+
if method == 'lavs/call':
|
|
1124
|
+
endpoint = params['endpoint']
|
|
1125
|
+
input_data = params.get('input')
|
|
1126
|
+
|
|
1127
|
+
try:
|
|
1128
|
+
result = await self.runtime.call(endpoint, input_data)
|
|
1129
|
+
return {
|
|
1130
|
+
'jsonrpc': '2.0',
|
|
1131
|
+
'id': request['id'],
|
|
1132
|
+
'result': result
|
|
1133
|
+
}
|
|
1134
|
+
except Exception as e:
|
|
1135
|
+
return self._error_response(
|
|
1136
|
+
request['id'],
|
|
1137
|
+
getattr(e, 'code', -32603),
|
|
1138
|
+
str(e)
|
|
1139
|
+
)
|
|
1140
|
+
|
|
1141
|
+
return self._error_response(
|
|
1142
|
+
request.get('id'),
|
|
1143
|
+
-32601,
|
|
1144
|
+
'Method not found'
|
|
1145
|
+
)
|
|
1146
|
+
|
|
1147
|
+
def _error_response(self, id, code, message, data=None):
|
|
1148
|
+
return {
|
|
1149
|
+
'jsonrpc': '2.0',
|
|
1150
|
+
'id': id,
|
|
1151
|
+
'error': {
|
|
1152
|
+
'code': code,
|
|
1153
|
+
'message': message,
|
|
1154
|
+
**(data and {'data': data} or {})
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
async def handle_manifest(self, request):
|
|
1159
|
+
manifest = self.runtime.get_manifest()
|
|
1160
|
+
return web.json_response(manifest.dict())
|
|
1161
|
+
|
|
1162
|
+
@web.middleware
|
|
1163
|
+
async def cors_middleware(self, request, handler):
|
|
1164
|
+
response = await handler(request)
|
|
1165
|
+
response.headers['Access-Control-Allow-Origin'] = '*'
|
|
1166
|
+
response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
|
|
1167
|
+
response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
|
|
1168
|
+
return response
|
|
1169
|
+
|
|
1170
|
+
async def start(self):
|
|
1171
|
+
runner = web.AppRunner(self.app)
|
|
1172
|
+
await runner.setup()
|
|
1173
|
+
site = web.TCPSite(
|
|
1174
|
+
runner,
|
|
1175
|
+
self.options.host,
|
|
1176
|
+
self.options.port
|
|
1177
|
+
)
|
|
1178
|
+
await site.start()
|
|
1179
|
+
print(f"LAVS server on {self.options.host}:{self.options.port}")
|
|
1180
|
+
|
|
1181
|
+
async def stop(self):
|
|
1182
|
+
await self.app.shutdown()
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
#### 2.1.8 WebSocket Server (for Subscriptions)
|
|
1186
|
+
|
|
1187
|
+
**Requirements:**
|
|
1188
|
+
|
|
1189
|
+
1. Accept WebSocket connections
|
|
1190
|
+
2. Handle `lavs/subscribe` and `lavs/unsubscribe` messages
|
|
1191
|
+
3. Start long-running handler for subscriptions
|
|
1192
|
+
4. Stream handler output to subscribed clients
|
|
1193
|
+
5. Clean up subscriptions on disconnect
|
|
1194
|
+
|
|
1195
|
+
**TypeScript:**
|
|
1196
|
+
|
|
1197
|
+
```typescript
|
|
1198
|
+
// src/server/websocket-server.ts
|
|
1199
|
+
|
|
1200
|
+
import WebSocket from 'ws';
|
|
1201
|
+
|
|
1202
|
+
export class WebSocketServer {
|
|
1203
|
+
private wss?: WebSocket.Server;
|
|
1204
|
+
private subscriptions = new Map<string, Subscription>();
|
|
1205
|
+
|
|
1206
|
+
constructor(
|
|
1207
|
+
private runtime: LAVSRuntime,
|
|
1208
|
+
private httpServer: any
|
|
1209
|
+
) {}
|
|
1210
|
+
|
|
1211
|
+
async start(): Promise<void> {
|
|
1212
|
+
this.wss = new WebSocket.Server({ server: this.httpServer });
|
|
1213
|
+
|
|
1214
|
+
this.wss.on('connection', (ws) => {
|
|
1215
|
+
ws.on('message', async (data) => {
|
|
1216
|
+
try {
|
|
1217
|
+
const request = JSON.parse(data.toString());
|
|
1218
|
+
const response = await this.handleMessage(ws, request);
|
|
1219
|
+
if (response) {
|
|
1220
|
+
ws.send(JSON.stringify(response));
|
|
1221
|
+
}
|
|
1222
|
+
} catch (error) {
|
|
1223
|
+
ws.send(JSON.stringify({
|
|
1224
|
+
jsonrpc: '2.0',
|
|
1225
|
+
error: {
|
|
1226
|
+
code: -32700,
|
|
1227
|
+
message: 'Parse error'
|
|
1228
|
+
}
|
|
1229
|
+
}));
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
ws.on('close', () => {
|
|
1234
|
+
this.cleanupSubscriptions(ws);
|
|
1235
|
+
});
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
private async handleMessage(ws: WebSocket, request: any) {
|
|
1240
|
+
const { method, params, id } = request;
|
|
1241
|
+
|
|
1242
|
+
if (method === 'lavs/subscribe') {
|
|
1243
|
+
const { endpoint } = params;
|
|
1244
|
+
const subscriptionId = this.createSubscription(ws, endpoint);
|
|
1245
|
+
|
|
1246
|
+
return {
|
|
1247
|
+
jsonrpc: '2.0',
|
|
1248
|
+
id,
|
|
1249
|
+
result: { subscriptionId }
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
if (method === 'lavs/unsubscribe') {
|
|
1254
|
+
const { subscriptionId } = params;
|
|
1255
|
+
this.removeSubscription(subscriptionId);
|
|
1256
|
+
|
|
1257
|
+
return {
|
|
1258
|
+
jsonrpc: '2.0',
|
|
1259
|
+
id,
|
|
1260
|
+
result: { success: true }
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return {
|
|
1265
|
+
jsonrpc: '2.0',
|
|
1266
|
+
id,
|
|
1267
|
+
error: {
|
|
1268
|
+
code: -32601,
|
|
1269
|
+
message: 'Method not found'
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
private createSubscription(
|
|
1275
|
+
ws: WebSocket,
|
|
1276
|
+
endpoint: string
|
|
1277
|
+
): string {
|
|
1278
|
+
const subscriptionId = `sub-${Date.now()}-${Math.random()}`;
|
|
1279
|
+
|
|
1280
|
+
// Start subscription handler
|
|
1281
|
+
const unsubscribe = this.runtime.subscribe(endpoint, (data) => {
|
|
1282
|
+
// Send data to client
|
|
1283
|
+
ws.send(JSON.stringify({
|
|
1284
|
+
jsonrpc: '2.0',
|
|
1285
|
+
method: 'lavs/data',
|
|
1286
|
+
params: {
|
|
1287
|
+
subscriptionId,
|
|
1288
|
+
data
|
|
1289
|
+
}
|
|
1290
|
+
}));
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1293
|
+
this.subscriptions.set(subscriptionId, {
|
|
1294
|
+
ws,
|
|
1295
|
+
endpoint,
|
|
1296
|
+
unsubscribe
|
|
1297
|
+
});
|
|
1298
|
+
|
|
1299
|
+
return subscriptionId;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
private removeSubscription(subscriptionId: string) {
|
|
1303
|
+
const sub = this.subscriptions.get(subscriptionId);
|
|
1304
|
+
if (sub) {
|
|
1305
|
+
sub.unsubscribe();
|
|
1306
|
+
this.subscriptions.delete(subscriptionId);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
private cleanupSubscriptions(ws: WebSocket) {
|
|
1311
|
+
for (const [id, sub] of this.subscriptions) {
|
|
1312
|
+
if (sub.ws === ws) {
|
|
1313
|
+
sub.unsubscribe();
|
|
1314
|
+
this.subscriptions.delete(id);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
async stop(): Promise<void> {
|
|
1320
|
+
// Cleanup all subscriptions
|
|
1321
|
+
for (const [id, sub] of this.subscriptions) {
|
|
1322
|
+
sub.unsubscribe();
|
|
1323
|
+
}
|
|
1324
|
+
this.subscriptions.clear();
|
|
1325
|
+
|
|
1326
|
+
// Close server
|
|
1327
|
+
if (this.wss) {
|
|
1328
|
+
this.wss.close();
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
interface Subscription {
|
|
1334
|
+
ws: WebSocket;
|
|
1335
|
+
endpoint: string;
|
|
1336
|
+
unsubscribe: () => void;
|
|
1337
|
+
}
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
### 2.2 Implementation Checklist
|
|
1341
|
+
|
|
1342
|
+
**Phase 1: Core Infrastructure (Week 1-2)**
|
|
1343
|
+
- [ ] Set up project structure (TypeScript + Python)
|
|
1344
|
+
- [ ] Define TypeScript types / Pydantic models for manifest
|
|
1345
|
+
- [ ] Implement ManifestLoader with validation
|
|
1346
|
+
- [ ] Implement basic LAVSRuntime class
|
|
1347
|
+
- [ ] Unit tests for manifest loading
|
|
1348
|
+
|
|
1349
|
+
**Phase 2: Executors (Week 2-3)**
|
|
1350
|
+
- [ ] Implement ScriptExecutor
|
|
1351
|
+
- [ ] Implement FunctionExecutor
|
|
1352
|
+
- [ ] Implement HTTPExecutor
|
|
1353
|
+
- [ ] Unit tests for each executor
|
|
1354
|
+
- [ ] Integration tests with sample scripts
|
|
1355
|
+
|
|
1356
|
+
**Phase 3: Server (Week 3-4)**
|
|
1357
|
+
- [ ] Implement HTTP server with JSON-RPC
|
|
1358
|
+
- [ ] Implement WebSocket server for subscriptions
|
|
1359
|
+
- [ ] Add CORS support
|
|
1360
|
+
- [ ] Integration tests for client-server communication
|
|
1361
|
+
|
|
1362
|
+
**Phase 4: Security (Week 4-5)**
|
|
1363
|
+
- [ ] Implement PermissionChecker
|
|
1364
|
+
- [ ] Add schema validation (JSON Schema)
|
|
1365
|
+
- [ ] Add timeout enforcement
|
|
1366
|
+
- [ ] Security audit and penetration testing
|
|
1367
|
+
|
|
1368
|
+
**Phase 5: Polish (Week 5-6)**
|
|
1369
|
+
- [ ] Error handling and logging
|
|
1370
|
+
- [ ] Performance optimization
|
|
1371
|
+
- [ ] Documentation and examples
|
|
1372
|
+
- [ ] CLI tool for running LAVS services
|
|
1373
|
+
|
|
1374
|
+
---
|
|
1375
|
+
|
|
1376
|
+
## 4. Frontend Client Requirements
|
|
1377
|
+
|
|
1378
|
+
### 4.1 LAVSClient Class
|
|
1379
|
+
|
|
1380
|
+
**TypeScript SDK for frontend applications.**
|
|
1381
|
+
|
|
1382
|
+
```typescript
|
|
1383
|
+
// @lavs/client/src/client.ts
|
|
1384
|
+
|
|
1385
|
+
export interface LAVSClientOptions {
|
|
1386
|
+
endpoint: string; // LAVS server URL
|
|
1387
|
+
transport?: 'http' | 'websocket' | 'auto';
|
|
1388
|
+
timeout?: number; // Request timeout (ms)
|
|
1389
|
+
reconnect?: boolean; // Auto-reconnect WebSocket
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
export class LAVSClient {
|
|
1393
|
+
private httpTransport: HTTPTransport;
|
|
1394
|
+
private wsTransport?: WebSocketTransport;
|
|
1395
|
+
private requestId = 0;
|
|
1396
|
+
|
|
1397
|
+
constructor(options: LAVSClientOptions);
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* Call a query or mutation endpoint
|
|
1401
|
+
*/
|
|
1402
|
+
async call<T = any>(
|
|
1403
|
+
endpoint: string,
|
|
1404
|
+
input?: any
|
|
1405
|
+
): Promise<T> {
|
|
1406
|
+
const request = {
|
|
1407
|
+
jsonrpc: '2.0',
|
|
1408
|
+
id: ++this.requestId,
|
|
1409
|
+
method: 'lavs/call',
|
|
1410
|
+
params: { endpoint, input }
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
const response = await this.httpTransport.send(request);
|
|
1414
|
+
|
|
1415
|
+
if (response.error) {
|
|
1416
|
+
throw new LAVSError(
|
|
1417
|
+
response.error.code,
|
|
1418
|
+
response.error.message,
|
|
1419
|
+
response.error.data
|
|
1420
|
+
);
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
return response.result as T;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Subscribe to a subscription endpoint
|
|
1428
|
+
* Returns unsubscribe function
|
|
1429
|
+
*/
|
|
1430
|
+
subscribe(
|
|
1431
|
+
endpoint: string,
|
|
1432
|
+
callback: (data: any) => void
|
|
1433
|
+
): () => void {
|
|
1434
|
+
if (!this.wsTransport) {
|
|
1435
|
+
this.wsTransport = new WebSocketTransport(this.options);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
return this.wsTransport.subscribe(endpoint, callback);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/**
|
|
1442
|
+
* Get service manifest
|
|
1443
|
+
*/
|
|
1444
|
+
async getManifest(): Promise<LAVSManifest> {
|
|
1445
|
+
const response = await fetch(
|
|
1446
|
+
`${this.options.endpoint}/manifest`
|
|
1447
|
+
);
|
|
1448
|
+
return response.json();
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Read file (if permitted by service)
|
|
1453
|
+
*/
|
|
1454
|
+
async readFile(path: string): Promise<string> {
|
|
1455
|
+
return this.call('__builtin_readFile', { path });
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Close connections
|
|
1460
|
+
*/
|
|
1461
|
+
disconnect(): void {
|
|
1462
|
+
this.wsTransport?.close();
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1467
|
+
### 4.2 HTTP Transport
|
|
1468
|
+
|
|
1469
|
+
```typescript
|
|
1470
|
+
// @lavs/client/src/transport/http-transport.ts
|
|
1471
|
+
|
|
1472
|
+
export class HTTPTransport {
|
|
1473
|
+
constructor(private endpoint: string) {}
|
|
1474
|
+
|
|
1475
|
+
async send(request: any): Promise<any> {
|
|
1476
|
+
const response = await fetch(`${this.endpoint}/rpc`, {
|
|
1477
|
+
method: 'POST',
|
|
1478
|
+
headers: {
|
|
1479
|
+
'Content-Type': 'application/json'
|
|
1480
|
+
},
|
|
1481
|
+
body: JSON.stringify(request)
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
if (!response.ok) {
|
|
1485
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
return response.json();
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
```
|
|
1492
|
+
|
|
1493
|
+
### 4.3 WebSocket Transport
|
|
1494
|
+
|
|
1495
|
+
```typescript
|
|
1496
|
+
// @lavs/client/src/transport/websocket-transport.ts
|
|
1497
|
+
|
|
1498
|
+
export class WebSocketTransport {
|
|
1499
|
+
private ws?: WebSocket;
|
|
1500
|
+
private subscriptions = new Map<string, Subscription>();
|
|
1501
|
+
|
|
1502
|
+
constructor(private options: LAVSClientOptions) {
|
|
1503
|
+
this.connect();
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
private connect() {
|
|
1507
|
+
const wsUrl = this.options.endpoint.replace(/^http/, 'ws');
|
|
1508
|
+
this.ws = new WebSocket(wsUrl);
|
|
1509
|
+
|
|
1510
|
+
this.ws.onmessage = (event) => {
|
|
1511
|
+
const message = JSON.parse(event.data);
|
|
1512
|
+
|
|
1513
|
+
if (message.method === 'lavs/data') {
|
|
1514
|
+
const { subscriptionId, data } = message.params;
|
|
1515
|
+
const sub = this.subscriptions.get(subscriptionId);
|
|
1516
|
+
if (sub) {
|
|
1517
|
+
sub.callback(data);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
this.ws.onerror = (error) => {
|
|
1523
|
+
console.error('WebSocket error:', error);
|
|
1524
|
+
};
|
|
1525
|
+
|
|
1526
|
+
this.ws.onclose = () => {
|
|
1527
|
+
if (this.options.reconnect) {
|
|
1528
|
+
setTimeout(() => this.connect(), 1000);
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
subscribe(
|
|
1534
|
+
endpoint: string,
|
|
1535
|
+
callback: (data: any) => void
|
|
1536
|
+
): () => void {
|
|
1537
|
+
const request = {
|
|
1538
|
+
jsonrpc: '2.0',
|
|
1539
|
+
id: Date.now(),
|
|
1540
|
+
method: 'lavs/subscribe',
|
|
1541
|
+
params: { endpoint }
|
|
1542
|
+
};
|
|
1543
|
+
|
|
1544
|
+
// Send subscribe request
|
|
1545
|
+
this.ws!.send(JSON.stringify(request));
|
|
1546
|
+
|
|
1547
|
+
// Wait for subscription ID in response
|
|
1548
|
+
const listener = (event: MessageEvent) => {
|
|
1549
|
+
const response = JSON.parse(event.data);
|
|
1550
|
+
if (response.id === request.id) {
|
|
1551
|
+
const subscriptionId = response.result.subscriptionId;
|
|
1552
|
+
|
|
1553
|
+
this.subscriptions.set(subscriptionId, {
|
|
1554
|
+
endpoint,
|
|
1555
|
+
callback
|
|
1556
|
+
});
|
|
1557
|
+
|
|
1558
|
+
this.ws!.removeEventListener('message', listener);
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
this.ws!.addEventListener('message', listener);
|
|
1563
|
+
|
|
1564
|
+
// Return unsubscribe function
|
|
1565
|
+
return () => {
|
|
1566
|
+
// Find subscription ID
|
|
1567
|
+
for (const [id, sub] of this.subscriptions) {
|
|
1568
|
+
if (sub.endpoint === endpoint && sub.callback === callback) {
|
|
1569
|
+
this.unsubscribe(id);
|
|
1570
|
+
break;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
private unsubscribe(subscriptionId: string) {
|
|
1577
|
+
this.ws!.send(JSON.stringify({
|
|
1578
|
+
jsonrpc: '2.0',
|
|
1579
|
+
id: Date.now(),
|
|
1580
|
+
method: 'lavs/unsubscribe',
|
|
1581
|
+
params: { subscriptionId }
|
|
1582
|
+
}));
|
|
1583
|
+
|
|
1584
|
+
this.subscriptions.delete(subscriptionId);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
close() {
|
|
1588
|
+
this.ws?.close();
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
interface Subscription {
|
|
1593
|
+
endpoint: string;
|
|
1594
|
+
callback: (data: any) => void;
|
|
1595
|
+
}
|
|
1596
|
+
```
|
|
1597
|
+
|
|
1598
|
+
### 4.4 Usage Example
|
|
1599
|
+
|
|
1600
|
+
```typescript
|
|
1601
|
+
// Example: Todo app frontend
|
|
1602
|
+
|
|
1603
|
+
import { LAVSClient } from '@lavs/client';
|
|
1604
|
+
|
|
1605
|
+
const client = new LAVSClient({
|
|
1606
|
+
endpoint: 'http://localhost:5555'
|
|
1607
|
+
});
|
|
1608
|
+
|
|
1609
|
+
// Call mutation
|
|
1610
|
+
const newTodo = await client.call('addTodo', {
|
|
1611
|
+
text: 'Buy milk',
|
|
1612
|
+
priority: 1
|
|
1613
|
+
});
|
|
1614
|
+
|
|
1615
|
+
// Subscribe to updates
|
|
1616
|
+
const unsubscribe = client.subscribe('todoUpdates', (data) => {
|
|
1617
|
+
console.log('Todo updated:', data);
|
|
1618
|
+
// Update UI
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
// Later: unsubscribe
|
|
1622
|
+
unsubscribe();
|
|
1623
|
+
```
|
|
1624
|
+
|
|
1625
|
+
---
|
|
1626
|
+
|
|
1627
|
+
## 5. Testing Requirements
|
|
1628
|
+
|
|
1629
|
+
### 5.1 Unit Tests
|
|
1630
|
+
|
|
1631
|
+
**Coverage targets: >80%**
|
|
1632
|
+
|
|
1633
|
+
**Backend (TypeScript/Python):**
|
|
1634
|
+
|
|
1635
|
+
- [ ] ManifestLoader
|
|
1636
|
+
- Valid manifest parsing
|
|
1637
|
+
- Invalid JSON handling
|
|
1638
|
+
- Schema validation errors
|
|
1639
|
+
- Path resolution
|
|
1640
|
+
- [ ] ScriptExecutor
|
|
1641
|
+
- Successful execution
|
|
1642
|
+
- Timeout handling
|
|
1643
|
+
- Error handling (non-zero exit)
|
|
1644
|
+
- Input methods (stdin, args, env)
|
|
1645
|
+
- Output parsing
|
|
1646
|
+
- [ ] FunctionExecutor
|
|
1647
|
+
- Module loading
|
|
1648
|
+
- Function calls
|
|
1649
|
+
- Timeout handling
|
|
1650
|
+
- [ ] PermissionChecker
|
|
1651
|
+
- File access patterns
|
|
1652
|
+
- Network access rules
|
|
1653
|
+
- [ ] Schema validation
|
|
1654
|
+
- Valid inputs
|
|
1655
|
+
- Invalid inputs
|
|
1656
|
+
- Type coercion
|
|
1657
|
+
|
|
1658
|
+
**Frontend:**
|
|
1659
|
+
|
|
1660
|
+
- [ ] LAVSClient
|
|
1661
|
+
- HTTP calls
|
|
1662
|
+
- WebSocket subscriptions
|
|
1663
|
+
- Error handling
|
|
1664
|
+
- Reconnection logic
|
|
1665
|
+
|
|
1666
|
+
### 5.2 Integration Tests
|
|
1667
|
+
|
|
1668
|
+
- [ ] End-to-end request flow
|
|
1669
|
+
- HTTP request → Script execution → Response
|
|
1670
|
+
- [ ] Subscription flow
|
|
1671
|
+
- WebSocket connection → Subscribe → Data push → Unsubscribe
|
|
1672
|
+
- [ ] Permission enforcement
|
|
1673
|
+
- Blocked file access
|
|
1674
|
+
- Blocked network access
|
|
1675
|
+
- [ ] Multi-client scenarios
|
|
1676
|
+
- Concurrent requests
|
|
1677
|
+
- Multiple subscriptions
|
|
1678
|
+
|
|
1679
|
+
### 5.3 Example Test Cases
|
|
1680
|
+
|
|
1681
|
+
**TypeScript:**
|
|
1682
|
+
|
|
1683
|
+
```typescript
|
|
1684
|
+
// tests/integration/script-executor.test.ts
|
|
1685
|
+
|
|
1686
|
+
import { LAVSRuntime } from '../src';
|
|
1687
|
+
|
|
1688
|
+
describe('ScriptExecutor', () => {
|
|
1689
|
+
let runtime: LAVSRuntime;
|
|
1690
|
+
|
|
1691
|
+
beforeAll(async () => {
|
|
1692
|
+
runtime = new LAVSRuntime({
|
|
1693
|
+
manifestPath: './tests/fixtures/todo-manifest.json'
|
|
1694
|
+
});
|
|
1695
|
+
await runtime.start();
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1698
|
+
afterAll(async () => {
|
|
1699
|
+
await runtime.stop();
|
|
1700
|
+
});
|
|
1701
|
+
|
|
1702
|
+
it('should execute script and return result', async () => {
|
|
1703
|
+
const result = await runtime.call('listTodos');
|
|
1704
|
+
expect(Array.isArray(result)).toBe(true);
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
it('should pass input via stdin', async () => {
|
|
1708
|
+
const result = await runtime.call('addTodo', {
|
|
1709
|
+
text: 'Test todo',
|
|
1710
|
+
priority: 1
|
|
1711
|
+
});
|
|
1712
|
+
|
|
1713
|
+
expect(result).toMatchObject({
|
|
1714
|
+
text: 'Test todo',
|
|
1715
|
+
priority: 1,
|
|
1716
|
+
done: false
|
|
1717
|
+
});
|
|
1718
|
+
});
|
|
1719
|
+
|
|
1720
|
+
it('should enforce timeout', async () => {
|
|
1721
|
+
await expect(
|
|
1722
|
+
runtime.call('slowEndpoint')
|
|
1723
|
+
).rejects.toThrow('timeout');
|
|
1724
|
+
});
|
|
1725
|
+
});
|
|
1726
|
+
```
|
|
1727
|
+
|
|
1728
|
+
### 5.4 Test Fixtures
|
|
1729
|
+
|
|
1730
|
+
Create sample LAVS services for testing:
|
|
1731
|
+
|
|
1732
|
+
```
|
|
1733
|
+
tests/fixtures/
|
|
1734
|
+
├── todo-service/
|
|
1735
|
+
│ ├── lavs.json
|
|
1736
|
+
│ ├── scripts/
|
|
1737
|
+
│ │ └── todo-service.js
|
|
1738
|
+
│ └── data/
|
|
1739
|
+
│ └── todos.json
|
|
1740
|
+
├── notes-service/
|
|
1741
|
+
│ └── lavs.json
|
|
1742
|
+
└── invalid-manifests/
|
|
1743
|
+
├── missing-version.json
|
|
1744
|
+
├── invalid-schema.json
|
|
1745
|
+
└── bad-handler.json
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
---
|
|
1749
|
+
|
|
1750
|
+
## 6. Documentation Requirements
|
|
1751
|
+
|
|
1752
|
+
### 6.1 README Files
|
|
1753
|
+
|
|
1754
|
+
**For each package:**
|
|
1755
|
+
|
|
1756
|
+
- Quick start guide
|
|
1757
|
+
- Installation instructions
|
|
1758
|
+
- Basic usage examples
|
|
1759
|
+
- API reference link
|
|
1760
|
+
|
|
1761
|
+
### 6.2 API Documentation
|
|
1762
|
+
|
|
1763
|
+
Use JSDoc (TypeScript) and docstrings (Python) for inline documentation.
|
|
1764
|
+
|
|
1765
|
+
Generate API docs with:
|
|
1766
|
+
- TypeScript: **TypeDoc**
|
|
1767
|
+
- Python: **Sphinx**
|
|
1768
|
+
|
|
1769
|
+
### 6.3 Tutorial Documents
|
|
1770
|
+
|
|
1771
|
+
Create step-by-step tutorials:
|
|
1772
|
+
|
|
1773
|
+
1. **Getting Started**: Build a simple note-taking service
|
|
1774
|
+
2. **Advanced Topics**: Subscriptions, permissions, MCP integration
|
|
1775
|
+
3. **Best Practices**: Security, performance, error handling
|
|
1776
|
+
4. **Migration Guide**: From custom APIs to LAVS
|
|
1777
|
+
|
|
1778
|
+
### 6.4 Example Projects
|
|
1779
|
+
|
|
1780
|
+
Provide complete example projects:
|
|
1781
|
+
|
|
1782
|
+
- **todo-manager**: Full-featured todo app with React frontend
|
|
1783
|
+
- **note-taker**: Markdown notes with rich editor
|
|
1784
|
+
- **data-dashboard**: Charts and visualizations
|
|
1785
|
+
- **code-snippet-manager**: Code storage with syntax highlighting
|
|
1786
|
+
|
|
1787
|
+
---
|
|
1788
|
+
|
|
1789
|
+
## 7. Deployment and Distribution
|
|
1790
|
+
|
|
1791
|
+
### 7.1 NPM Packages
|
|
1792
|
+
|
|
1793
|
+
**Backend (TypeScript):**
|
|
1794
|
+
|
|
1795
|
+
```json
|
|
1796
|
+
{
|
|
1797
|
+
"name": "@lavs/runtime",
|
|
1798
|
+
"version": "1.0.0",
|
|
1799
|
+
"main": "dist/index.js",
|
|
1800
|
+
"types": "dist/index.d.ts",
|
|
1801
|
+
"bin": {
|
|
1802
|
+
"lavs": "dist/cli.js"
|
|
1803
|
+
},
|
|
1804
|
+
"dependencies": {
|
|
1805
|
+
"express": "^4.18.0",
|
|
1806
|
+
"ws": "^8.0.0",
|
|
1807
|
+
"ajv": "^8.12.0",
|
|
1808
|
+
"minimatch": "^9.0.0"
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
```
|
|
1812
|
+
|
|
1813
|
+
**Frontend:**
|
|
1814
|
+
|
|
1815
|
+
```json
|
|
1816
|
+
{
|
|
1817
|
+
"name": "@lavs/client",
|
|
1818
|
+
"version": "1.0.0",
|
|
1819
|
+
"main": "dist/index.js",
|
|
1820
|
+
"types": "dist/index.d.ts",
|
|
1821
|
+
"module": "dist/index.esm.js"
|
|
1822
|
+
}
|
|
1823
|
+
```
|
|
1824
|
+
|
|
1825
|
+
### 7.2 PyPI Package (Python)
|
|
1826
|
+
|
|
1827
|
+
```toml
|
|
1828
|
+
# pyproject.toml
|
|
1829
|
+
|
|
1830
|
+
[project]
|
|
1831
|
+
name = "lavs"
|
|
1832
|
+
version = "1.0.0"
|
|
1833
|
+
description = "LAVS Runtime for Python"
|
|
1834
|
+
dependencies = [
|
|
1835
|
+
"aiohttp>=3.8.0",
|
|
1836
|
+
"pydantic>=2.0.0",
|
|
1837
|
+
"jsonschema>=4.0.0"
|
|
1838
|
+
]
|
|
1839
|
+
|
|
1840
|
+
[project.scripts]
|
|
1841
|
+
lavs = "lavs.cli:main"
|
|
1842
|
+
```
|
|
1843
|
+
|
|
1844
|
+
### 7.3 CLI Tool
|
|
1845
|
+
|
|
1846
|
+
Provide CLI for running LAVS services:
|
|
1847
|
+
|
|
1848
|
+
```bash
|
|
1849
|
+
# Install
|
|
1850
|
+
npm install -g @lavs/runtime
|
|
1851
|
+
|
|
1852
|
+
# Run service
|
|
1853
|
+
lavs start ./lavs.json
|
|
1854
|
+
|
|
1855
|
+
# Options
|
|
1856
|
+
lavs start ./lavs.json --port 8000 --host 0.0.0.0
|
|
1857
|
+
```
|
|
1858
|
+
|
|
1859
|
+
### 7.4 Docker Support
|
|
1860
|
+
|
|
1861
|
+
```dockerfile
|
|
1862
|
+
# Dockerfile
|
|
1863
|
+
|
|
1864
|
+
FROM node:20-alpine
|
|
1865
|
+
|
|
1866
|
+
WORKDIR /app
|
|
1867
|
+
|
|
1868
|
+
COPY package*.json ./
|
|
1869
|
+
RUN npm install
|
|
1870
|
+
|
|
1871
|
+
COPY . .
|
|
1872
|
+
|
|
1873
|
+
EXPOSE 5555
|
|
1874
|
+
|
|
1875
|
+
CMD ["lavs", "start", "/app/lavs.json"]
|
|
1876
|
+
```
|
|
1877
|
+
|
|
1878
|
+
---
|
|
1879
|
+
|
|
1880
|
+
## 8. Implementation Timeline
|
|
1881
|
+
|
|
1882
|
+
### Week 1-2: Foundation
|
|
1883
|
+
- Set up repositories (TypeScript + Python)
|
|
1884
|
+
- Define types and interfaces
|
|
1885
|
+
- Implement manifest loader and validator
|
|
1886
|
+
|
|
1887
|
+
### Week 3-4: Core Execution
|
|
1888
|
+
- Implement all executors (script, function, HTTP, MCP)
|
|
1889
|
+
- Add permission enforcement
|
|
1890
|
+
- Unit tests for executors
|
|
1891
|
+
|
|
1892
|
+
### Week 5-6: Server Layer
|
|
1893
|
+
- HTTP server with JSON-RPC
|
|
1894
|
+
- WebSocket server for subscriptions
|
|
1895
|
+
- Integration tests
|
|
1896
|
+
|
|
1897
|
+
### Week 7-8: Frontend SDK
|
|
1898
|
+
- Implement LAVSClient
|
|
1899
|
+
- HTTP and WebSocket transports
|
|
1900
|
+
- Example view components
|
|
1901
|
+
|
|
1902
|
+
### Week 9-10: Testing & Documentation
|
|
1903
|
+
- Comprehensive test suite
|
|
1904
|
+
- API documentation
|
|
1905
|
+
- Tutorial and examples
|
|
1906
|
+
|
|
1907
|
+
### Week 11-12: Polish & Release
|
|
1908
|
+
- Performance optimization
|
|
1909
|
+
- Security audit
|
|
1910
|
+
- Beta release and community feedback
|
|
1911
|
+
|
|
1912
|
+
---
|
|
1913
|
+
|
|
1914
|
+
## 9. Success Metrics
|
|
1915
|
+
|
|
1916
|
+
### Technical Metrics
|
|
1917
|
+
- [ ] Test coverage > 80%
|
|
1918
|
+
- [ ] API documentation complete
|
|
1919
|
+
- [ ] All spec requirements implemented
|
|
1920
|
+
- [ ] Security audit passed
|
|
1921
|
+
|
|
1922
|
+
### Community Metrics
|
|
1923
|
+
- [ ] 3+ example projects published
|
|
1924
|
+
- [ ] Tutorial documentation complete
|
|
1925
|
+
- [ ] Early adopter feedback incorporated
|
|
1926
|
+
- [ ] 50+ GitHub stars in first month
|
|
1927
|
+
|
|
1928
|
+
### Performance Metrics
|
|
1929
|
+
- [ ] HTTP request latency < 50ms (local)
|
|
1930
|
+
- [ ] Subscription latency < 100ms
|
|
1931
|
+
- [ ] Supports 100+ concurrent requests
|
|
1932
|
+
- [ ] Memory usage < 100MB for typical service
|
|
1933
|
+
|
|
1934
|
+
---
|
|
1935
|
+
|
|
1936
|
+
## Appendix A: Technology Stack
|
|
1937
|
+
|
|
1938
|
+
### Backend (TypeScript)
|
|
1939
|
+
- **Runtime**: Node.js 18+
|
|
1940
|
+
- **HTTP Server**: Express.js
|
|
1941
|
+
- **WebSocket**: ws
|
|
1942
|
+
- **Validation**: Ajv (JSON Schema)
|
|
1943
|
+
- **Testing**: Vitest
|
|
1944
|
+
- **Build**: tsup
|
|
1945
|
+
|
|
1946
|
+
### Backend (Python)
|
|
1947
|
+
- **Runtime**: Python 3.10+
|
|
1948
|
+
- **HTTP Server**: aiohttp
|
|
1949
|
+
- **Validation**: jsonschema + Pydantic
|
|
1950
|
+
- **Testing**: pytest
|
|
1951
|
+
- **Build**: setuptools
|
|
1952
|
+
|
|
1953
|
+
### Frontend (TypeScript)
|
|
1954
|
+
- **Build**: Vite
|
|
1955
|
+
- **Testing**: Vitest + jsdom
|
|
1956
|
+
- **Bundle**: ESM + CommonJS
|
|
1957
|
+
|
|
1958
|
+
---
|
|
1959
|
+
|
|
1960
|
+
## Appendix B: Reference Links
|
|
1961
|
+
|
|
1962
|
+
- LAVS Specification: [LAVS-SPEC.md](./LAVS-SPEC.md)
|
|
1963
|
+
- JSON-RPC 2.0: https://www.jsonrpc.org/specification
|
|
1964
|
+
- JSON Schema: https://json-schema.org/
|
|
1965
|
+
- Model Context Protocol: https://modelcontextprotocol.io/
|
|
1966
|
+
|
|
1967
|
+
---
|
|
1968
|
+
|
|
1969
|
+
## License
|
|
1970
|
+
|
|
1971
|
+
Apache 2.0
|
|
1972
|
+
|
|
1973
|
+
Copyright 2025 AgentStudio Team
|