kennel 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -5
- package/dist/cli/dispatch.js +9 -0
- package/dist/cli/src/automations/notifications.d.ts +40 -0
- package/dist/cli/src/automations/notifications.js +220 -0
- package/dist/cli/src/cli/dispatch.d.ts +1 -0
- package/dist/cli/src/cli/dispatch.js +125 -0
- package/dist/cli/src/cli/usage.d.ts +1 -0
- package/dist/cli/src/cli/usage.js +25 -0
- package/dist/cli/src/core/api-client.d.ts +13 -0
- package/dist/cli/src/core/api-client.js +1 -0
- package/dist/cli/src/core/command.d.ts +1 -0
- package/dist/cli/src/core/command.js +69 -0
- package/dist/cli/src/core/core-folders.d.ts +1 -0
- package/dist/cli/src/core/core-folders.js +42 -0
- package/dist/cli/src/core/init.d.ts +1 -0
- package/dist/cli/src/core/init.js +141 -0
- package/dist/cli/src/core/runtime.d.ts +14 -0
- package/dist/cli/src/core/runtime.js +1 -0
- package/dist/cli/src/deploy/cloudflare.d.ts +6 -0
- package/dist/cli/src/deploy/cloudflare.js +100 -0
- package/dist/cli/src/deploy/environment.d.ts +2 -0
- package/dist/cli/src/deploy/environment.js +47 -0
- package/dist/cli/src/deploy/smoke-tests.d.ts +4 -0
- package/dist/cli/src/deploy/smoke-tests.js +92 -0
- package/dist/cli/src/deploy/trigger-dev.d.ts +2 -0
- package/dist/cli/src/deploy/trigger-dev.js +255 -0
- package/dist/cli/src/deploy/vercel.d.ts +3 -0
- package/dist/cli/src/deploy/vercel.js +67 -0
- package/dist/cli/src/main.d.ts +1 -0
- package/dist/cli/src/main.js +9 -0
- package/dist/cli/src/mcp/agent-tools.d.ts +8 -0
- package/dist/cli/src/mcp/agent-tools.js +247 -0
- package/dist/cli/src/mcp/config.d.ts +25 -0
- package/dist/cli/src/mcp/config.js +185 -0
- package/dist/cli/src/mcp/function-source.d.ts +7 -0
- package/dist/cli/src/mcp/function-source.js +42 -0
- package/dist/cli/src/mcp/generate.d.ts +1 -0
- package/dist/cli/src/mcp/generate.js +47 -0
- package/dist/cli/src/mcp/install-page.d.ts +12 -0
- package/dist/cli/src/mcp/install-page.js +5 -0
- package/dist/cli/src/notifications/email-worker.d.ts +8 -0
- package/dist/cli/src/notifications/email-worker.js +137 -0
- package/dist/cli/src/package/mcp-data.d.ts +1 -0
- package/dist/cli/src/package/mcp-data.js +1 -0
- package/dist/cli/src/package/mcp-email-worker.d.ts +1 -0
- package/dist/cli/src/package/mcp-email-worker.js +1 -0
- package/dist/cli/src/package/mcp-http.d.ts +1 -0
- package/dist/cli/src/package/mcp-http.js +1 -0
- package/dist/cli/src/package/mcp-stdio.d.ts +1 -0
- package/dist/cli/src/package/mcp-stdio.js +1 -0
- package/dist/cli/src/package/mcp.d.ts +1 -0
- package/dist/cli/src/package/mcp.js +1 -0
- package/dist/cli/src/package/preview.d.ts +9 -0
- package/dist/cli/src/package/preview.js +1 -0
- package/dist/cli/src/plugins/external.d.ts +36 -0
- package/dist/cli/src/plugins/external.js +503 -0
- package/dist/cli/src/publish/cloudflare-init.d.ts +12 -0
- package/dist/cli/src/publish/cloudflare-init.js +101 -0
- package/dist/cli/src/publish/config.d.ts +28 -0
- package/dist/cli/src/publish/config.js +178 -0
- package/dist/cli/src/publish/options.d.ts +13 -0
- package/dist/cli/src/publish/options.js +78 -0
- package/dist/cli/src/publish/vercel-init.d.ts +9 -0
- package/dist/cli/src/publish/vercel-init.js +52 -0
- package/dist/cli/src/shared/json.d.ts +4 -0
- package/dist/cli/src/shared/json.js +56 -0
- package/dist/cli/src/shared/object.d.ts +2 -0
- package/dist/cli/src/shared/object.js +3 -0
- package/dist/cli/src/shared/package-manager.d.ts +11 -0
- package/dist/cli/src/shared/package-manager.js +39 -0
- package/dist/cli/src/shared/path.d.ts +4 -0
- package/dist/cli/src/shared/path.js +40 -0
- package/dist/cli/src/shared/process.d.ts +7 -0
- package/dist/cli/src/shared/process.js +12 -0
- package/dist/cli/src/shared/project-config.d.ts +2 -0
- package/dist/cli/src/shared/project-config.js +26 -0
- package/dist/cli/src/site/dev.d.ts +10 -0
- package/dist/cli/src/site/dev.js +126 -0
- package/dist/cli/src/site/extension.d.ts +8 -0
- package/dist/cli/src/site/extension.js +113 -0
- package/dist/cli/src/site/folder-icons.d.ts +46 -0
- package/dist/cli/src/site/folder-icons.js +86 -0
- package/dist/cli/src/site/hot-viewer.d.ts +2 -0
- package/dist/cli/src/site/hot-viewer.js +231 -0
- package/dist/cli/src/site/kinds.d.ts +1 -0
- package/dist/cli/src/site/kinds.js +1 -0
- package/dist/cli/src/site/mail.d.ts +1 -0
- package/dist/cli/src/site/mail.js +10 -0
- package/dist/cli/src/site/renderers.d.ts +61 -0
- package/dist/cli/src/site/renderers.js +219 -0
- package/dist/cli/src/site/server-plugins.d.ts +54 -0
- package/dist/cli/src/site/server-plugins.js +1 -0
- package/dist/cli/src/site/viewer.d.ts +36 -0
- package/dist/cli/src/site/viewer.js +352 -0
- package/dist/cli/src/site/vitepress.d.ts +1 -0
- package/dist/cli/src/site/vitepress.js +1 -0
- package/dist/cli/usage.js +1 -0
- package/dist/core/api-client.js +75 -44
- package/dist/core/command.js +6 -3
- package/dist/core/core-folders.js +38280 -33
- package/dist/core/init.js +59 -4
- package/dist/core/runtime.js +57163 -41853
- package/dist/package/preview.js +40589 -17894
- package/dist/plugins/external.d.ts +36 -0
- package/dist/plugins/external.js +503 -0
- package/dist/site/server-plugins.js +394 -59
- package/dist/site/viewer.js +18 -5
- package/kernel/apps/web/.env.example +11 -0
- package/kernel/apps/web/components.json +20 -0
- package/kernel/apps/web/eslint.config.mjs +60 -0
- package/kernel/apps/web/index.html +17 -0
- package/kernel/apps/web/package.json +79 -0
- package/kernel/apps/web/public/favicon.svg +6 -0
- package/kernel/apps/web/public/providers/claude.svg +1 -0
- package/kernel/apps/web/public/providers/codex.svg +1 -0
- package/kernel/apps/web/public/providers/cursor.svg +1 -0
- package/kernel/apps/web/public/providers/opencode.svg +1 -0
- package/kernel/apps/web/public/providers/pi.svg +1 -0
- package/kernel/apps/web/server/acp/index.ts +1 -0
- package/kernel/apps/web/server/acp/live-agent-connection.ts +1 -0
- package/kernel/apps/web/server/acp/process-manager.ts +1 -0
- package/kernel/apps/web/server/acp/registry.ts +1 -0
- package/kernel/apps/web/server/acp/sdk.ts +1 -0
- package/kernel/apps/web/server/acp/transport.ts +1 -0
- package/kernel/apps/web/server/acp/types.ts +1 -0
- package/kernel/apps/web/server/acp-live-plugin.ts +30 -0
- package/kernel/apps/web/server/api/document-edit.ts +1 -0
- package/kernel/apps/web/server/api/open-path.ts +1 -0
- package/kernel/apps/web/server/core-plugin.ts +49 -0
- package/kernel/apps/web/server/folder-favicon.ts +1 -0
- package/kernel/apps/web/server/folder-icons.ts +1 -0
- package/kernel/apps/web/server/folder-metadata-plugin.ts +31 -0
- package/kernel/apps/web/server/plugins.ts +1 -0
- package/kernel/apps/web/server/preview-kinds.ts +1 -0
- package/kernel/apps/web/src/ai-input.tsx +62 -0
- package/kernel/apps/web/src/annotations.tsx +430 -0
- package/kernel/apps/web/src/api/client.ts +3 -0
- package/kernel/apps/web/src/api/errors.ts +1 -0
- package/kernel/apps/web/src/api/events.ts +42 -0
- package/kernel/apps/web/src/app.css +332 -0
- package/kernel/apps/web/src/app.tsx +667 -0
- package/kernel/apps/web/src/ask-draft.ts +164 -0
- package/kernel/apps/web/src/ask-tray.tsx +256 -0
- package/kernel/apps/web/src/comment-editor.tsx +93 -0
- package/kernel/apps/web/src/comment-form.tsx +162 -0
- package/kernel/apps/web/src/copy-path.ts +18 -0
- package/kernel/apps/web/src/deferred-ask-tray.tsx +20 -0
- package/kernel/apps/web/src/document-url.ts +46 -0
- package/kernel/apps/web/src/documents-url.ts +23 -0
- package/kernel/apps/web/src/dropped-folder.ts +64 -0
- package/kernel/apps/web/src/external-plugins.ts +3 -0
- package/kernel/apps/web/src/file-viewer.tsx +171 -0
- package/kernel/apps/web/src/folder-filter-icons.tsx +39 -0
- package/kernel/apps/web/src/folder-metadata.ts +76 -0
- package/kernel/apps/web/src/folder-plugin-view.tsx +87 -0
- package/kernel/apps/web/src/folder-query-cache.ts +66 -0
- package/kernel/apps/web/src/host-adapters.ts +209 -0
- package/kernel/apps/web/src/host-bridge.ts +214 -0
- package/kernel/apps/web/src/lib/entity-folder.ts +2 -0
- package/kernel/apps/web/src/linked-session-header.tsx +43 -0
- package/kernel/apps/web/src/live-session-controls.tsx +326 -0
- package/kernel/apps/web/src/local-source.ts +32 -0
- package/kernel/apps/web/src/main.tsx +24 -0
- package/kernel/apps/web/src/markdown-page.tsx +444 -0
- package/kernel/apps/web/src/notes-page.tsx +103 -0
- package/kernel/apps/web/src/plugins.ts +53 -0
- package/kernel/apps/web/src/project-search-dialog.tsx +257 -0
- package/kernel/apps/web/src/project-search.ts +18 -0
- package/kernel/apps/web/src/query-client.ts +4 -0
- package/kernel/apps/web/src/rehype-source-lines.ts +22 -0
- package/kernel/apps/web/src/routes/document.tsx +1 -0
- package/kernel/apps/web/src/routes/entities.tsx +277 -0
- package/kernel/apps/web/src/routes/search.tsx +60 -0
- package/kernel/apps/web/src/selection-context.ts +68 -0
- package/kernel/apps/web/src/selection-input.tsx +58 -0
- package/kernel/apps/web/src/selection-popup.tsx +155 -0
- package/kernel/apps/web/src/session-transcript-page.tsx +152 -0
- package/kernel/apps/web/src/use-annotations.ts +162 -0
- package/kernel/apps/web/src/use-ask-ai.ts +26 -0
- package/kernel/apps/web/src/use-ask-draft.ts +27 -0
- package/kernel/apps/web/src/use-document.ts +37 -0
- package/kernel/apps/web/src/use-folder-notes.ts +49 -0
- package/kernel/apps/web/src/use-linked-session.ts +33 -0
- package/kernel/apps/web/src/view-context.tsx +69 -0
- package/kernel/apps/web/src/view-header.tsx +66 -0
- package/kernel/apps/web/src/viewer-capabilities.ts +33 -0
- package/kernel/apps/web/src/viewer-route.ts +1 -0
- package/kernel/apps/web/src/viewport-height.ts +33 -0
- package/kernel/apps/web/tsconfig.json +24 -0
- package/kernel/apps/web/vite.config.ts +252 -0
- package/kernel/packages/agents/eslint.config.js +10 -0
- package/kernel/packages/agents/package.json +75 -0
- package/kernel/packages/agents/src/agent-card.tsx +334 -0
- package/kernel/packages/agents/src/client.tsx +13 -0
- package/kernel/packages/agents/src/index.ts +18 -0
- package/kernel/packages/agents/src/manifest.ts +7 -0
- package/kernel/packages/agents/src/node.ts +447 -0
- package/kernel/packages/agents/src/profiles.ts +137 -0
- package/kernel/packages/agents/src/resolve.ts +69 -0
- package/kernel/packages/agents/src/server.ts +60 -0
- package/kernel/packages/agents/src/types.ts +82 -0
- package/kernel/packages/agents/src/viewer.tsx +370 -0
- package/kernel/packages/agents/test/profiles.test.mjs +88 -0
- package/kernel/packages/agents/test/resolve.test.mjs +729 -0
- package/kernel/packages/agents/tsconfig.json +17 -0
- package/kernel/packages/api/README.md +73 -0
- package/kernel/packages/api/openapi.json +3368 -0
- package/kernel/packages/api/package.json +41 -0
- package/kernel/packages/api/src/client/errors.ts +1 -0
- package/kernel/packages/api/src/client/index.ts +2 -0
- package/kernel/packages/api/src/contracts/schemas.ts +277 -0
- package/kernel/packages/api/src/contracts.ts +20 -0
- package/kernel/packages/api/src/index.ts +34 -0
- package/kernel/packages/api/src/server/acp/index.ts +35 -0
- package/kernel/packages/api/src/server/acp/live-agent-connection.ts +44 -0
- package/kernel/packages/api/src/server/acp/process-manager.ts +291 -0
- package/kernel/packages/api/src/server/acp/registry.ts +140 -0
- package/kernel/packages/api/src/server/acp/sdk.ts +15 -0
- package/kernel/packages/api/src/server/acp/transport.ts +115 -0
- package/kernel/packages/api/src/server/acp/types.ts +89 -0
- package/kernel/packages/api/src/server/acp-live-plugin.ts +423 -0
- package/kernel/packages/api/src/server/api/create-agent-file.ts +46 -0
- package/kernel/packages/api/src/server/api/document-edit.ts +125 -0
- package/kernel/packages/api/src/server/api/open-path.ts +40 -0
- package/kernel/packages/api/src/server/contracts.ts +85 -0
- package/kernel/packages/api/src/server/entity-folder.ts +353 -0
- package/kernel/packages/api/src/server/folder-favicon.ts +17 -0
- package/kernel/packages/api/src/server/folder-icons.ts +113 -0
- package/kernel/packages/api/src/server/folder-metadata-plugin.ts +1758 -0
- package/kernel/packages/api/src/server/host.ts +21 -0
- package/kernel/packages/api/src/server/index.ts +197 -0
- package/kernel/packages/api/src/server/linked-folder-discovery.ts +158 -0
- package/kernel/packages/api/src/server/plugins.ts +205 -0
- package/kernel/packages/api/src/server/project-discovery.ts +69 -0
- package/kernel/packages/api/src/server/watcher.ts +46 -0
- package/kernel/packages/api/src/shared/selection.ts +16 -0
- package/kernel/packages/api/src/shared/viewer-route.ts +200 -0
- package/kernel/packages/api/test/agents-loading.test.ts +94 -0
- package/kernel/packages/api/test/core.test.ts +364 -0
- package/kernel/packages/api/test/entity-folder.test.ts +131 -0
- package/kernel/packages/api/test/linked-folder-discovery.test.ts +78 -0
- package/kernel/packages/api/test/media-endpoint.test.ts +83 -0
- package/kernel/packages/api/test/partial-loading.test.ts +43 -0
- package/kernel/packages/api/test/project-discovery.test.ts +44 -0
- package/kernel/packages/api/tsconfig.json +11 -0
- package/kernel/packages/api-client/README.md +72 -0
- package/kernel/packages/api-client/package.json +26 -0
- package/kernel/packages/api-client/scripts/generate.ts +68 -0
- package/kernel/packages/api-client/src/errors.ts +59 -0
- package/kernel/packages/api-client/src/generated.d.ts +1248 -0
- package/kernel/packages/api-client/src/index.ts +206 -0
- package/kernel/packages/api-client/src/responses.ts +19 -0
- package/kernel/packages/api-client/test/client.test.ts +143 -0
- package/kernel/packages/api-client/tsconfig.json +12 -0
- package/kernel/packages/folder-plugin/eslint.config.js +10 -0
- package/kernel/packages/folder-plugin/package.json +50 -0
- package/kernel/packages/folder-plugin/src/client.ts +73 -0
- package/kernel/packages/folder-plugin/src/endpoint.ts +273 -0
- package/kernel/packages/folder-plugin/src/index.ts +15 -0
- package/kernel/packages/folder-plugin/src/server.ts +78 -0
- package/kernel/packages/folder-plugin/src/subpath.ts +34 -0
- package/kernel/packages/folder-plugin/src/types.ts +86 -0
- package/kernel/packages/folder-plugin/src/validation.ts +56 -0
- package/kernel/packages/folder-plugin/test/contract.test.mjs +133 -0
- package/kernel/packages/folder-plugin/tsconfig.json +17 -0
- package/kernel/packages/kinds/package.json +24 -0
- package/kernel/packages/kinds/src/kinds.ts +172 -0
- package/kernel/packages/markdown/README.md +40 -0
- package/kernel/packages/markdown/explorer.css +1 -0
- package/kernel/packages/markdown/package.json +30 -0
- package/kernel/packages/markdown/src/documents.ts +1 -0
- package/kernel/packages/markdown/src/explorer.ts +1 -0
- package/kernel/packages/markdown/src/index.ts +2 -0
- package/kernel/packages/markdown/src/metadata.ts +63 -0
- package/kernel/packages/markdown/src/node.ts +1 -0
- package/kernel/packages/markdown/styles.css +1 -0
- package/kernel/packages/notes/SKILL.md +19 -0
- package/kernel/packages/notes/eslint.config.js +10 -0
- package/kernel/packages/notes/package.json +72 -0
- package/kernel/packages/notes/src/client.tsx +12 -0
- package/kernel/packages/notes/src/data/ai-input.ts +58 -0
- package/kernel/packages/notes/src/data/api.ts +40 -0
- package/kernel/packages/notes/src/data/parse.ts +15 -0
- package/kernel/packages/notes/src/data/routing.ts +33 -0
- package/kernel/packages/notes/src/data/use-folder-notes.ts +49 -0
- package/kernel/packages/notes/src/index.ts +2 -0
- package/kernel/packages/notes/src/manifest.ts +6 -0
- package/kernel/packages/notes/src/pages/notes-page.tsx +79 -0
- package/kernel/packages/notes/src/pages/single-note-page.tsx +57 -0
- package/kernel/packages/notes/src/server.ts +88 -0
- package/kernel/packages/notes/src/ui/ai-composer-controls.tsx +70 -0
- package/kernel/packages/notes/src/ui/folder-notes-list.tsx +140 -0
- package/kernel/packages/notes/tsconfig.json +16 -0
- package/kernel/packages/schemas/ICON-POLICY.md +43 -0
- package/kernel/packages/schemas/SKILL.md +185 -0
- package/kernel/packages/schemas/eslint.config.js +10 -0
- package/kernel/packages/schemas/package.json +81 -0
- package/kernel/packages/schemas/src/client.tsx +137 -0
- package/kernel/packages/schemas/src/data/config-file.ts +37 -0
- package/kernel/packages/schemas/src/data/contract.ts +174 -0
- package/kernel/packages/schemas/src/data/favicon.ts +218 -0
- package/kernel/packages/schemas/src/data/fields.ts +96 -0
- package/kernel/packages/schemas/src/data/icon-image.ts +53 -0
- package/kernel/packages/schemas/src/data/icon.ts +97 -0
- package/kernel/packages/schemas/src/data/load.ts +161 -0
- package/kernel/packages/schemas/src/data/params.ts +103 -0
- package/kernel/packages/schemas/src/data/query.ts +33 -0
- package/kernel/packages/schemas/src/data/sort.ts +50 -0
- package/kernel/packages/schemas/src/data/workspace.ts +101 -0
- package/kernel/packages/schemas/src/index.ts +22 -0
- package/kernel/packages/schemas/src/manifest.ts +4 -0
- package/kernel/packages/schemas/src/node.ts +384 -0
- package/kernel/packages/schemas/src/pages/collection.tsx +252 -0
- package/kernel/packages/schemas/src/server.ts +208 -0
- package/kernel/packages/schemas/src/ui/schema-entity-list.tsx +124 -0
- package/kernel/packages/schemas/src/ui/schema-filters.tsx +186 -0
- package/kernel/packages/schemas/src/ui/schema-search.tsx +35 -0
- package/kernel/packages/schemas/src/ui/use-query-param-filter-setting.tsx +15 -0
- package/kernel/packages/schemas/test/contract.test.mjs +26 -0
- package/kernel/packages/schemas/test/fields.test.mjs +187 -0
- package/kernel/packages/schemas/test/load.test.mjs +12 -0
- package/kernel/packages/schemas/test/node.test.mjs +412 -0
- package/kernel/packages/schemas/test/query.test.mjs +134 -0
- package/kernel/packages/schemas/test/workspace.test.mjs +86 -0
- package/kernel/packages/schemas/tsconfig.json +17 -0
- package/kernel/packages/session-finding/package.json +33 -0
- package/kernel/packages/session-finding/src/index.ts +120 -0
- package/kernel/packages/session-finding/test/list-sessions.test.mjs +139 -0
- package/kernel/packages/session-finding/tsconfig.json +12 -0
- package/kernel/packages/ui/LICENSE +21 -0
- package/kernel/packages/ui/components.json +20 -0
- package/kernel/packages/ui/eslint.config.js +8 -0
- package/kernel/packages/ui/package.json +106 -0
- package/kernel/packages/ui/src/chat/file-link.ts +178 -0
- package/kernel/packages/ui/src/chat/index.ts +18 -0
- package/kernel/packages/ui/src/chat/transcript.tsx +348 -0
- package/kernel/packages/ui/src/chat/turns.ts +76 -0
- package/kernel/packages/ui/src/chat/types.ts +23 -0
- package/kernel/packages/ui/src/chat/use-overflowing.ts +56 -0
- package/kernel/packages/ui/src/components/accordion.tsx +74 -0
- package/kernel/packages/ui/src/components/alert-dialog.tsx +164 -0
- package/kernel/packages/ui/src/components/alert.tsx +68 -0
- package/kernel/packages/ui/src/components/app-breadcrumbs.tsx +170 -0
- package/kernel/packages/ui/src/components/app-header.tsx +125 -0
- package/kernel/packages/ui/src/components/app-options.tsx +87 -0
- package/kernel/packages/ui/src/components/app-view-header.tsx +34 -0
- package/kernel/packages/ui/src/components/aspect-ratio.tsx +11 -0
- package/kernel/packages/ui/src/components/avatar.tsx +53 -0
- package/kernel/packages/ui/src/components/badge.tsx +47 -0
- package/kernel/packages/ui/src/components/base-dialog.tsx +3 -0
- package/kernel/packages/ui/src/components/base-tabs.tsx +63 -0
- package/kernel/packages/ui/src/components/breadcrumb.tsx +110 -0
- package/kernel/packages/ui/src/components/button-group.tsx +86 -0
- package/kernel/packages/ui/src/components/button.tsx +65 -0
- package/kernel/packages/ui/src/components/calendar.tsx +240 -0
- package/kernel/packages/ui/src/components/card.tsx +95 -0
- package/kernel/packages/ui/src/components/carousel.tsx +240 -0
- package/kernel/packages/ui/src/components/chart.tsx +375 -0
- package/kernel/packages/ui/src/components/checkbox.tsx +39 -0
- package/kernel/packages/ui/src/components/collapsible.tsx +33 -0
- package/kernel/packages/ui/src/components/collection-icon.tsx +28 -0
- package/kernel/packages/ui/src/components/command.tsx +205 -0
- package/kernel/packages/ui/src/components/content-issues.tsx +63 -0
- package/kernel/packages/ui/src/components/context-menu.tsx +298 -0
- package/kernel/packages/ui/src/components/copy-context.tsx +134 -0
- package/kernel/packages/ui/src/components/dialog.tsx +157 -0
- package/kernel/packages/ui/src/components/drawer.tsx +162 -0
- package/kernel/packages/ui/src/components/dropdown-menu.tsx +303 -0
- package/kernel/packages/ui/src/components/empty.tsx +108 -0
- package/kernel/packages/ui/src/components/field.tsx +260 -0
- package/kernel/packages/ui/src/components/file-preview.tsx +152 -0
- package/kernel/packages/ui/src/components/file-renderer.tsx +466 -0
- package/kernel/packages/ui/src/components/filter-chip-panel.tsx +157 -0
- package/kernel/packages/ui/src/components/filter-select.tsx +127 -0
- package/kernel/packages/ui/src/components/folder-activity.tsx +646 -0
- package/kernel/packages/ui/src/components/folder-file-list.tsx +58 -0
- package/kernel/packages/ui/src/components/folder-filter-bar.tsx +191 -0
- package/kernel/packages/ui/src/components/folder-image.tsx +18 -0
- package/kernel/packages/ui/src/components/folder-landing.tsx +70 -0
- package/kernel/packages/ui/src/components/folder-list.tsx +140 -0
- package/kernel/packages/ui/src/components/folder-metadata.tsx +107 -0
- package/kernel/packages/ui/src/components/folder-mobile-bar.tsx +60 -0
- package/kernel/packages/ui/src/components/folder-project-list.tsx +133 -0
- package/kernel/packages/ui/src/components/folder-session-list.tsx +113 -0
- package/kernel/packages/ui/src/components/folder-session-page.tsx +126 -0
- package/kernel/packages/ui/src/components/folder-sidebar.tsx +52 -0
- package/kernel/packages/ui/src/components/folder-skill-list.tsx +62 -0
- package/kernel/packages/ui/src/components/folder-tabs.tsx +156 -0
- package/kernel/packages/ui/src/components/form.tsx +167 -0
- package/kernel/packages/ui/src/components/hover-card.tsx +52 -0
- package/kernel/packages/ui/src/components/icons.tsx +34 -0
- package/kernel/packages/ui/src/components/input-group.tsx +184 -0
- package/kernel/packages/ui/src/components/input-otp.tsx +90 -0
- package/kernel/packages/ui/src/components/input.tsx +29 -0
- package/kernel/packages/ui/src/components/item.tsx +195 -0
- package/kernel/packages/ui/src/components/kbd.tsx +32 -0
- package/kernel/packages/ui/src/components/label.tsx +27 -0
- package/kernel/packages/ui/src/components/link.tsx +45 -0
- package/kernel/packages/ui/src/components/live-tool-call.tsx +193 -0
- package/kernel/packages/ui/src/components/menubar.tsx +323 -0
- package/kernel/packages/ui/src/components/navigation-menu.tsx +210 -0
- package/kernel/packages/ui/src/components/note-card.tsx +149 -0
- package/kernel/packages/ui/src/components/pagination.tsx +128 -0
- package/kernel/packages/ui/src/components/popover.tsx +56 -0
- package/kernel/packages/ui/src/components/progress.tsx +31 -0
- package/kernel/packages/ui/src/components/radio-group.tsx +54 -0
- package/kernel/packages/ui/src/components/scroll-area.tsx +61 -0
- package/kernel/packages/ui/src/components/select.tsx +219 -0
- package/kernel/packages/ui/src/components/separator.tsx +30 -0
- package/kernel/packages/ui/src/components/session-icon.tsx +124 -0
- package/kernel/packages/ui/src/components/sheet.tsx +157 -0
- package/kernel/packages/ui/src/components/sidebar.tsx +789 -0
- package/kernel/packages/ui/src/components/skeleton.tsx +13 -0
- package/kernel/packages/ui/src/components/slider.tsx +73 -0
- package/kernel/packages/ui/src/components/sonner.tsx +41 -0
- package/kernel/packages/ui/src/components/spinner.tsx +16 -0
- package/kernel/packages/ui/src/components/switch.tsx +40 -0
- package/kernel/packages/ui/src/components/table.tsx +120 -0
- package/kernel/packages/ui/src/components/tabs.tsx +78 -0
- package/kernel/packages/ui/src/components/textarea.tsx +25 -0
- package/kernel/packages/ui/src/components/toggle-group.tsx +87 -0
- package/kernel/packages/ui/src/components/toggle.tsx +48 -0
- package/kernel/packages/ui/src/components/tooltip.tsx +71 -0
- package/kernel/packages/ui/src/components/viewer-options.tsx +166 -0
- package/kernel/packages/ui/src/hooks/use-folder-filter.ts +103 -0
- package/kernel/packages/ui/src/hooks/use-mobile.ts +19 -0
- package/kernel/packages/ui/src/index.ts +13 -0
- package/kernel/packages/ui/src/lib/document-extensions.ts +83 -0
- package/kernel/packages/ui/src/lib/folder-activity.ts +143 -0
- package/kernel/packages/ui/src/lib/folder-filter.ts +284 -0
- package/kernel/packages/ui/src/lib/live-tool-call.tsx +109 -0
- package/kernel/packages/ui/src/lib/media-urls.ts +176 -0
- package/kernel/packages/ui/src/lib/obsidian-links.ts +120 -0
- package/kernel/packages/ui/src/lib/source-components.tsx +65 -0
- package/kernel/packages/ui/src/lib/utils.tsx +7 -0
- package/kernel/packages/ui/src/pages/entity-detail-page.tsx +82 -0
- package/kernel/packages/ui/src/pages/entity-list-page.tsx +50 -0
- package/kernel/packages/ui/src/pages/entity-page.tsx +69 -0
- package/kernel/packages/ui/src/styles/folder-activity.css +2151 -0
- package/kernel/packages/ui/test/copy-context.test.mjs +48 -0
- package/kernel/packages/ui/test/folder-filter.test.mjs +484 -0
- package/kernel/packages/ui/tsconfig.json +15 -0
- package/kernel/plugins/calendar/SKILL.md +173 -0
- package/kernel/plugins/calendar/eslint.config.js +10 -0
- package/kernel/plugins/calendar/package.json +73 -0
- package/kernel/plugins/calendar/schema.json +137 -0
- package/kernel/plugins/calendar/src/calendar.tsx +328 -0
- package/kernel/plugins/calendar/src/client.tsx +139 -0
- package/kernel/plugins/calendar/src/context.ts +48 -0
- package/kernel/plugins/calendar/src/copy-button.tsx +66 -0
- package/kernel/plugins/calendar/src/event-dialog.tsx +270 -0
- package/kernel/plugins/calendar/src/index.ts +4 -0
- package/kernel/plugins/calendar/src/manifest.ts +7 -0
- package/kernel/plugins/calendar/src/parse.ts +610 -0
- package/kernel/plugins/calendar/src/server.ts +160 -0
- package/kernel/plugins/calendar/src/utils.ts +80 -0
- package/kernel/plugins/calendar/src/views.tsx +418 -0
- package/kernel/plugins/calendar/test/context.test.mjs +60 -0
- package/kernel/plugins/calendar/test/package.test.mjs +43 -0
- package/kernel/plugins/calendar/test/parse.test.mjs +392 -0
- package/kernel/plugins/calendar/test/server.test.mjs +126 -0
- package/kernel/plugins/calendar/tsconfig.json +17 -0
- package/kernel/plugins/mail/SKILL.md +97 -0
- package/kernel/plugins/mail/eslint.config.js +10 -0
- package/kernel/plugins/mail/package.json +79 -0
- package/kernel/plugins/mail/src/api.ts +359 -0
- package/kernel/plugins/mail/src/bun-ffi.d.ts +14 -0
- package/kernel/plugins/mail/src/client.tsx +14 -0
- package/kernel/plugins/mail/src/flock.ts +137 -0
- package/kernel/plugins/mail/src/folders.ts +37 -0
- package/kernel/plugins/mail/src/history.ts +485 -0
- package/kernel/plugins/mail/src/index.ts +3 -0
- package/kernel/plugins/mail/src/mail-card.tsx +123 -0
- package/kernel/plugins/mail/src/mail-conversation.tsx +153 -0
- package/kernel/plugins/mail/src/mail-detail-page.tsx +467 -0
- package/kernel/plugins/mail/src/mail-hooks.ts +252 -0
- package/kernel/plugins/mail/src/mail-page.tsx +109 -0
- package/kernel/plugins/mail/src/mail-request.ts +78 -0
- package/kernel/plugins/mail/src/mail-send-box.tsx +175 -0
- package/kernel/plugins/mail/src/mailos.ts +723 -0
- package/kernel/plugins/mail/src/manifest.ts +7 -0
- package/kernel/plugins/mail/src/node.ts +171 -0
- package/kernel/plugins/mail/src/parse.ts +139 -0
- package/kernel/plugins/mail/src/server.ts +125 -0
- package/kernel/plugins/mail/src/types.ts +10 -0
- package/kernel/plugins/mail/src/viewer.tsx +147 -0
- package/kernel/plugins/mail/test/flock.test.mjs +156 -0
- package/kernel/plugins/mail/test/folders.test.mjs +138 -0
- package/kernel/plugins/mail/test/history.test.mjs +460 -0
- package/kernel/plugins/mail/test/mailos.test.mjs +752 -0
- package/kernel/plugins/mail/test/node.test.mjs +207 -0
- package/kernel/plugins/mail/test/package.test.mjs +54 -0
- package/kernel/plugins/mail/test/parse.test.mjs +32 -0
- package/kernel/plugins/mail/test/server.test.mjs +116 -0
- package/kernel/plugins/mail/test/viewer.test.mjs +192 -0
- package/kernel/plugins/mail/tsconfig.json +17 -0
- package/kernel/plugins/projects/SKILL.md +73 -0
- package/kernel/plugins/projects/eslint.config.js +10 -0
- package/kernel/plugins/projects/package.json +70 -0
- package/kernel/plugins/projects/src/client.tsx +17 -0
- package/kernel/plugins/projects/src/data/model.ts +129 -0
- package/kernel/plugins/projects/src/index.ts +17 -0
- package/kernel/plugins/projects/src/manifest.ts +7 -0
- package/kernel/plugins/projects/src/project-context.ts +41 -0
- package/kernel/plugins/projects/src/server.ts +276 -0
- package/kernel/plugins/projects/src/ui/project-card.tsx +61 -0
- package/kernel/plugins/projects/src/ui/projects-page.tsx +102 -0
- package/kernel/plugins/projects/test/package.test.mjs +51 -0
- package/kernel/plugins/projects/tsconfig.json +17 -0
- package/kernel/plugins/tasks/SKILL.md +341 -0
- package/kernel/plugins/tasks/eslint.config.js +10 -0
- package/kernel/plugins/tasks/package.json +74 -0
- package/kernel/plugins/tasks/schema.json +939 -0
- package/kernel/plugins/tasks/src/api.ts +212 -0
- package/kernel/plugins/tasks/src/client.tsx +23 -0
- package/kernel/plugins/tasks/src/data/parse.ts +544 -0
- package/kernel/plugins/tasks/src/data/task-id.ts +56 -0
- package/kernel/plugins/tasks/src/data/todo-model.ts +795 -0
- package/kernel/plugins/tasks/src/index.ts +34 -0
- package/kernel/plugins/tasks/src/manifest.ts +7 -0
- package/kernel/plugins/tasks/src/pages/task-detail.tsx +48 -0
- package/kernel/plugins/tasks/src/pages/task-list.tsx +88 -0
- package/kernel/plugins/tasks/src/server.ts +447 -0
- package/kernel/plugins/tasks/src/styles.css +9 -0
- package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +372 -0
- package/kernel/plugins/tasks/src/ui/error-details.tsx +78 -0
- package/kernel/plugins/tasks/src/ui/task-page.tsx +392 -0
- package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +36 -0
- package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +66 -0
- package/kernel/plugins/tasks/src/ui/todo-item.tsx +494 -0
- package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +60 -0
- package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +48 -0
- package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +106 -0
- package/kernel/plugins/tasks/test/api.test.mjs +99 -0
- package/kernel/plugins/tasks/test/folder-sources.test.mjs +46 -0
- package/kernel/plugins/tasks/test/package.test.mjs +54 -0
- package/kernel/plugins/tasks/test/parse.test.mjs +225 -0
- package/kernel/plugins/tasks/test/server.test.mjs +386 -0
- package/kernel/plugins/tasks/tsconfig.json +17 -0
- package/node_modules/@agentclientprotocol/sdk/LICENSE +191 -0
- package/node_modules/@agentclientprotocol/sdk/README.md +70 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.d.ts +1835 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.js +1885 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.test.js +5036 -0
- package/node_modules/@agentclientprotocol/sdk/dist/acp.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.d.ts +82 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.js +428 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.test.js +470 -0
- package/node_modules/@agentclientprotocol/sdk/dist/connection.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.d.ts +26 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.js +96 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.test.js +77 -0
- package/node_modules/@agentclientprotocol/sdk/dist/cookie-store.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/agent.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/agent.js +232 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/agent.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/client.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/client.js +132 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/client.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/dual-version-agent.d.ts +9 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/dual-version-agent.js +221 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/dual-version-agent.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-client.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-client.js +86 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-client.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-server.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-server.js +112 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/http-server.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/ws-client.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/ws-client.js +88 -0
- package/node_modules/@agentclientprotocol/sdk/dist/examples/ws-client.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.d.ts +33 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.js +435 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.test.js +1380 -0
- package/node_modules/@agentclientprotocol/sdk/dist/http-stream.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.d.ts +603 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js +1064 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.test.js +851 -0
- package/node_modules/@agentclientprotocol/sdk/dist/jsonrpc.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.d.ts +22 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.js +64 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.test.js +45 -0
- package/node_modules/@agentclientprotocol/sdk/dist/line-buffer.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.d.ts +17 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.js +426 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.test.js +499 -0
- package/node_modules/@agentclientprotocol/sdk/dist/node-adapter.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.d.ts +37 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.js +474 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.test.js +535 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol-router.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.d.ts +11 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.js +57 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.test.js +73 -0
- package/node_modules/@agentclientprotocol/sdk/dist/protocol.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/guards.gen.d.ts +199 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/guards.gen.js +211 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/guards.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/index.d.ts +51 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/index.js +52 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/index.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/types.gen.d.ts +6118 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/types.gen.js +3 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/types.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.d.ts +14160 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.js +3066 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.d.ts +30 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js +98 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.test.js +93 -0
- package/node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-permission.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-permission.test.js +261 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-permission.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-session-sse.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-session-sse.test.js +490 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-session-sse.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.d.ts +2 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.js +104 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.test.js +52 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-sse.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-websocket-upgrade.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-websocket-upgrade.test.js +946 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server-websocket-upgrade.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.d.ts +81 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.js +380 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.test.js +1082 -0
- package/node_modules/@agentclientprotocol/sdk/dist/server.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.d.ts +4 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.js +91 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.test.js +126 -0
- package/node_modules/@agentclientprotocol/sdk/dist/sse.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.d.ts +35 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.js +106 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.test.js +206 -0
- package/node_modules/@agentclientprotocol/sdk/dist/stream.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/streams.d.ts +8 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/streams.js +51 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/streams.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-agent.d.ts +24 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-agent.js +163 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-agent.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-http-server.d.ts +9 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-http-server.js +74 -0
- package/node_modules/@agentclientprotocol/sdk/dist/test-support/test-http-server.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.d.ts +806 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.js +1183 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.test.js +512 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/acp.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/guards.gen.d.ts +954 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/guards.gen.js +1035 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/guards.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/index.d.ts +42 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/index.js +43 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/index.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/types.gen.d.ts +6146 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/types.gen.js +3 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/types.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/zod.gen.d.ts +30552 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/zod.gen.js +3204 -0
- package/node_modules/@agentclientprotocol/sdk/dist/v2/schema/zod.gen.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-server.d.ts +14 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-server.js +358 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-server.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.d.ts +54 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.js +246 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.test.js +833 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-stream.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.d.ts +13 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.js +78 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.test.d.ts +1 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.test.js +42 -0
- package/node_modules/@agentclientprotocol/sdk/dist/ws-utils.test.js.map +1 -0
- package/node_modules/@agentclientprotocol/sdk/package.json +105 -0
- package/node_modules/@agentclientprotocol/sdk/schema/schema.json +8819 -0
- package/node_modules/@agentclientprotocol/sdk/schema/v2/schema.unstable.json +10098 -0
- package/package.json +52 -6
- package/web/assets/{abnfDiagram-VRR7QNED-Nfq-O04D.js → abnfDiagram-VRR7QNED-Bgfb1nEB.js} +1 -1
- package/web/assets/app-DoGr2Zi7.js +2 -0
- package/web/assets/app-options-D-RJiQ-X.js +25 -0
- package/web/assets/app-view-header-BLvLq02T.js +1 -0
- package/web/assets/arc-Dk_KI36B.js +1 -0
- package/web/assets/{architectureDiagram-ZJ3FMSHR-qhRwPNcQ.js → architectureDiagram-ZJ3FMSHR-NR_KhRCf.js} +1 -1
- package/web/assets/ask-tray-TzeTcO6-.js +14 -0
- package/web/assets/{blockDiagram-677ZJIJ3-C56P3bGu.js → blockDiagram-677ZJIJ3-CkLkwx9C.js} +1 -1
- package/web/assets/button-C6arH7zt.js +1 -0
- package/web/assets/{c4Diagram-LMCZKHZV-Ey1M72zD.js → c4Diagram-LMCZKHZV-CFCUH8e_.js} +1 -1
- package/web/assets/channel-uMEjV8qc.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-a6isk9VU.js → chunk-2Q5K7J3B-B_BPLWsW.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-uy4kdSLL.js → chunk-32BRIVSS-B1VB1hOy.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-oj2sBFd7.js → chunk-5VM5RSS4-KFcYr8Co.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-Bzl1ukAi.js → chunk-EX3LRPZG-CpBX3kuK.js} +3 -3
- package/web/assets/{chunk-JWPE2WC7-sUph7I_t.js → chunk-JWPE2WC7-BPSl40wG.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-C0ERSuVK.js → chunk-MOJQB5TN-D2RcYmoU.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-Dyw1Hfwp.js → chunk-RYQCIY6F-m7Gyn-t3.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-DnSz22rb.js → chunk-V7JOEXUC-TDvdopxS.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-Bp2SNel7.js → chunk-VR4S4FIN-DZTsG51a.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-Dqtar746.js → chunk-XXDRQBXY-Dp0--RE2.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +1 -0
- package/web/assets/client-C6Nxdfif.js +2 -0
- package/web/assets/client-CXYfBko5.js +17 -0
- package/web/assets/client-CoKtOq-X.js +7 -0
- package/web/assets/client-DyRQz5RU.js +53 -0
- package/web/assets/client-OY6HUzuD.js +98 -0
- package/web/assets/client-YOYWZIFi.js +34 -0
- package/web/assets/client-j2kQmxsO.js +22 -0
- package/web/assets/command-BugZBGXE.js +38 -0
- package/web/assets/copy-context-C0Uqsp-3.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-Dx1VqMjj.js → cose-bilkent-JH36ORCC-CPu3PI8h.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-SjhCWmIV.js → cynefin-VYW2F7L2-DWxftYAm.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-Dvqz2594.js → cynefinDiagram-TSTJHNR4-DsmN2V-p.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-Ju2m2qXt.js → dagre-VKFMJZFB-COEbApyY.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-DsHKTt0k.js → diagram-FQU43EPY-0O9WGWKB.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-DWHAcLkJ.js → diagram-G47NLZAW-CutEdMVh.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-uUMz46ZD.js → diagram-NH7WQ7WH-C9KZc3B2.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-BRjVzjdp.js → diagram-OA4YK3LP-D8kkPXbY.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-Cb-FhBpQ.js → diagram-WEI45ONY-_YqiTaGP.js} +1 -1
- package/web/assets/document-Dgt5eZFj.js +19 -0
- package/web/assets/{ebnfDiagram-CCIWWBDH-IhhxX3IB.js → ebnfDiagram-CCIWWBDH-JO-zQh6g.js} +1 -1
- package/web/assets/{entities-DUnx74kH.js → entities-C3wz7FCx.js} +12 -12
- package/web/assets/{erDiagram-Q63AITRT-D1frgeWf.js → erDiagram-Q63AITRT-9UjQwJ4P.js} +1 -1
- package/web/assets/file-viewer-DZJ8nYnl.js +1 -0
- package/web/assets/{flowDiagram-23GEKE2U-BiPPM-FY.js → flowDiagram-23GEKE2U-Ca08tnYM.js} +5 -5
- package/web/assets/folder-image-BfGgxo7i.js +1 -0
- package/web/assets/folder-landing-qUKBCnG-.js +54 -0
- package/web/assets/folder-list-BfFjv7rR.js +1 -0
- package/web/assets/folder-metadata-DCw8xzHk.js +2 -0
- package/web/assets/folder-mobile-bar-Ubz4babf.js +1 -0
- package/web/assets/folder-plugin-view-DsWR1zmQ.js +6 -0
- package/web/assets/{ganttDiagram-NO4QXBWP-CmEOlHD7.js → ganttDiagram-NO4QXBWP-KnHzX5W3.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-tTjcpZpU.js → gitGraphDiagram-IHSO6WYX-Cm8woNtK.js} +1 -1
- package/web/assets/index-BaRnbYRw.js +1 -0
- package/web/assets/index-BexmLxIP.css +1 -0
- package/web/assets/index-Bp9DidgD.js +1 -0
- package/web/assets/{index-eL1k96k8.js → index-CCXE8zc9.js} +1 -1
- package/web/assets/index-CNyy98F8.js +2 -0
- package/web/assets/{index-DmrKjrlM.js → index-CXhBn-ar.js} +1 -1
- package/web/assets/index-DDirZMgx.js +1 -0
- package/web/assets/{infoDiagram-FWYZ7A6U-Ok2sdbc1.js → infoDiagram-FWYZ7A6U-yyqmUtIb.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-kPnM5psX.js → ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js} +4 -4
- package/web/assets/{journeyDiagram-5HDEW3XC-BkoT0-45.js → journeyDiagram-5HDEW3XC-BKuw06HM.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-xnm_eFoU.js → kanban-definition-HUTT4EX6-n0010rmQ.js} +8 -8
- package/web/assets/{linear-CLZpgLH-.js → linear-C0d0lT8O.js} +1 -1
- package/web/assets/linked-session-header-BkEweU0Z.js +3 -0
- package/web/assets/{markdown-njUwQKsR.js → markdown-Bw9RgUGR.js} +9 -9
- package/web/assets/{mermaid.core-Bvxj3RoN.js → mermaid.core-BDVbShyO.js} +6 -6
- package/web/assets/metadata-KV0dpp4G.js +1 -0
- package/web/assets/{mindmap-definition-LN4V7U3C-42Uoox79.js → mindmap-definition-LN4V7U3C--_0ks3GF.js} +1 -1
- package/web/assets/note-card-DBfX6gW1.js +6 -0
- package/web/assets/{pegDiagram-2B236MQR-B-GZCw3w.js → pegDiagram-2B236MQR-CBoNIpKR.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-DRmmssIB.js → pieDiagram-ENE6RG2P-MA5tkYh5.js} +3 -3
- package/web/assets/popover-DBD7FF-W.js +9 -0
- package/web/assets/{project-search-dialog-B730oZ1S.js → project-search-dialog-DM1IkSZu.js} +6 -6
- package/web/assets/{quadrantDiagram-ABIIQ3AL-BfhVQ7V9.js → quadrantDiagram-ABIIQ3AL-CWT1ryqF.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-DxKx7XRp.js → railroadDiagram-RFXS5EU6-ZiLB5FGi.js} +1 -1
- package/web/assets/{react-DZzLHL-l.js → react-B9jn2M18.js} +2 -2
- package/web/assets/{requirementDiagram-TGXJPOKE-NUzj9fw1.js → requirementDiagram-TGXJPOKE-CQq9uneq.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-Cy9OMnl-.js → sankeyDiagram-HTMAVEWB-qDG-0JqI.js} +1 -1
- package/web/assets/search-DNrQA5fF.js +2 -0
- package/web/assets/select-D8cqNgcp.js +30 -0
- package/web/assets/selection-popup-DmtTeRs2.js +7 -0
- package/web/assets/{sequenceDiagram-DBY2YBRQ-CBNE9mzn.js → sequenceDiagram-DBY2YBRQ-CiApurLO.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-S4HhfX0n.js → sizeCapture-X5ZJPWSS-DZSR5QXm.js} +1 -1
- package/web/assets/stateDiagram-2N3HPSRC-CjJJR9_z.js +1 -0
- package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +1 -0
- package/web/assets/{swimlanes-5IMT3BWC-DJ2aLWal.js → swimlanes-5IMT3BWC-CKmo1sg6.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +8 -0
- package/web/assets/tanstack-YzX_Mi37.js +3 -0
- package/web/assets/{timeline-definition-FHXFAJF6-vFDUVPCX.js → timeline-definition-FHXFAJF6-D-NMwS3y.js} +1 -1
- package/web/assets/{use-folder-filter-BbTUlXgG.js → use-folder-filter-LQyXns5Q.js} +1 -1
- package/web/assets/{utils-CwHGE3BB.js → utils-DCaHk0Gm.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-AsnhK2zW.js → vennDiagram-L72KCM5P-CfL6LBWw.js} +1 -1
- package/web/assets/view-context-gyDl_p2V.js +229 -0
- package/web/assets/viewer-capabilities-Bpp8Uvcg.js +1 -0
- package/web/assets/{wardleyDiagram-EHGQE667-Cj1wFbNV.js → wardleyDiagram-EHGQE667-DgldMxaj.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-Bbvnutsm.js → xychartDiagram-FW5EYKEG-CIoAIFX8.js} +1 -1
- package/web/favicon.svg +6 -0
- package/web/index.html +5 -4
- package/web/assets/app-CPSmsokP.js +0 -2
- package/web/assets/app-options-XEWvevsz.js +0 -25
- package/web/assets/app-view-header-BKZ90ToF.js +0 -1
- package/web/assets/arc-DbpbZvCt.js +0 -1
- package/web/assets/arrow-left-CFeHb-Z1.js +0 -1
- package/web/assets/ask-tray-D2YHtbPj.js +0 -14
- package/web/assets/button-BJ7z-ZA7.js +0 -1
- package/web/assets/calendar-days-DWh2XMO2.js +0 -1
- package/web/assets/channel-dSRp_qTo.js +0 -1
- package/web/assets/chevron-down-C5oRtqbX.js +0 -1
- package/web/assets/chevron-right-CsPtvh8C.js +0 -1
- package/web/assets/chevron-up-DjpU6Pyv.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-B7B2zLzM.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-B7B2zLzM.js +0 -1
- package/web/assets/client-CAudjYV9.js +0 -34
- package/web/assets/client-Dn9-_Gm_.js +0 -14
- package/web/assets/client-Dxrf2tyq.js +0 -102
- package/web/assets/client-aFI2M4pE.js +0 -53
- package/web/assets/collection-icon-TbOVyORG.js +0 -1
- package/web/assets/collection-page-Du6FKkuU.js +0 -10
- package/web/assets/command-C_g5E1Wx.js +0 -38
- package/web/assets/copy-Ikmr6Iq2.js +0 -1
- package/web/assets/copy-context-Cl1TE2PJ.js +0 -1
- package/web/assets/document-DcjNSJCk.js +0 -2
- package/web/assets/external-link-BXmSXqqF.js +0 -1
- package/web/assets/file-renderer-BRZTrYx8.js +0 -19
- package/web/assets/file-text-CiiSsCDq.js +0 -1
- package/web/assets/file-viewer-C1wAeVDK.js +0 -1
- package/web/assets/folder-image-AXBrHUcU.js +0 -1
- package/web/assets/folder-landing-BhRg7hwn.js +0 -54
- package/web/assets/folder-list-rIdszVde.js +0 -1
- package/web/assets/folder-metadata-puTC5QqJ.js +0 -2
- package/web/assets/folder-mobile-bar-DjjRQo3T.js +0 -1
- package/web/assets/folder-plugin-view-BU_kzR8j.js +0 -6
- package/web/assets/index-DS2Wmd9I.css +0 -1
- package/web/assets/index-DgqzSeIR.js +0 -1
- package/web/assets/index-DnlTDqaa.js +0 -1
- package/web/assets/index-DztTMDFz.js +0 -2
- package/web/assets/index-kY75qc96.js +0 -1
- package/web/assets/index-p38i_yyY.js +0 -1
- package/web/assets/link-2-BWKA6t--.js +0 -1
- package/web/assets/link-DC_1Z6Yy.js +0 -11
- package/web/assets/linked-session-header-DJYWZ_-q.js +0 -3
- package/web/assets/mail-2rCdIFul.js +0 -1
- package/web/assets/markdown-title-dncAYYiP.js +0 -131
- package/web/assets/notes-page-DIW6rgJp.js +0 -10
- package/web/assets/pencil-8cobiSSq.js +0 -1
- package/web/assets/plus-BHV2wJr7.js +0 -1
- package/web/assets/popover-Cmmgj-MJ.js +0 -9
- package/web/assets/search-CvlYUkN6.js +0 -2
- package/web/assets/select-1SvaKQsS.js +0 -30
- package/web/assets/selection-popup-ntjycEVh.js +0 -7
- package/web/assets/sparkles-CBhGREdc.js +0 -1
- package/web/assets/stateDiagram-2N3HPSRC-BEw1Mheu.js +0 -1
- package/web/assets/stateDiagram-v2-6OUMAXLB-BHtjl1iD.js +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-Z362aroZ.js +0 -8
- package/web/assets/tanstack-CD46mJkU.js +0 -1
- package/web/assets/view-context-D-fh9AbH.js +0 -81
- package/web/assets/viewer-capabilities-CROIaoqh.js +0 -1
- package/web/assets/x-BUeE--I4.js +0 -1
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
import { execFile as execFileCb } from "node:child_process"
|
|
2
|
+
import { constants } from "node:fs"
|
|
3
|
+
import { access, realpath } from "node:fs/promises"
|
|
4
|
+
import { homedir } from "node:os"
|
|
5
|
+
import { delimiter, isAbsolute, resolve as resolvePath, sep } from "node:path"
|
|
6
|
+
import { promisify } from "node:util"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Injectable subprocess runner. Production uses `execFile`; tests inject a
|
|
10
|
+
* fake that records exact arguments and controls output/errors. The options
|
|
11
|
+
* mirror execFile's accepted shape so the real and fake implementations can
|
|
12
|
+
* share one signature.
|
|
13
|
+
*/
|
|
14
|
+
export type ExecFileLike = (
|
|
15
|
+
file: string,
|
|
16
|
+
args: string[],
|
|
17
|
+
options: {
|
|
18
|
+
cwd: string
|
|
19
|
+
timeout: number
|
|
20
|
+
maxBuffer: number
|
|
21
|
+
windowsHide?: boolean
|
|
22
|
+
signal?: AbortSignal
|
|
23
|
+
},
|
|
24
|
+
) => Promise<{ stdout: string; stderr: string }>
|
|
25
|
+
|
|
26
|
+
const defaultExecFileLike = promisify(execFileCb) as ExecFileLike
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Failure code for a MailOS command. `timeout` when the child was killed by
|
|
30
|
+
* the deadline, `not-found` when the CLI reported the target missing,
|
|
31
|
+
* `aborted` when the caller cancelled (e.g. client disconnect), `failed` for
|
|
32
|
+
* every other non-zero exit.
|
|
33
|
+
*/
|
|
34
|
+
export type MailosCommandFailure =
|
|
35
|
+
"timeout" | "not-found" | "aborted" | "failed"
|
|
36
|
+
|
|
37
|
+
export class MailosCommandError extends Error {
|
|
38
|
+
readonly code: MailosCommandFailure
|
|
39
|
+
readonly timedOut: boolean
|
|
40
|
+
readonly aborted: boolean
|
|
41
|
+
readonly exitCode: number | null
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
code: MailosCommandFailure,
|
|
45
|
+
message: string,
|
|
46
|
+
details: {
|
|
47
|
+
exitCode?: number | null
|
|
48
|
+
timedOut?: boolean
|
|
49
|
+
aborted?: boolean
|
|
50
|
+
} = {},
|
|
51
|
+
) {
|
|
52
|
+
super(message)
|
|
53
|
+
this.name = "MailosCommandError"
|
|
54
|
+
this.code = code
|
|
55
|
+
this.timedOut = details.timedOut ?? code === "timeout"
|
|
56
|
+
this.aborted = details.aborted ?? code === "aborted"
|
|
57
|
+
this.exitCode = details.exitCode ?? null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function classifyExecError(error: unknown): MailosCommandError {
|
|
62
|
+
if (error instanceof MailosCommandError) return error
|
|
63
|
+
if (!(error instanceof Error)) {
|
|
64
|
+
return new MailosCommandError("failed", "MailOS command failed")
|
|
65
|
+
}
|
|
66
|
+
if (error.name === "AbortError") {
|
|
67
|
+
return new MailosCommandError("aborted", "MailOS command cancelled")
|
|
68
|
+
}
|
|
69
|
+
const execError = error as Error & {
|
|
70
|
+
code?: string | number
|
|
71
|
+
killed?: boolean
|
|
72
|
+
}
|
|
73
|
+
if (execError.killed) {
|
|
74
|
+
return new MailosCommandError("timeout", "MailOS command timed out", {
|
|
75
|
+
timedOut: true,
|
|
76
|
+
exitCode: typeof execError.code === "number" ? execError.code : null,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
return new MailosCommandError("failed", "MailOS command failed to complete", {
|
|
80
|
+
exitCode: typeof execError.code === "number" ? execError.code : null,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Central subprocess lifecycle: a hard timeout kills the child, an optional
|
|
86
|
+
* AbortSignal (client disconnect) cancels it, and errors are converted into
|
|
87
|
+
* redacted `MailosCommandError` values that never carry command output
|
|
88
|
+
* (credentials or message bodies cannot leak into error messages or logs).
|
|
89
|
+
*/
|
|
90
|
+
export async function runMailos(
|
|
91
|
+
execFile: ExecFileLike,
|
|
92
|
+
mailosBin: string,
|
|
93
|
+
args: string[],
|
|
94
|
+
options: {
|
|
95
|
+
cwd: string
|
|
96
|
+
timeoutMs: number
|
|
97
|
+
maxBufferBytes?: number
|
|
98
|
+
signal?: AbortSignal
|
|
99
|
+
},
|
|
100
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
101
|
+
if (options.signal?.aborted) {
|
|
102
|
+
throw new MailosCommandError("aborted", "MailOS command cancelled")
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
return await execFile(mailosBin, args, {
|
|
106
|
+
cwd: options.cwd,
|
|
107
|
+
timeout: options.timeoutMs,
|
|
108
|
+
maxBuffer: options.maxBufferBytes ?? 10 * 1024 * 1024,
|
|
109
|
+
windowsHide: true,
|
|
110
|
+
signal: options.signal,
|
|
111
|
+
})
|
|
112
|
+
} catch (error) {
|
|
113
|
+
const classified = classifyExecError(error)
|
|
114
|
+
if (options.signal?.aborted && classified.code !== "aborted") {
|
|
115
|
+
throw new MailosCommandError("aborted", "MailOS command cancelled")
|
|
116
|
+
}
|
|
117
|
+
throw classified
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type MailosServiceOptions = {
|
|
122
|
+
execFile?: ExecFileLike
|
|
123
|
+
mailosBin?: string
|
|
124
|
+
/** Test seam: MailOS's global draft dir (defaults to ~/.email/drafts). */
|
|
125
|
+
globalDraftDir?: string
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type MailosIdentity = {
|
|
129
|
+
from: string | null
|
|
130
|
+
name: string | null
|
|
131
|
+
/** False when the CLI could not resolve an identity (caller may hide the row). */
|
|
132
|
+
ok: boolean
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type ConversationMessage = {
|
|
136
|
+
body: string
|
|
137
|
+
date: string | null
|
|
138
|
+
from: string | null
|
|
139
|
+
id: string
|
|
140
|
+
subject: string | null
|
|
141
|
+
to: string | null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export type ConversationOutcome =
|
|
145
|
+
"empty" | "ok" | "partial" | "not-found" | "timeout"
|
|
146
|
+
|
|
147
|
+
export type ConversationResult = {
|
|
148
|
+
items: ConversationMessage[]
|
|
149
|
+
missing: string[]
|
|
150
|
+
outcome: ConversationOutcome
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export type SendPreviewResult = {
|
|
154
|
+
dryRun: true
|
|
155
|
+
output: string
|
|
156
|
+
revision: string
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export type SendResult = {
|
|
160
|
+
dryRun: false
|
|
161
|
+
output: string
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type SendFailureReason =
|
|
165
|
+
| "revision-match"
|
|
166
|
+
| "contract"
|
|
167
|
+
| "command"
|
|
168
|
+
| "invalid-draft"
|
|
169
|
+
| "unsupported-draft-dir"
|
|
170
|
+
|
|
171
|
+
export class MailSendFailure extends Error {
|
|
172
|
+
readonly reason: SendFailureReason
|
|
173
|
+
|
|
174
|
+
constructor(reason: SendFailureReason, message: string) {
|
|
175
|
+
super(message)
|
|
176
|
+
this.name = "MailSendFailure"
|
|
177
|
+
this.reason = reason
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function isExecutable(path: string) {
|
|
182
|
+
try {
|
|
183
|
+
await access(path, constants.X_OK)
|
|
184
|
+
return true
|
|
185
|
+
} catch {
|
|
186
|
+
return false
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function pathIsWithin(child: string, parent: string) {
|
|
191
|
+
const rel = child.startsWith(parent) ? child.slice(parent.length) : null
|
|
192
|
+
if (!rel) return false
|
|
193
|
+
return rel === "" || rel.startsWith(sep)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the MailOS binary, refusing to pick a binary that lives inside the
|
|
198
|
+
* working folder so drafts cannot point commands at an attacker-controlled
|
|
199
|
+
* executable.
|
|
200
|
+
*/
|
|
201
|
+
export async function resolveMailosBinary({
|
|
202
|
+
cwd,
|
|
203
|
+
}: {
|
|
204
|
+
cwd: string
|
|
205
|
+
}): Promise<string> {
|
|
206
|
+
const preferred = resolvePath(homedir(), ".local", "bin", "mailos")
|
|
207
|
+
if (await isExecutable(preferred)) return preferred
|
|
208
|
+
|
|
209
|
+
const pathEnv = process.env.PATH ?? ""
|
|
210
|
+
for (const dir of pathEnv.split(delimiter)) {
|
|
211
|
+
const trimmed = dir.trim()
|
|
212
|
+
if (!trimmed) continue
|
|
213
|
+
if (!isAbsolute(trimmed)) continue
|
|
214
|
+
|
|
215
|
+
const candidate = resolvePath(trimmed, "mailos")
|
|
216
|
+
if (!isAbsolute(candidate)) continue
|
|
217
|
+
if (pathIsWithin(candidate, cwd)) continue
|
|
218
|
+
|
|
219
|
+
if (await isExecutable(candidate)) return candidate
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
throw new Error(
|
|
223
|
+
"MailOS binary not found. Expected ~/.local/bin/mailos or an absolute PATH entry.",
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Bounded per-(folder, id) in-flight and success cache. The scope key embeds
|
|
229
|
+
* the working folder so caches never cross account/folder scope, in-flight
|
|
230
|
+
* reads are deduplicated, and successful reads are held for the conversation
|
|
231
|
+
* window instead of re-invoking the CLI on every detail view.
|
|
232
|
+
*
|
|
233
|
+
* Cancellation is subscriber-scoped: each caller's AbortSignal is registered
|
|
234
|
+
* on the shared in-flight entry; one canceled consumer only removes its own
|
|
235
|
+
* subscription, and the shared child is aborted only when the *last*
|
|
236
|
+
* subscriber cancels. A canceled consumer therefore never kills a concurrent
|
|
237
|
+
* consumer of the same (cwd, id), while a fully-disconnected request still
|
|
238
|
+
* stops its children.
|
|
239
|
+
*/
|
|
240
|
+
type ConversationMessageCacheEntry = {
|
|
241
|
+
message: ConversationMessage
|
|
242
|
+
at: number
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type ConversationInFlight = {
|
|
246
|
+
promise: Promise<ConversationMessage>
|
|
247
|
+
controller: AbortController
|
|
248
|
+
signals: Map<AbortSignal, () => void>
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
type ConversationCache = {
|
|
252
|
+
inFlight: Map<string, ConversationInFlight>
|
|
253
|
+
success: Map<string, ConversationMessageCacheEntry>
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const conversationCache: ConversationCache = {
|
|
257
|
+
inFlight: new Map(),
|
|
258
|
+
success: new Map(),
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export const conversationLimits = {
|
|
262
|
+
maxReferences: 12,
|
|
263
|
+
// MailOS `read` is an IMAP/notmuch operation; real-world successful reads
|
|
264
|
+
// are measured at 22-26s, so the per-read cap sits above that envelope
|
|
265
|
+
// (60s) while the whole conversation view stays bounded at 75s. There is
|
|
266
|
+
// deliberately no retry loop: slow-but-successful reads must not be
|
|
267
|
+
// classified as failures.
|
|
268
|
+
perReadTimeoutMs: 60_000,
|
|
269
|
+
totalBudgetMs: 75_000,
|
|
270
|
+
concurrency: 3,
|
|
271
|
+
successCacheSize: 40,
|
|
272
|
+
// Successful reads are only reused within the conversation window; after
|
|
273
|
+
// this the CLI is re-invoked so actions (send/archive/delete) never stay
|
|
274
|
+
// masked by a stale server-side copy.
|
|
275
|
+
successTtlMs: 60_000,
|
|
276
|
+
} as const
|
|
277
|
+
|
|
278
|
+
export function resetConversationCache() {
|
|
279
|
+
conversationCache.inFlight.clear()
|
|
280
|
+
conversationCache.success.clear()
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function scopeKey(cwd: string, id: string) {
|
|
284
|
+
return `${cwd}\u0000${id}`
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function parseConversationMarkdown(
|
|
288
|
+
id: string,
|
|
289
|
+
output: string,
|
|
290
|
+
): ConversationMessage {
|
|
291
|
+
const subject = /^#\s+(.+)$/m.exec(output)?.[1]?.trim() ?? null
|
|
292
|
+
const from =
|
|
293
|
+
/^\*\*From:\*\*\s+(.+?)(?:\s{2,}|$)/m.exec(output)?.[1]?.trim() ?? null
|
|
294
|
+
const to =
|
|
295
|
+
/^\*\*To:\*\*\s+(.+?)(?:\s{2,}|$)/m.exec(output)?.[1]?.trim() ?? null
|
|
296
|
+
const date =
|
|
297
|
+
/^\*\*Date:\*\*\s+(.+?)(?:\s{2,}|$)/m.exec(output)?.[1]?.trim() ?? null
|
|
298
|
+
const separator = output.indexOf("\n---\n")
|
|
299
|
+
const body = (separator >= 0 ? output.slice(separator + 5) : output).trim()
|
|
300
|
+
return { body, date, from, id, subject, to }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Structured, account-scoped MailOS access. Every command is an explicit
|
|
305
|
+
* fixed template over a canonical draft identity; nothing from the client is
|
|
306
|
+
* ever formatted into the command line. Identity/conversation/send/archive
|
|
307
|
+
* live here instead of the web plugin so the basic draft reader (`node.ts`)
|
|
308
|
+
* never needs the CLI.
|
|
309
|
+
*/
|
|
310
|
+
export type SendDraftOptions = {
|
|
311
|
+
/**
|
|
312
|
+
* The exact draft directory the client authorized (its mailDir). MailOS
|
|
313
|
+
* resolves draft ids against the global ~/.email/drafts by default; passing
|
|
314
|
+
* this makes send/preview target the file already read by list/detail,
|
|
315
|
+
* never a same-named draft elsewhere.
|
|
316
|
+
*/
|
|
317
|
+
draftDir: string
|
|
318
|
+
signal?: AbortSignal
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Internal parameter shape: the draft dir may be absent until validated. */
|
|
322
|
+
type SendDraftParams = {
|
|
323
|
+
draftDir?: string
|
|
324
|
+
signal?: AbortSignal
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function requireDraftDir(draftDir: string | undefined) {
|
|
328
|
+
if (!draftDir || !isAbsolute(draftDir)) {
|
|
329
|
+
throw new MailSendFailure(
|
|
330
|
+
"invalid-draft",
|
|
331
|
+
"A send draft directory (the authorized mailDir) is required",
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
return draftDir
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function sameCanonicalDir(left: string, right: string) {
|
|
338
|
+
const canonical = async (value: string) =>
|
|
339
|
+
realpath(value).catch(() => resolvePath(value))
|
|
340
|
+
return Promise.all([canonical(left), canonical(right)]).then(
|
|
341
|
+
([leftReal, rightReal]) => leftReal === rightReal,
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** The single directory `mailos drafts archive <id>` can address. */
|
|
346
|
+
export function mailosGlobalDraftDir() {
|
|
347
|
+
return resolvePath(homedir(), ".email", "drafts")
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function createMailosService(options: MailosServiceOptions = {}) {
|
|
351
|
+
const execFile = options.execFile ?? defaultExecFileLike
|
|
352
|
+
const mailosBin = options.mailosBin
|
|
353
|
+
const globalDraftDir = options.globalDraftDir
|
|
354
|
+
|
|
355
|
+
async function binary(cwd: string) {
|
|
356
|
+
if (mailosBin) {
|
|
357
|
+
if (!isAbsolute(mailosBin)) {
|
|
358
|
+
throw new Error("mailosBin must be an absolute path")
|
|
359
|
+
}
|
|
360
|
+
if (pathIsWithin(mailosBin, cwd)) {
|
|
361
|
+
throw new Error("mailosBin cannot live inside the working folder")
|
|
362
|
+
}
|
|
363
|
+
return mailosBin
|
|
364
|
+
}
|
|
365
|
+
return resolveMailosBinary({ cwd })
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function normalizeIdentityValue(value: string | null): string | null {
|
|
369
|
+
return value && value !== "(not set)" ? value : null
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function identity(cwd: string): Promise<MailosIdentity> {
|
|
373
|
+
try {
|
|
374
|
+
const bin = await binary(cwd)
|
|
375
|
+
const { stdout, stderr } = await runMailos(execFile, bin, ["whoami"], {
|
|
376
|
+
cwd,
|
|
377
|
+
timeoutMs: 15_000,
|
|
378
|
+
})
|
|
379
|
+
const output = [stdout, stderr].filter(Boolean).join("\n")
|
|
380
|
+
const from = normalizeIdentityValue(
|
|
381
|
+
/^Effective From:[ \t]*([^\r\n]+)$/im.exec(output)?.[1]?.trim() ?? null,
|
|
382
|
+
)
|
|
383
|
+
const name = normalizeIdentityValue(
|
|
384
|
+
/^From Name:[ \t]*([^\r\n]+)$/im.exec(output)?.[1]?.trim() ?? null,
|
|
385
|
+
)
|
|
386
|
+
return { from, name, ok: Boolean(from ?? name) }
|
|
387
|
+
} catch {
|
|
388
|
+
// Sender resolution is best-effort lazy enrichment; never fail the row.
|
|
389
|
+
return { from: null, name: null, ok: false }
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Resolved markdown signature for a folder, or null when the folder has no
|
|
395
|
+
* signature configured (or the CLI cannot resolve one). Best-effort exactly
|
|
396
|
+
* like `identity`: a failing or empty `mailos sig` never fails the draft
|
|
397
|
+
* preview, it just leaves the signature section empty.
|
|
398
|
+
*/
|
|
399
|
+
async function signature(
|
|
400
|
+
folder: string,
|
|
401
|
+
signal?: AbortSignal,
|
|
402
|
+
): Promise<string | null> {
|
|
403
|
+
try {
|
|
404
|
+
const bin = await binary(folder)
|
|
405
|
+
const { stdout } = await runMailos(execFile, bin, ["sig", folder], {
|
|
406
|
+
cwd: folder,
|
|
407
|
+
timeoutMs: 15_000,
|
|
408
|
+
signal,
|
|
409
|
+
})
|
|
410
|
+
const output = stdout.trim()
|
|
411
|
+
if (!output) return null
|
|
412
|
+
if (output.includes("(no signature configured)")) return null
|
|
413
|
+
if (output.includes("(signature is empty)")) return null
|
|
414
|
+
return output
|
|
415
|
+
} catch {
|
|
416
|
+
return null
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function readMessage(
|
|
421
|
+
cwd: string,
|
|
422
|
+
id: string,
|
|
423
|
+
signal?: AbortSignal,
|
|
424
|
+
): Promise<ConversationMessage> {
|
|
425
|
+
const bin = await binary(cwd)
|
|
426
|
+
const { stdout } = await runMailos(
|
|
427
|
+
execFile,
|
|
428
|
+
bin,
|
|
429
|
+
["read", id, "--markdown"],
|
|
430
|
+
{
|
|
431
|
+
cwd,
|
|
432
|
+
timeoutMs: conversationLimits.perReadTimeoutMs,
|
|
433
|
+
signal,
|
|
434
|
+
},
|
|
435
|
+
)
|
|
436
|
+
return parseConversationMarkdown(id, stdout)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function cachedRead(
|
|
440
|
+
cwd: string,
|
|
441
|
+
id: string,
|
|
442
|
+
signal?: AbortSignal,
|
|
443
|
+
): Promise<ConversationMessage> {
|
|
444
|
+
const key = scopeKey(cwd, id)
|
|
445
|
+
const cached = conversationCache.success.get(key)
|
|
446
|
+
if (cached) {
|
|
447
|
+
if (Date.now() - cached.at < conversationLimits.successTtlMs) {
|
|
448
|
+
return Promise.resolve(cached.message)
|
|
449
|
+
}
|
|
450
|
+
conversationCache.success.delete(key)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
let entry = conversationCache.inFlight.get(key)
|
|
454
|
+
if (!entry) {
|
|
455
|
+
const controller = new AbortController()
|
|
456
|
+
const started = readMessage(cwd, id, controller.signal)
|
|
457
|
+
const created: ConversationInFlight = {
|
|
458
|
+
promise: started,
|
|
459
|
+
controller,
|
|
460
|
+
signals: new Map(),
|
|
461
|
+
}
|
|
462
|
+
entry = created
|
|
463
|
+
conversationCache.inFlight.set(key, created)
|
|
464
|
+
void started
|
|
465
|
+
.then((message) => {
|
|
466
|
+
const success = conversationCache.success
|
|
467
|
+
if (success.size >= conversationLimits.successCacheSize) {
|
|
468
|
+
success.delete(success.keys().next().value as string)
|
|
469
|
+
}
|
|
470
|
+
success.set(key, { message, at: Date.now() })
|
|
471
|
+
})
|
|
472
|
+
.catch(() => {
|
|
473
|
+
// The failure is delivered to `started` consumers; only the cache
|
|
474
|
+
// bookkeeping chain observes it here and must swallow it.
|
|
475
|
+
})
|
|
476
|
+
.finally(() => {
|
|
477
|
+
conversationCache.inFlight.delete(key)
|
|
478
|
+
for (const [subscriber, onAbort] of created.signals) {
|
|
479
|
+
subscriber.removeEventListener("abort", onAbort)
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
}
|
|
483
|
+
const active = entry
|
|
484
|
+
if (signal) {
|
|
485
|
+
const onAbort = () => {
|
|
486
|
+
active.signals.delete(signal)
|
|
487
|
+
// Last subscriber cancel kills the shared child; any remaining
|
|
488
|
+
// subscriber keeps it alive and still receives the result.
|
|
489
|
+
if (active.signals.size === 0) active.controller.abort()
|
|
490
|
+
}
|
|
491
|
+
active.signals.set(signal, onAbort)
|
|
492
|
+
if (signal.aborted) onAbort()
|
|
493
|
+
else signal.addEventListener("abort", onAbort, { once: true })
|
|
494
|
+
}
|
|
495
|
+
// The shared child runs on its own controller. Each caller's own abort
|
|
496
|
+
// only races their individual wait: the caller stops waiting (their
|
|
497
|
+
// request rejects as aborted) while the shared child keeps running for
|
|
498
|
+
// any remaining subscribers — production requests therefore reuse the
|
|
499
|
+
// in-flight read AND still stop on client disconnect.
|
|
500
|
+
if (!signal) return active.promise
|
|
501
|
+
return new Promise<ConversationMessage>((resolveOuter, rejectOuter) => {
|
|
502
|
+
let settled = false
|
|
503
|
+
const settleRace = (value: ConversationMessage | Error) => {
|
|
504
|
+
if (settled) return
|
|
505
|
+
settled = true
|
|
506
|
+
signal.removeEventListener("abort", onCallerAbort)
|
|
507
|
+
if (value instanceof Error) rejectOuter(value)
|
|
508
|
+
else resolveOuter(value)
|
|
509
|
+
}
|
|
510
|
+
const onCallerAbort = () =>
|
|
511
|
+
settleRace(
|
|
512
|
+
new MailosCommandError("aborted", "MailOS command cancelled"),
|
|
513
|
+
)
|
|
514
|
+
active.promise.then(
|
|
515
|
+
(message) => settleRace(message),
|
|
516
|
+
(error: unknown) =>
|
|
517
|
+
settleRace(error instanceof Error ? error : new Error(String(error))),
|
|
518
|
+
)
|
|
519
|
+
signal.addEventListener("abort", onCallerAbort, { once: true })
|
|
520
|
+
if (signal.aborted) onCallerAbort()
|
|
521
|
+
})
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
async function conversation(
|
|
525
|
+
cwd: string,
|
|
526
|
+
references: string[],
|
|
527
|
+
signal?: AbortSignal,
|
|
528
|
+
): Promise<ConversationResult> {
|
|
529
|
+
const ids = [
|
|
530
|
+
...new Set(
|
|
531
|
+
references
|
|
532
|
+
.map((candidate) => candidate.trim())
|
|
533
|
+
.filter((candidate) => Boolean(candidate) && !/\s/.test(candidate)),
|
|
534
|
+
),
|
|
535
|
+
].slice(0, conversationLimits.maxReferences)
|
|
536
|
+
|
|
537
|
+
const items: ConversationMessage[] = []
|
|
538
|
+
const missing: string[] = []
|
|
539
|
+
if (!ids.length) return { items, missing, outcome: "empty" }
|
|
540
|
+
|
|
541
|
+
const deadline = Date.now() + conversationLimits.totalBudgetMs
|
|
542
|
+
let timedOut = false
|
|
543
|
+
const queued = ids.map((id) => ({ id, started: false, done: false }))
|
|
544
|
+
let nextIndex = 0
|
|
545
|
+
|
|
546
|
+
const worker = async () => {
|
|
547
|
+
while (nextIndex < queued.length) {
|
|
548
|
+
const slot = queued[nextIndex]
|
|
549
|
+
if (!slot) break
|
|
550
|
+
nextIndex += 1
|
|
551
|
+
slot.started = true
|
|
552
|
+
try {
|
|
553
|
+
const message = await cachedRead(cwd, slot.id, signal)
|
|
554
|
+
if (!items.some((item) => item.id === message.id)) {
|
|
555
|
+
items.push(message)
|
|
556
|
+
}
|
|
557
|
+
} catch (error) {
|
|
558
|
+
if (error instanceof MailosCommandError) {
|
|
559
|
+
if (error.timedOut) timedOut = true
|
|
560
|
+
if (error.aborted) throw error
|
|
561
|
+
}
|
|
562
|
+
missing.push(slot.id)
|
|
563
|
+
}
|
|
564
|
+
if (Date.now() >= deadline) {
|
|
565
|
+
timedOut = true
|
|
566
|
+
break
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const workers = Array.from(
|
|
572
|
+
{ length: Math.min(conversationLimits.concurrency, ids.length) },
|
|
573
|
+
() => worker(),
|
|
574
|
+
)
|
|
575
|
+
await Promise.all(workers)
|
|
576
|
+
|
|
577
|
+
if (timedOut) return { items, missing, outcome: "timeout" }
|
|
578
|
+
if (!items.length && missing.length === ids.length) {
|
|
579
|
+
return { items, missing, outcome: "not-found" }
|
|
580
|
+
}
|
|
581
|
+
if (missing.length > 0) return { items, missing, outcome: "partial" }
|
|
582
|
+
return { items, missing, outcome: "ok" }
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async function sendPreview(
|
|
586
|
+
cwd: string,
|
|
587
|
+
id: string,
|
|
588
|
+
options: SendDraftParams = {},
|
|
589
|
+
): Promise<SendPreviewResult> {
|
|
590
|
+
const draftDir = requireDraftDir(options.draftDir)
|
|
591
|
+
const bin = await binary(cwd)
|
|
592
|
+
const args = ["send", "draft", id, "--draft-dir", draftDir, "--preview"]
|
|
593
|
+
const { stdout, stderr } = await runMailos(execFile, bin, args, {
|
|
594
|
+
cwd,
|
|
595
|
+
timeoutMs: 30_000,
|
|
596
|
+
signal: options.signal,
|
|
597
|
+
})
|
|
598
|
+
const output = [stdout, stderr].filter(Boolean).join("\n")
|
|
599
|
+
const revision = /^Revision:\s*([a-f0-9]{64})\s*$/im.exec(output)?.[1]
|
|
600
|
+
if (!revision) {
|
|
601
|
+
throw new MailSendFailure(
|
|
602
|
+
"invalid-draft",
|
|
603
|
+
"MailOS did not return a revision; the draft is not sendable.",
|
|
604
|
+
)
|
|
605
|
+
}
|
|
606
|
+
return { dryRun: true, output, revision }
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
async function confirmSend(
|
|
610
|
+
cwd: string,
|
|
611
|
+
id: string,
|
|
612
|
+
revision: string,
|
|
613
|
+
options: SendDraftParams = {},
|
|
614
|
+
): Promise<SendResult> {
|
|
615
|
+
if (!/^[a-f0-9]{64}$/i.test(revision)) {
|
|
616
|
+
throw new MailSendFailure("revision-match", "Invalid draft revision")
|
|
617
|
+
}
|
|
618
|
+
const draftDir = requireDraftDir(options.draftDir)
|
|
619
|
+
const bin = await binary(cwd)
|
|
620
|
+
const args = [
|
|
621
|
+
"send",
|
|
622
|
+
"draft",
|
|
623
|
+
id,
|
|
624
|
+
"--draft-dir",
|
|
625
|
+
draftDir,
|
|
626
|
+
"--draft-revision",
|
|
627
|
+
revision,
|
|
628
|
+
"--delete-after=false",
|
|
629
|
+
]
|
|
630
|
+
const { stdout, stderr } = await runMailos(execFile, bin, args, {
|
|
631
|
+
cwd,
|
|
632
|
+
timeoutMs: 60_000,
|
|
633
|
+
signal: options.signal,
|
|
634
|
+
})
|
|
635
|
+
const output = [stdout, stderr].filter(Boolean).join("\n")
|
|
636
|
+
// MailOS refuses a single draft whose bytes changed after the preview
|
|
637
|
+
// (send.go prints `❌ Draft <base> changed after preview` and errors the
|
|
638
|
+
// run). Surface that retryable conflict as a revision conflict, not as a
|
|
639
|
+
// generic command failure.
|
|
640
|
+
if (/\n?\s*❌\s*Draft\s+\S+\s+changed after preview/.test(output)) {
|
|
641
|
+
throw new MailSendFailure(
|
|
642
|
+
"revision-match",
|
|
643
|
+
"Draft changed after preview; refresh and preview again before sending",
|
|
644
|
+
)
|
|
645
|
+
}
|
|
646
|
+
const contract = validateSendContract(output)
|
|
647
|
+
if (!contract.ok) {
|
|
648
|
+
throw new MailSendFailure("contract", contract.reason)
|
|
649
|
+
}
|
|
650
|
+
return { dryRun: false, output }
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
async function archive(
|
|
654
|
+
cwd: string,
|
|
655
|
+
id: string,
|
|
656
|
+
options: SendDraftParams = {},
|
|
657
|
+
): Promise<void> {
|
|
658
|
+
const draftDir = requireDraftDir(options.draftDir)
|
|
659
|
+
// `mailos drafts archive <id>` resolves ids ONLY against the global
|
|
660
|
+
// ~/.email/drafts directory (drafts.go `localDraftPath` ->
|
|
661
|
+
// `globalDraftDir`); it has no --draft-dir flag. A custom mailDir would
|
|
662
|
+
// silently mutate a same-named file (or fail) in the home drafts folder,
|
|
663
|
+
// so a non-canonical target is rejected here, before any spawn.
|
|
664
|
+
if (
|
|
665
|
+
!(await sameCanonicalDir(
|
|
666
|
+
draftDir,
|
|
667
|
+
globalDraftDir ?? mailosGlobalDraftDir(),
|
|
668
|
+
))
|
|
669
|
+
) {
|
|
670
|
+
throw new MailSendFailure(
|
|
671
|
+
"unsupported-draft-dir",
|
|
672
|
+
"MailOS drafts archive can only address the default ~/.email/drafts folder; this draft lives elsewhere. Delete it or archive it directly with mailos.",
|
|
673
|
+
)
|
|
674
|
+
}
|
|
675
|
+
const bin = await binary(cwd)
|
|
676
|
+
await runMailos(execFile, bin, ["drafts", "archive", id], {
|
|
677
|
+
cwd,
|
|
678
|
+
timeoutMs: 30_000,
|
|
679
|
+
signal: options.signal,
|
|
680
|
+
})
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return {
|
|
684
|
+
identity,
|
|
685
|
+
signature,
|
|
686
|
+
conversation,
|
|
687
|
+
sendPreview,
|
|
688
|
+
confirmSend,
|
|
689
|
+
archive,
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export type MailosService = ReturnType<typeof createMailosService>
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* MailOS exits successfully even when a bulk run skipped or failed drafts, so
|
|
697
|
+
* a non-zero exit alone cannot prove delivery. Validate the printed contract:
|
|
698
|
+
* no failure/skip markers, a summary claiming at least one sent draft, and no
|
|
699
|
+
* recorded errors.
|
|
700
|
+
*/
|
|
701
|
+
export function validateSendContract(
|
|
702
|
+
output: string,
|
|
703
|
+
): { ok: true } | { ok: false; reason: string } {
|
|
704
|
+
const markers = /^\s*(❌|⏭️)/m.exec(output)
|
|
705
|
+
if (markers) {
|
|
706
|
+
return { ok: false, reason: "MailOS reported a failed or skipped draft" }
|
|
707
|
+
}
|
|
708
|
+
if (output.includes("No draft files found to send")) {
|
|
709
|
+
return { ok: false, reason: "MailOS did not find the draft to send" }
|
|
710
|
+
}
|
|
711
|
+
const errors = /^\s*❌\s*Errors:\s*(\d+)/m.exec(output)
|
|
712
|
+
if (errors?.[1] && Number(errors[1]) > 0) {
|
|
713
|
+
return {
|
|
714
|
+
ok: false,
|
|
715
|
+
reason: `MailOS reported ${errors[1]} send error(s)`,
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
const sent = /^\s*✅\s*(?:Sent|Previewed|Would send):\s*(\d+)/m.exec(output)
|
|
719
|
+
if (!sent || Number(sent[1]) < 1) {
|
|
720
|
+
return { ok: false, reason: "MailOS did not confirm the draft was sent" }
|
|
721
|
+
}
|
|
722
|
+
return { ok: true }
|
|
723
|
+
}
|