@pi-harness/pi-harness 0.1.1 → 0.1.3
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/LICENSE +9 -0
- package/README.md +31 -7
- package/apps/web/dist/assets/index-BoEwZu6r.css +2 -0
- package/apps/web/dist/assets/index-alZn4u37.js +20 -0
- package/apps/web/dist/assets/markdown-vendor-DUdMWn0M.js +66 -0
- package/apps/web/dist/assets/react-vendor-BD7-wQo9.js +9 -0
- package/apps/web/dist/icons/app/android-192.png +0 -0
- package/apps/web/dist/icons/app/android-512.png +0 -0
- package/apps/web/dist/icons/app/app-blue-512.png +0 -0
- package/apps/web/dist/icons/app/app-store-1024.png +0 -0
- package/apps/web/dist/icons/app/apple-touch-icon-180.png +0 -0
- package/apps/web/dist/icons/app/maskable-512.png +0 -0
- package/apps/web/dist/icons/favicon/favicon-16.png +0 -0
- package/apps/web/dist/icons/favicon/favicon-32.png +0 -0
- package/apps/web/dist/icons/favicon/favicon-48.png +0 -0
- package/apps/web/dist/icons/png-blue/pi-256.png +0 -0
- package/apps/web/dist/icons/png-blue/pi-512.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-1024.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-128.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-16.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-24.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-256.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-32.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-48.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-512.png +0 -0
- package/apps/web/dist/icons/png-ink/pi-64.png +0 -0
- package/apps/web/dist/icons/png-white/pi-1024.png +0 -0
- package/apps/web/dist/icons/png-white/pi-128.png +0 -0
- package/apps/web/dist/icons/png-white/pi-16.png +0 -0
- package/apps/web/dist/icons/png-white/pi-24.png +0 -0
- package/apps/web/dist/icons/png-white/pi-256.png +0 -0
- package/apps/web/dist/icons/png-white/pi-32.png +0 -0
- package/apps/web/dist/icons/png-white/pi-48.png +0 -0
- package/apps/web/dist/icons/png-white/pi-512.png +0 -0
- package/apps/web/dist/icons/png-white/pi-64.png +0 -0
- package/apps/web/dist/icons/social/og-1200x630.png +0 -0
- package/apps/web/dist/icons/svg/app-icon-blue.svg +13 -0
- package/apps/web/dist/icons/svg/app-icon-ink.svg +13 -0
- package/apps/web/dist/icons/svg/favicon.svg +10 -0
- package/apps/web/dist/icons/svg/lockup-horizontal.svg +13 -0
- package/apps/web/dist/icons/svg/mark-blue.svg +10 -0
- package/apps/web/dist/icons/svg/mark-compact.svg +10 -0
- package/apps/web/dist/icons/svg/mark-ink.svg +10 -0
- package/apps/web/dist/icons/svg/mark-white.svg +10 -0
- package/apps/web/dist/icons/svg/mark.svg +10 -0
- package/apps/web/dist/index.html +18 -6
- package/apps/web/dist/manifest.webmanifest +14 -0
- package/apps/web/index.html +14 -4
- package/apps/web/package.json +11 -9
- package/apps/web/profile/cordis.yml +222 -1
- package/apps/web/public/icons/app/android-192.png +0 -0
- package/apps/web/public/icons/app/android-512.png +0 -0
- package/apps/web/public/icons/app/app-blue-512.png +0 -0
- package/apps/web/public/icons/app/app-store-1024.png +0 -0
- package/apps/web/public/icons/app/apple-touch-icon-180.png +0 -0
- package/apps/web/public/icons/app/maskable-512.png +0 -0
- package/apps/web/public/icons/favicon/favicon-16.png +0 -0
- package/apps/web/public/icons/favicon/favicon-32.png +0 -0
- package/apps/web/public/icons/favicon/favicon-48.png +0 -0
- package/apps/web/public/icons/png-blue/pi-256.png +0 -0
- package/apps/web/public/icons/png-blue/pi-512.png +0 -0
- package/apps/web/public/icons/png-ink/pi-1024.png +0 -0
- package/apps/web/public/icons/png-ink/pi-128.png +0 -0
- package/apps/web/public/icons/png-ink/pi-16.png +0 -0
- package/apps/web/public/icons/png-ink/pi-24.png +0 -0
- package/apps/web/public/icons/png-ink/pi-256.png +0 -0
- package/apps/web/public/icons/png-ink/pi-32.png +0 -0
- package/apps/web/public/icons/png-ink/pi-48.png +0 -0
- package/apps/web/public/icons/png-ink/pi-512.png +0 -0
- package/apps/web/public/icons/png-ink/pi-64.png +0 -0
- package/apps/web/public/icons/png-white/pi-1024.png +0 -0
- package/apps/web/public/icons/png-white/pi-128.png +0 -0
- package/apps/web/public/icons/png-white/pi-16.png +0 -0
- package/apps/web/public/icons/png-white/pi-24.png +0 -0
- package/apps/web/public/icons/png-white/pi-256.png +0 -0
- package/apps/web/public/icons/png-white/pi-32.png +0 -0
- package/apps/web/public/icons/png-white/pi-48.png +0 -0
- package/apps/web/public/icons/png-white/pi-512.png +0 -0
- package/apps/web/public/icons/png-white/pi-64.png +0 -0
- package/apps/web/public/icons/social/og-1200x630.png +0 -0
- package/apps/web/public/icons/svg/app-icon-blue.svg +13 -0
- package/apps/web/public/icons/svg/app-icon-ink.svg +13 -0
- package/apps/web/public/icons/svg/favicon.svg +10 -0
- package/apps/web/public/icons/svg/lockup-horizontal.svg +13 -0
- package/apps/web/public/icons/svg/mark-blue.svg +10 -0
- package/apps/web/public/icons/svg/mark-compact.svg +10 -0
- package/apps/web/public/icons/svg/mark-ink.svg +10 -0
- package/apps/web/public/icons/svg/mark-white.svg +10 -0
- package/apps/web/public/icons/svg/mark.svg +10 -0
- package/apps/web/public/manifest.webmanifest +14 -0
- package/apps/web/server-dist/bin.js +19 -6
- package/apps/web/server-dist/bin.js.map +1 -1
- package/apps/web/src/command-palette.ts +28 -7
- package/apps/web/src/file-diff.ts +15 -10
- package/apps/web/src/main.ts +4 -1
- package/apps/web/src/runtime.css +17 -4
- package/apps/web/src/server/bin.ts +24 -7
- package/apps/web/src/style.css +2604 -7
- package/apps/web/src/tailwind.css +25 -0
- package/apps/web/tsconfig.build.json +5 -1
- package/apps/web/tsconfig.json +1 -1
- package/apps/web/vite.config.ts +20 -0
- package/package.json +29 -17
- package/packages/api-gateway/LICENSE +9 -0
- package/packages/api-gateway/dist/index.d.ts.map +1 -1
- package/packages/api-gateway/dist/index.js +1202 -37
- package/packages/api-gateway/dist/index.js.map +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/archify.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +25 -0
- package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +22 -0
- package/packages/api-gateway/dist/marketplace-entries/official/context.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-group.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-timer.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/genui.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +25 -0
- package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/memory.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +19 -0
- package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +22 -0
- package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +19 -0
- package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +22 -0
- package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +16 -0
- package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +16 -0
- package/packages/api-gateway/dist/marketplace.d.ts +60 -0
- package/packages/api-gateway/dist/marketplace.d.ts.map +1 -0
- package/packages/api-gateway/dist/marketplace.js +235 -0
- package/packages/api-gateway/dist/marketplace.js.map +1 -0
- package/packages/api-gateway/dist/workspaces.d.ts +8 -0
- package/packages/api-gateway/dist/workspaces.d.ts.map +1 -0
- package/packages/api-gateway/dist/workspaces.js +14 -0
- package/packages/api-gateway/dist/workspaces.js.map +1 -0
- package/packages/api-gateway/package.json +20 -10
- package/packages/api-gateway/scripts/copy-marketplace-entries.mjs +13 -0
- package/packages/api-gateway/src/index.ts +1272 -56
- package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/annotation.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/archify.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/at-file.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +25 -0
- package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +22 -0
- package/packages/api-gateway/src/marketplace-entries/official/context.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cordis-group.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cordis-logger-console.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cordis-timer.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/genui.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +25 -0
- package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/memory.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +19 -0
- package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/modlens.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/module-search.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/openpets.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +22 -0
- package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-export.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/session-search.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/synapse.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +19 -0
- package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +22 -0
- package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/web-research.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +16 -0
- package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +16 -0
- package/packages/api-gateway/src/marketplace.ts +293 -0
- package/packages/api-gateway/src/workspaces.ts +20 -0
- package/packages/api-gateway/test/index.test.ts +501 -31
- package/packages/api-gateway/test/marketplace.test.ts +296 -0
- package/packages/api-gateway/test/workspaces.test.ts +13 -0
- package/packages/api-gateway/tsconfig.build.json +1 -1
- package/packages/api-gateway/tsconfig.json +1 -1
- package/packages/bundle-web-app/LICENSE +9 -0
- package/packages/bundle-web-app/package.json +19 -9
- package/packages/bundle-web-app/tsconfig.build.json +1 -1
- package/packages/bundle-web-app/tsconfig.json +1 -1
- package/packages/cli/LICENSE +9 -0
- package/packages/cli/dist/args.d.ts.map +1 -1
- package/packages/cli/dist/args.js +16 -9
- package/packages/cli/dist/args.js.map +1 -1
- package/packages/cli/dist/bin.js +12 -3
- package/packages/cli/dist/bin.js.map +1 -1
- package/packages/cli/dist/main.d.ts +1 -0
- package/packages/cli/dist/main.d.ts.map +1 -1
- package/packages/cli/dist/main.js +49 -9
- package/packages/cli/dist/main.js.map +1 -1
- package/packages/cli/dist/node-stdio.d.ts +3 -1
- package/packages/cli/dist/node-stdio.d.ts.map +1 -1
- package/packages/cli/dist/node-stdio.js +91 -13
- package/packages/cli/dist/node-stdio.js.map +1 -1
- package/packages/cli/dist/relaunch.d.ts.map +1 -1
- package/packages/cli/dist/relaunch.js +23 -10
- package/packages/cli/dist/relaunch.js.map +1 -1
- package/packages/cli/package.json +18 -8
- package/packages/cli/src/args.ts +16 -10
- package/packages/cli/src/bin.ts +12 -3
- package/packages/cli/src/main.ts +54 -10
- package/packages/cli/src/node-stdio.ts +85 -13
- package/packages/cli/src/relaunch.ts +19 -6
- package/packages/cli/test/args.test.ts +22 -3
- package/packages/cli/test/binary.test.ts +58 -0
- package/packages/cli/test/broken-pipe.test.ts +32 -0
- package/packages/cli/test/cli.test.ts +57 -8
- package/packages/cli/test/node-stdio.test.ts +89 -0
- package/packages/cli/test/relaunch.test.ts +30 -2
- package/packages/cli/test/stdin-shutdown.test.ts +59 -0
- package/packages/cli/tsconfig.build.json +1 -3
- package/packages/cli/tsconfig.json +1 -4
- package/packages/client-web/LICENSE +9 -0
- package/packages/client-web/dist/annotation-ui.d.ts +11 -0
- package/packages/client-web/dist/annotation-ui.d.ts.map +1 -0
- package/packages/client-web/dist/annotation-ui.js +24 -0
- package/packages/client-web/dist/annotation-ui.js.map +1 -0
- package/packages/client-web/dist/browser-session-view.d.ts +7 -0
- package/packages/client-web/dist/browser-session-view.d.ts.map +1 -0
- package/packages/client-web/dist/browser-session-view.js +8 -0
- package/packages/client-web/dist/browser-session-view.js.map +1 -0
- package/packages/client-web/dist/control-room.d.ts +169 -2
- package/packages/client-web/dist/control-room.d.ts.map +1 -1
- package/packages/client-web/dist/control-room.js +156 -11
- package/packages/client-web/dist/control-room.js.map +1 -1
- package/packages/client-web/dist/design-contract.d.ts.map +1 -1
- package/packages/client-web/dist/design-contract.js +178 -19
- package/packages/client-web/dist/design-contract.js.map +1 -1
- package/packages/client-web/dist/index.d.ts +4 -1
- package/packages/client-web/dist/index.d.ts.map +1 -1
- package/packages/client-web/dist/index.js +11 -3
- package/packages/client-web/dist/index.js.map +1 -1
- package/packages/client-web/dist/markdown.d.ts +5 -0
- package/packages/client-web/dist/markdown.d.ts.map +1 -0
- package/packages/client-web/dist/markdown.js +20 -0
- package/packages/client-web/dist/markdown.js.map +1 -0
- package/packages/client-web/dist/marketplace-catalog.d.ts +3 -0
- package/packages/client-web/dist/marketplace-catalog.d.ts.map +1 -0
- package/packages/client-web/dist/marketplace-catalog.js +10 -0
- package/packages/client-web/dist/marketplace-catalog.js.map +1 -0
- package/packages/client-web/dist/marketplace-navigation.d.ts +19 -0
- package/packages/client-web/dist/marketplace-navigation.d.ts.map +1 -0
- package/packages/client-web/dist/marketplace-navigation.js +31 -0
- package/packages/client-web/dist/marketplace-navigation.js.map +1 -0
- package/packages/client-web/dist/message-content.d.ts +9 -0
- package/packages/client-web/dist/message-content.d.ts.map +1 -0
- package/packages/client-web/dist/message-content.js +54 -0
- package/packages/client-web/dist/message-content.js.map +1 -0
- package/packages/client-web/dist/plugin-navigation.d.ts +3 -0
- package/packages/client-web/dist/plugin-navigation.d.ts.map +1 -0
- package/packages/client-web/dist/plugin-navigation.js +10 -0
- package/packages/client-web/dist/plugin-navigation.js.map +1 -0
- package/packages/client-web/dist/plugin-search.d.ts +2 -0
- package/packages/client-web/dist/plugin-search.d.ts.map +1 -0
- package/packages/client-web/dist/plugin-search.js +7 -0
- package/packages/client-web/dist/plugin-search.js.map +1 -0
- package/packages/client-web/dist/plugin-stars-view.d.ts +12 -0
- package/packages/client-web/dist/plugin-stars-view.d.ts.map +1 -0
- package/packages/client-web/dist/plugin-stars-view.js +8 -0
- package/packages/client-web/dist/plugin-stars-view.js.map +1 -0
- package/packages/client-web/dist/prompt-completion.d.ts +13 -0
- package/packages/client-web/dist/prompt-completion.d.ts.map +1 -0
- package/packages/client-web/dist/prompt-completion.js +17 -0
- package/packages/client-web/dist/prompt-completion.js.map +1 -0
- package/packages/client-web/dist/react-room.d.ts +2 -1
- package/packages/client-web/dist/react-room.d.ts.map +1 -1
- package/packages/client-web/dist/react-room.js +2349 -84
- package/packages/client-web/dist/react-room.js.map +1 -1
- package/packages/client-web/dist/runtime-events.d.ts +4 -0
- package/packages/client-web/dist/runtime-events.d.ts.map +1 -0
- package/packages/client-web/dist/runtime-events.js +29 -0
- package/packages/client-web/dist/runtime-events.js.map +1 -0
- package/packages/client-web/package.json +19 -7
- package/packages/client-web/src/annotation-ui.ts +29 -0
- package/packages/client-web/src/browser-session-view.ts +13 -0
- package/packages/client-web/src/control-room.ts +359 -10
- package/packages/client-web/src/design-contract.ts +248 -26
- package/packages/client-web/src/index.ts +17 -4
- package/packages/client-web/src/markdown.tsx +22 -0
- package/packages/client-web/src/marketplace-catalog.ts +10 -0
- package/packages/client-web/src/marketplace-navigation.ts +46 -0
- package/packages/client-web/src/message-content.ts +51 -0
- package/packages/client-web/src/plugin-navigation.ts +9 -0
- package/packages/client-web/src/plugin-search.ts +5 -0
- package/packages/client-web/src/plugin-stars-view.ts +19 -0
- package/packages/client-web/src/prompt-completion.ts +24 -0
- package/packages/client-web/src/react-room.tsx +7365 -49
- package/packages/client-web/src/runtime-events.ts +29 -0
- package/packages/client-web/test/annotation-ui.test.ts +21 -0
- package/packages/client-web/test/browser-session-view.test.ts +17 -0
- package/packages/client-web/test/design-contract.test.ts +46 -1
- package/packages/client-web/test/marketplace-catalog.test.ts +52 -0
- package/packages/client-web/test/message-content.test.ts +43 -0
- package/packages/client-web/test/plugin-navigation.test.ts +16 -0
- package/packages/client-web/test/plugin-search.test.ts +22 -0
- package/packages/client-web/test/plugin-stars-view.test.ts +20 -0
- package/packages/client-web/test/prompt-completion.test.ts +21 -0
- package/packages/client-web/test/runtime-events.test.ts +28 -0
- package/packages/client-web/tsconfig.build.json +13 -1
- package/packages/client-web/tsconfig.json +11 -1
- package/packages/core/LICENSE +9 -0
- package/packages/core/dist/boot.d.ts.map +1 -1
- package/packages/core/dist/boot.js +42 -3
- package/packages/core/dist/boot.js.map +1 -1
- package/packages/core/dist/config.d.ts +2 -0
- package/packages/core/dist/config.d.ts.map +1 -0
- package/packages/core/dist/config.js +8 -0
- package/packages/core/dist/config.js.map +1 -0
- package/packages/core/dist/http.d.ts +8 -0
- package/packages/core/dist/http.d.ts.map +1 -0
- package/packages/core/dist/http.js +27 -0
- package/packages/core/dist/http.js.map +1 -0
- package/packages/core/dist/index.d.ts +2 -0
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +2 -0
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/plugins/agent-teams.d.ts +17 -0
- package/packages/core/dist/plugins/agent-teams.d.ts.map +1 -0
- package/packages/core/dist/plugins/agent-teams.js +298 -0
- package/packages/core/dist/plugins/agent-teams.js.map +1 -0
- package/packages/core/dist/plugins/anchored-standard.d.ts +14 -0
- package/packages/core/dist/plugins/anchored-standard.d.ts.map +1 -0
- package/packages/core/dist/plugins/anchored-standard.js +84 -0
- package/packages/core/dist/plugins/anchored-standard.js.map +1 -0
- package/packages/core/dist/plugins/annotation.d.ts +18 -0
- package/packages/core/dist/plugins/annotation.d.ts.map +1 -0
- package/packages/core/dist/plugins/annotation.js +94 -0
- package/packages/core/dist/plugins/annotation.js.map +1 -0
- package/packages/core/dist/plugins/archify.d.ts +23 -0
- package/packages/core/dist/plugins/archify.d.ts.map +1 -0
- package/packages/core/dist/plugins/archify.js +98 -0
- package/packages/core/dist/plugins/archify.js.map +1 -0
- package/packages/core/dist/plugins/at-file.d.ts +8 -0
- package/packages/core/dist/plugins/at-file.d.ts.map +1 -0
- package/packages/core/dist/plugins/at-file.js +52 -0
- package/packages/core/dist/plugins/at-file.js.map +1 -0
- package/packages/core/dist/plugins/auto-mode.d.ts +15 -0
- package/packages/core/dist/plugins/auto-mode.d.ts.map +1 -0
- package/packages/core/dist/plugins/auto-mode.js +114 -0
- package/packages/core/dist/plugins/auto-mode.js.map +1 -0
- package/packages/core/dist/plugins/better-sidebar.d.ts +37 -0
- package/packages/core/dist/plugins/better-sidebar.d.ts.map +1 -0
- package/packages/core/dist/plugins/better-sidebar.js +89 -0
- package/packages/core/dist/plugins/better-sidebar.js.map +1 -0
- package/packages/core/dist/plugins/browser-fetch.d.ts +14 -0
- package/packages/core/dist/plugins/browser-fetch.d.ts.map +1 -0
- package/packages/core/dist/plugins/browser-fetch.js +167 -0
- package/packages/core/dist/plugins/browser-fetch.js.map +1 -0
- package/packages/core/dist/plugins/browser-session.d.ts +14 -0
- package/packages/core/dist/plugins/browser-session.d.ts.map +1 -0
- package/packages/core/dist/plugins/browser-session.js +265 -0
- package/packages/core/dist/plugins/browser-session.js.map +1 -0
- package/packages/core/dist/plugins/canvas-draw.d.ts +8 -0
- package/packages/core/dist/plugins/canvas-draw.d.ts.map +1 -0
- package/packages/core/dist/plugins/canvas-draw.js +88 -0
- package/packages/core/dist/plugins/canvas-draw.js.map +1 -0
- package/packages/core/dist/plugins/change-verifier.d.ts +8 -0
- package/packages/core/dist/plugins/change-verifier.d.ts.map +1 -0
- package/packages/core/dist/plugins/change-verifier.js +67 -0
- package/packages/core/dist/plugins/change-verifier.js.map +1 -0
- package/packages/core/dist/plugins/cleaner.d.ts +8 -0
- package/packages/core/dist/plugins/cleaner.d.ts.map +1 -0
- package/packages/core/dist/plugins/cleaner.js +56 -0
- package/packages/core/dist/plugins/cleaner.js.map +1 -0
- package/packages/core/dist/plugins/cli-notifier.d.ts +15 -0
- package/packages/core/dist/plugins/cli-notifier.d.ts.map +1 -0
- package/packages/core/dist/plugins/cli-notifier.js +110 -0
- package/packages/core/dist/plugins/cli-notifier.js.map +1 -0
- package/packages/core/dist/plugins/code2skill.d.ts +8 -0
- package/packages/core/dist/plugins/code2skill.d.ts.map +1 -0
- package/packages/core/dist/plugins/code2skill.js +95 -0
- package/packages/core/dist/plugins/code2skill.js.map +1 -0
- package/packages/core/dist/plugins/colleague-skill.d.ts +27 -0
- package/packages/core/dist/plugins/colleague-skill.d.ts.map +1 -0
- package/packages/core/dist/plugins/colleague-skill.js +99 -0
- package/packages/core/dist/plugins/colleague-skill.js.map +1 -0
- package/packages/core/dist/plugins/context-doctor.d.ts +30 -0
- package/packages/core/dist/plugins/context-doctor.d.ts.map +1 -0
- package/packages/core/dist/plugins/context-doctor.js +95 -0
- package/packages/core/dist/plugins/context-doctor.js.map +1 -0
- package/packages/core/dist/plugins/context.d.ts +8 -0
- package/packages/core/dist/plugins/context.d.ts.map +1 -0
- package/packages/core/dist/plugins/context.js +87 -0
- package/packages/core/dist/plugins/context.js.map +1 -0
- package/packages/core/dist/plugins/cost-meter.d.ts +32 -0
- package/packages/core/dist/plugins/cost-meter.d.ts.map +1 -0
- package/packages/core/dist/plugins/cost-meter.js +204 -0
- package/packages/core/dist/plugins/cost-meter.js.map +1 -0
- package/packages/core/dist/plugins/dependency-checker.d.ts +27 -0
- package/packages/core/dist/plugins/dependency-checker.d.ts.map +1 -0
- package/packages/core/dist/plugins/dependency-checker.js +221 -0
- package/packages/core/dist/plugins/dependency-checker.js.map +1 -0
- package/packages/core/dist/plugins/docker-sandbox.d.ts +8 -0
- package/packages/core/dist/plugins/docker-sandbox.d.ts.map +1 -0
- package/packages/core/dist/plugins/docker-sandbox.js +102 -0
- package/packages/core/dist/plugins/docker-sandbox.js.map +1 -0
- package/packages/core/dist/plugins/fail-logger.d.ts +8 -0
- package/packages/core/dist/plugins/fail-logger.d.ts.map +1 -0
- package/packages/core/dist/plugins/fail-logger.js +51 -0
- package/packages/core/dist/plugins/fail-logger.js.map +1 -0
- package/packages/core/dist/plugins/genui.d.ts +8 -0
- package/packages/core/dist/plugins/genui.d.ts.map +1 -0
- package/packages/core/dist/plugins/genui.js +79 -0
- package/packages/core/dist/plugins/genui.js.map +1 -0
- package/packages/core/dist/plugins/git-time-capsule.d.ts +9 -0
- package/packages/core/dist/plugins/git-time-capsule.d.ts.map +1 -0
- package/packages/core/dist/plugins/git-time-capsule.js +90 -0
- package/packages/core/dist/plugins/git-time-capsule.js.map +1 -0
- package/packages/core/dist/plugins/graph-memory.d.ts +16 -0
- package/packages/core/dist/plugins/graph-memory.d.ts.map +1 -0
- package/packages/core/dist/plugins/graph-memory.js +382 -0
- package/packages/core/dist/plugins/graph-memory.js.map +1 -0
- package/packages/core/dist/plugins/history-compressor.d.ts +15 -0
- package/packages/core/dist/plugins/history-compressor.d.ts.map +1 -0
- package/packages/core/dist/plugins/history-compressor.js +80 -0
- package/packages/core/dist/plugins/history-compressor.js.map +1 -0
- package/packages/core/dist/plugins/hol-guard.d.ts +29 -0
- package/packages/core/dist/plugins/hol-guard.d.ts.map +1 -0
- package/packages/core/dist/plugins/hol-guard.js +139 -0
- package/packages/core/dist/plugins/hol-guard.js.map +1 -0
- package/packages/core/dist/plugins/i18n-pair.d.ts +8 -0
- package/packages/core/dist/plugins/i18n-pair.d.ts.map +1 -0
- package/packages/core/dist/plugins/i18n-pair.js +76 -0
- package/packages/core/dist/plugins/i18n-pair.js.map +1 -0
- package/packages/core/dist/plugins/image-compressor.d.ts +8 -0
- package/packages/core/dist/plugins/image-compressor.d.ts.map +1 -0
- package/packages/core/dist/plugins/image-compressor.js +150 -0
- package/packages/core/dist/plugins/image-compressor.js.map +1 -0
- package/packages/core/dist/plugins/llm-verifier.d.ts +42 -0
- package/packages/core/dist/plugins/llm-verifier.d.ts.map +1 -0
- package/packages/core/dist/plugins/llm-verifier.js +128 -0
- package/packages/core/dist/plugins/llm-verifier.js.map +1 -0
- package/packages/core/dist/plugins/mcp-client.d.ts +19 -0
- package/packages/core/dist/plugins/mcp-client.d.ts.map +1 -0
- package/packages/core/dist/plugins/mcp-client.js +534 -0
- package/packages/core/dist/plugins/mcp-client.js.map +1 -0
- package/packages/core/dist/plugins/mcp-panel.d.ts +14 -0
- package/packages/core/dist/plugins/mcp-panel.d.ts.map +1 -0
- package/packages/core/dist/plugins/mcp-panel.js +180 -0
- package/packages/core/dist/plugins/mcp-panel.js.map +1 -0
- package/packages/core/dist/plugins/memory.d.ts +15 -0
- package/packages/core/dist/plugins/memory.d.ts.map +1 -0
- package/packages/core/dist/plugins/memory.js +161 -0
- package/packages/core/dist/plugins/memory.js.map +1 -0
- package/packages/core/dist/plugins/mirage-bridge.d.ts +23 -0
- package/packages/core/dist/plugins/mirage-bridge.d.ts.map +1 -0
- package/packages/core/dist/plugins/mirage-bridge.js +149 -0
- package/packages/core/dist/plugins/mirage-bridge.js.map +1 -0
- package/packages/core/dist/plugins/mock-server.d.ts +22 -0
- package/packages/core/dist/plugins/mock-server.d.ts.map +1 -0
- package/packages/core/dist/plugins/mock-server.js +149 -0
- package/packages/core/dist/plugins/mock-server.js.map +1 -0
- package/packages/core/dist/plugins/model.d.ts +1 -1
- package/packages/core/dist/plugins/model.d.ts.map +1 -1
- package/packages/core/dist/plugins/model.js +3 -1
- package/packages/core/dist/plugins/model.js.map +1 -1
- package/packages/core/dist/plugins/models.d.ts.map +1 -1
- package/packages/core/dist/plugins/models.js +5 -2
- package/packages/core/dist/plugins/models.js.map +1 -1
- package/packages/core/dist/plugins/modlens.d.ts +8 -0
- package/packages/core/dist/plugins/modlens.d.ts.map +1 -0
- package/packages/core/dist/plugins/modlens.js +63 -0
- package/packages/core/dist/plugins/modlens.js.map +1 -0
- package/packages/core/dist/plugins/module-search.d.ts +27 -0
- package/packages/core/dist/plugins/module-search.d.ts.map +1 -0
- package/packages/core/dist/plugins/module-search.js +174 -0
- package/packages/core/dist/plugins/module-search.js.map +1 -0
- package/packages/core/dist/plugins/obsidian-sync.d.ts +14 -0
- package/packages/core/dist/plugins/obsidian-sync.d.ts.map +1 -0
- package/packages/core/dist/plugins/obsidian-sync.js +79 -0
- package/packages/core/dist/plugins/obsidian-sync.js.map +1 -0
- package/packages/core/dist/plugins/openpets.d.ts +14 -0
- package/packages/core/dist/plugins/openpets.d.ts.map +1 -0
- package/packages/core/dist/plugins/openpets.js +99 -0
- package/packages/core/dist/plugins/openpets.js.map +1 -0
- package/packages/core/dist/plugins/plan-execute.d.ts +8 -0
- package/packages/core/dist/plugins/plan-execute.d.ts.map +1 -0
- package/packages/core/dist/plugins/plan-execute.js +70 -0
- package/packages/core/dist/plugins/plan-execute.js.map +1 -0
- package/packages/core/dist/plugins/plugin-check.d.ts +38 -0
- package/packages/core/dist/plugins/plugin-check.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-check.js +227 -0
- package/packages/core/dist/plugins/plugin-check.js.map +1 -0
- package/packages/core/dist/plugins/plugin-dev.d.ts +8 -0
- package/packages/core/dist/plugins/plugin-dev.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-dev.js +44 -0
- package/packages/core/dist/plugins/plugin-dev.js.map +1 -0
- package/packages/core/dist/plugins/plugin-finder.d.ts +16 -0
- package/packages/core/dist/plugins/plugin-finder.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-finder.js +98 -0
- package/packages/core/dist/plugins/plugin-finder.js.map +1 -0
- package/packages/core/dist/plugins/plugin-radar.d.ts +29 -0
- package/packages/core/dist/plugins/plugin-radar.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-radar.js +146 -0
- package/packages/core/dist/plugins/plugin-radar.js.map +1 -0
- package/packages/core/dist/plugins/plugin-stars.d.ts +45 -0
- package/packages/core/dist/plugins/plugin-stars.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-stars.js +165 -0
- package/packages/core/dist/plugins/plugin-stars.js.map +1 -0
- package/packages/core/dist/plugins/prompt-guard.d.ts +8 -0
- package/packages/core/dist/plugins/prompt-guard.d.ts.map +1 -0
- package/packages/core/dist/plugins/prompt-guard.js +114 -0
- package/packages/core/dist/plugins/prompt-guard.js.map +1 -0
- package/packages/core/dist/plugins/prompt-library.d.ts +25 -0
- package/packages/core/dist/plugins/prompt-library.d.ts.map +1 -0
- package/packages/core/dist/plugins/prompt-library.js +142 -0
- package/packages/core/dist/plugins/prompt-library.js.map +1 -0
- package/packages/core/dist/plugins/readme-gen.d.ts +25 -0
- package/packages/core/dist/plugins/readme-gen.d.ts.map +1 -0
- package/packages/core/dist/plugins/readme-gen.js +139 -0
- package/packages/core/dist/plugins/readme-gen.js.map +1 -0
- package/packages/core/dist/plugins/recall-unread.d.ts +24 -0
- package/packages/core/dist/plugins/recall-unread.d.ts.map +1 -0
- package/packages/core/dist/plugins/recall-unread.js +124 -0
- package/packages/core/dist/plugins/recall-unread.js.map +1 -0
- package/packages/core/dist/plugins/resources.d.ts +1 -0
- package/packages/core/dist/plugins/resources.d.ts.map +1 -1
- package/packages/core/dist/plugins/resources.js +31 -22
- package/packages/core/dist/plugins/resources.js.map +1 -1
- package/packages/core/dist/plugins/reverse-skill.d.ts +23 -0
- package/packages/core/dist/plugins/reverse-skill.d.ts.map +1 -0
- package/packages/core/dist/plugins/reverse-skill.js +60 -0
- package/packages/core/dist/plugins/reverse-skill.js.map +1 -0
- package/packages/core/dist/plugins/reviewer-bot.d.ts +14 -0
- package/packages/core/dist/plugins/reviewer-bot.d.ts.map +1 -0
- package/packages/core/dist/plugins/reviewer-bot.js +133 -0
- package/packages/core/dist/plugins/reviewer-bot.js.map +1 -0
- package/packages/core/dist/plugins/runtime-doctor.d.ts +33 -0
- package/packages/core/dist/plugins/runtime-doctor.d.ts.map +1 -0
- package/packages/core/dist/plugins/runtime-doctor.js +114 -0
- package/packages/core/dist/plugins/runtime-doctor.js.map +1 -0
- package/packages/core/dist/plugins/runtime.d.ts.map +1 -1
- package/packages/core/dist/plugins/runtime.js +63 -14
- package/packages/core/dist/plugins/runtime.js.map +1 -1
- package/packages/core/dist/plugins/secure-audit.d.ts +31 -0
- package/packages/core/dist/plugins/secure-audit.d.ts.map +1 -0
- package/packages/core/dist/plugins/secure-audit.js +121 -0
- package/packages/core/dist/plugins/secure-audit.js.map +1 -0
- package/packages/core/dist/plugins/session-bookmarks.d.ts +15 -0
- package/packages/core/dist/plugins/session-bookmarks.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-bookmarks.js +87 -0
- package/packages/core/dist/plugins/session-bookmarks.js.map +1 -0
- package/packages/core/dist/plugins/session-bridge.d.ts +44 -0
- package/packages/core/dist/plugins/session-bridge.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-bridge.js +265 -0
- package/packages/core/dist/plugins/session-bridge.js.map +1 -0
- package/packages/core/dist/plugins/session-compare.d.ts +33 -0
- package/packages/core/dist/plugins/session-compare.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-compare.js +150 -0
- package/packages/core/dist/plugins/session-compare.js.map +1 -0
- package/packages/core/dist/plugins/session-export.d.ts +9 -0
- package/packages/core/dist/plugins/session-export.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-export.js +93 -0
- package/packages/core/dist/plugins/session-export.js.map +1 -0
- package/packages/core/dist/plugins/session-insights.d.ts +8 -0
- package/packages/core/dist/plugins/session-insights.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-insights.js +47 -0
- package/packages/core/dist/plugins/session-insights.js.map +1 -0
- package/packages/core/dist/plugins/session-search.d.ts +20 -0
- package/packages/core/dist/plugins/session-search.d.ts.map +1 -0
- package/packages/core/dist/plugins/session-search.js +122 -0
- package/packages/core/dist/plugins/session-search.js.map +1 -0
- package/packages/core/dist/plugins/session.d.ts.map +1 -1
- package/packages/core/dist/plugins/session.js +4 -2
- package/packages/core/dist/plugins/session.js.map +1 -1
- package/packages/core/dist/plugins/skill-catalog.d.ts +26 -0
- package/packages/core/dist/plugins/skill-catalog.d.ts.map +1 -0
- package/packages/core/dist/plugins/skill-catalog.js +97 -0
- package/packages/core/dist/plugins/skill-catalog.js.map +1 -0
- package/packages/core/dist/plugins/skill-guard.d.ts +26 -0
- package/packages/core/dist/plugins/skill-guard.d.ts.map +1 -0
- package/packages/core/dist/plugins/skill-guard.js +139 -0
- package/packages/core/dist/plugins/skill-guard.js.map +1 -0
- package/packages/core/dist/plugins/sql-lens.d.ts +8 -0
- package/packages/core/dist/plugins/sql-lens.d.ts.map +1 -0
- package/packages/core/dist/plugins/sql-lens.js +85 -0
- package/packages/core/dist/plugins/sql-lens.js.map +1 -0
- package/packages/core/dist/plugins/stdio.d.ts +1 -1
- package/packages/core/dist/plugins/stdio.d.ts.map +1 -1
- package/packages/core/dist/plugins/stdio.js +3 -1
- package/packages/core/dist/plugins/stdio.js.map +1 -1
- package/packages/core/dist/plugins/synapse.d.ts +38 -0
- package/packages/core/dist/plugins/synapse.d.ts.map +1 -0
- package/packages/core/dist/plugins/synapse.js +93 -0
- package/packages/core/dist/plugins/synapse.js.map +1 -0
- package/packages/core/dist/plugins/tab-manager.d.ts +8 -0
- package/packages/core/dist/plugins/tab-manager.d.ts.map +1 -0
- package/packages/core/dist/plugins/tab-manager.js +135 -0
- package/packages/core/dist/plugins/tab-manager.js.map +1 -0
- package/packages/core/dist/plugins/taskboard.d.ts +15 -0
- package/packages/core/dist/plugins/taskboard.d.ts.map +1 -0
- package/packages/core/dist/plugins/taskboard.js +347 -0
- package/packages/core/dist/plugins/taskboard.js.map +1 -0
- package/packages/core/dist/plugins/telemetry-blocker.d.ts +8 -0
- package/packages/core/dist/plugins/telemetry-blocker.d.ts.map +1 -0
- package/packages/core/dist/plugins/telemetry-blocker.js +57 -0
- package/packages/core/dist/plugins/telemetry-blocker.js.map +1 -0
- package/packages/core/dist/plugins/test-harness.d.ts +8 -0
- package/packages/core/dist/plugins/test-harness.d.ts.map +1 -0
- package/packages/core/dist/plugins/test-harness.js +64 -0
- package/packages/core/dist/plugins/test-harness.js.map +1 -0
- package/packages/core/dist/plugins/theme-studio.d.ts +29 -0
- package/packages/core/dist/plugins/theme-studio.d.ts.map +1 -0
- package/packages/core/dist/plugins/theme-studio.js +141 -0
- package/packages/core/dist/plugins/theme-studio.js.map +1 -0
- package/packages/core/dist/plugins/token-guard.d.ts +15 -0
- package/packages/core/dist/plugins/token-guard.d.ts.map +1 -0
- package/packages/core/dist/plugins/token-guard.js +78 -0
- package/packages/core/dist/plugins/token-guard.js.map +1 -0
- package/packages/core/dist/plugins/tools.d.ts.map +1 -1
- package/packages/core/dist/plugins/tools.js +5 -2
- package/packages/core/dist/plugins/tools.js.map +1 -1
- package/packages/core/dist/plugins/turn-rewind.d.ts +19 -0
- package/packages/core/dist/plugins/turn-rewind.d.ts.map +1 -0
- package/packages/core/dist/plugins/turn-rewind.js +74 -0
- package/packages/core/dist/plugins/turn-rewind.js.map +1 -0
- package/packages/core/dist/plugins/undo-savepoint.d.ts +17 -0
- package/packages/core/dist/plugins/undo-savepoint.d.ts.map +1 -0
- package/packages/core/dist/plugins/undo-savepoint.js +247 -0
- package/packages/core/dist/plugins/undo-savepoint.js.map +1 -0
- package/packages/core/dist/plugins/vision-toolkit.d.ts +17 -0
- package/packages/core/dist/plugins/vision-toolkit.d.ts.map +1 -0
- package/packages/core/dist/plugins/vision-toolkit.js +145 -0
- package/packages/core/dist/plugins/vision-toolkit.js.map +1 -0
- package/packages/core/dist/plugins/web-research.d.ts +17 -0
- package/packages/core/dist/plugins/web-research.d.ts.map +1 -0
- package/packages/core/dist/plugins/web-research.js +275 -0
- package/packages/core/dist/plugins/web-research.js.map +1 -0
- package/packages/core/dist/plugins/workspace-navigator.d.ts +36 -0
- package/packages/core/dist/plugins/workspace-navigator.d.ts.map +1 -0
- package/packages/core/dist/plugins/workspace-navigator.js +150 -0
- package/packages/core/dist/plugins/workspace-navigator.js.map +1 -0
- package/packages/core/dist/plugins/workspace-search.d.ts +8 -0
- package/packages/core/dist/plugins/workspace-search.d.ts.map +1 -0
- package/packages/core/dist/plugins/workspace-search.js +134 -0
- package/packages/core/dist/plugins/workspace-search.js.map +1 -0
- package/packages/core/dist/plugins/yaml-validator.d.ts +8 -0
- package/packages/core/dist/plugins/yaml-validator.d.ts.map +1 -0
- package/packages/core/dist/plugins/yaml-validator.js +94 -0
- package/packages/core/dist/plugins/yaml-validator.js.map +1 -0
- package/packages/core/dist/profile.d.ts +1 -0
- package/packages/core/dist/profile.d.ts.map +1 -1
- package/packages/core/dist/profile.js +3 -0
- package/packages/core/dist/profile.js.map +1 -1
- package/packages/core/dist/runtime.d.ts.map +1 -1
- package/packages/core/dist/runtime.js +13 -4
- package/packages/core/dist/runtime.js.map +1 -1
- package/packages/core/dist/services.d.ts +55 -0
- package/packages/core/dist/services.d.ts.map +1 -1
- package/packages/core/dist/services.js +58 -2
- package/packages/core/dist/services.js.map +1 -1
- package/packages/core/dist/stdio.d.ts +13 -2
- package/packages/core/dist/stdio.d.ts.map +1 -1
- package/packages/core/dist/stdio.js +75 -9
- package/packages/core/dist/stdio.js.map +1 -1
- package/packages/core/dist/workspace-path.d.ts +12 -0
- package/packages/core/dist/workspace-path.d.ts.map +1 -0
- package/packages/core/dist/workspace-path.js +62 -0
- package/packages/core/dist/workspace-path.js.map +1 -0
- package/packages/core/package.json +18 -8
- package/packages/core/profiles/default/cordis.yml +85 -0
- package/packages/core/profiles/development/cordis.yml +1 -1
- package/packages/core/src/boot.ts +38 -2
- package/packages/core/src/config.ts +5 -0
- package/packages/core/src/http.ts +32 -0
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/plugins/agent-teams.ts +291 -0
- package/packages/core/src/plugins/anchored-standard.ts +88 -0
- package/packages/core/src/plugins/annotation.ts +106 -0
- package/packages/core/src/plugins/archify.ts +124 -0
- package/packages/core/src/plugins/at-file.ts +54 -0
- package/packages/core/src/plugins/auto-mode.ts +123 -0
- package/packages/core/src/plugins/better-sidebar.ts +117 -0
- package/packages/core/src/plugins/browser-fetch.ts +171 -0
- package/packages/core/src/plugins/browser-session.ts +287 -0
- package/packages/core/src/plugins/canvas-draw.ts +90 -0
- package/packages/core/src/plugins/change-verifier.ts +79 -0
- package/packages/core/src/plugins/cleaner.ts +61 -0
- package/packages/core/src/plugins/cli-notifier.ts +125 -0
- package/packages/core/src/plugins/code2skill.ts +96 -0
- package/packages/core/src/plugins/colleague-skill.ts +122 -0
- package/packages/core/src/plugins/context-doctor.ts +117 -0
- package/packages/core/src/plugins/context.ts +102 -0
- package/packages/core/src/plugins/cost-meter.ts +231 -0
- package/packages/core/src/plugins/dependency-checker.ts +241 -0
- package/packages/core/src/plugins/docker-sandbox.ts +100 -0
- package/packages/core/src/plugins/fail-logger.ts +51 -0
- package/packages/core/src/plugins/genui.ts +88 -0
- package/packages/core/src/plugins/git-time-capsule.ts +97 -0
- package/packages/core/src/plugins/graph-memory.ts +394 -0
- package/packages/core/src/plugins/history-compressor.ts +81 -0
- package/packages/core/src/plugins/hol-guard.ts +153 -0
- package/packages/core/src/plugins/i18n-pair.ts +82 -0
- package/packages/core/src/plugins/image-compressor.ts +144 -0
- package/packages/core/src/plugins/llm-verifier.ts +164 -0
- package/packages/core/src/plugins/mcp-client.ts +559 -0
- package/packages/core/src/plugins/mcp-panel.ts +190 -0
- package/packages/core/src/plugins/memory.ts +176 -0
- package/packages/core/src/plugins/mirage-bridge.ts +179 -0
- package/packages/core/src/plugins/mock-server.ts +158 -0
- package/packages/core/src/plugins/model.ts +3 -1
- package/packages/core/src/plugins/models.ts +5 -2
- package/packages/core/src/plugins/modlens.ts +63 -0
- package/packages/core/src/plugins/module-search.ts +201 -0
- package/packages/core/src/plugins/obsidian-sync.ts +83 -0
- package/packages/core/src/plugins/openpets.ts +109 -0
- package/packages/core/src/plugins/plan-execute.ts +76 -0
- package/packages/core/src/plugins/plugin-check.ts +232 -0
- package/packages/core/src/plugins/plugin-dev.ts +47 -0
- package/packages/core/src/plugins/plugin-finder.ts +108 -0
- package/packages/core/src/plugins/plugin-radar.ts +179 -0
- package/packages/core/src/plugins/plugin-stars.ts +205 -0
- package/packages/core/src/plugins/prompt-guard.ts +122 -0
- package/packages/core/src/plugins/prompt-library.ts +165 -0
- package/packages/core/src/plugins/readme-gen.ts +147 -0
- package/packages/core/src/plugins/recall-unread.ts +142 -0
- package/packages/core/src/plugins/resources.ts +28 -21
- package/packages/core/src/plugins/reverse-skill.ts +79 -0
- package/packages/core/src/plugins/reviewer-bot.ts +146 -0
- package/packages/core/src/plugins/runtime-doctor.ts +137 -0
- package/packages/core/src/plugins/runtime.ts +61 -14
- package/packages/core/src/plugins/secure-audit.ts +146 -0
- package/packages/core/src/plugins/session-bookmarks.ts +89 -0
- package/packages/core/src/plugins/session-bridge.ts +299 -0
- package/packages/core/src/plugins/session-compare.ts +180 -0
- package/packages/core/src/plugins/session-export.ts +99 -0
- package/packages/core/src/plugins/session-insights.ts +47 -0
- package/packages/core/src/plugins/session-search.ts +126 -0
- package/packages/core/src/plugins/session.ts +4 -2
- package/packages/core/src/plugins/skill-catalog.ts +117 -0
- package/packages/core/src/plugins/skill-guard.ts +152 -0
- package/packages/core/src/plugins/sql-lens.ts +92 -0
- package/packages/core/src/plugins/stdio.ts +3 -1
- package/packages/core/src/plugins/synapse.ts +130 -0
- package/packages/core/src/plugins/tab-manager.ts +135 -0
- package/packages/core/src/plugins/taskboard.ts +412 -0
- package/packages/core/src/plugins/telemetry-blocker.ts +62 -0
- package/packages/core/src/plugins/test-harness.ts +67 -0
- package/packages/core/src/plugins/theme-studio.ts +165 -0
- package/packages/core/src/plugins/token-guard.ts +84 -0
- package/packages/core/src/plugins/tools.ts +5 -2
- package/packages/core/src/plugins/turn-rewind.ts +86 -0
- package/packages/core/src/plugins/undo-savepoint.ts +284 -0
- package/packages/core/src/plugins/vision-toolkit.ts +153 -0
- package/packages/core/src/plugins/web-research.ts +289 -0
- package/packages/core/src/plugins/workspace-navigator.ts +164 -0
- package/packages/core/src/plugins/workspace-search.ts +139 -0
- package/packages/core/src/plugins/yaml-validator.ts +97 -0
- package/packages/core/src/profile.ts +3 -0
- package/packages/core/src/runtime.ts +11 -4
- package/packages/core/src/services.ts +110 -3
- package/packages/core/src/stdio.ts +79 -9
- package/packages/core/src/workspace-path.ts +69 -0
- package/packages/core/test/agent-teams.test.ts +24 -0
- package/packages/core/test/archify.test.ts +33 -0
- package/packages/core/test/better-sidebar.test.ts +125 -0
- package/packages/core/test/boot.test.ts +49 -6
- package/packages/core/test/colleague-skill.test.ts +74 -0
- package/packages/core/test/config.test.ts +121 -0
- package/packages/core/test/context-doctor.test.ts +32 -0
- package/packages/core/test/dependency-checker.test.ts +60 -0
- package/packages/core/test/git-time-capsule.test.ts +115 -0
- package/packages/core/test/http.test.ts +34 -0
- package/packages/core/test/llm-verifier.test.ts +72 -0
- package/packages/core/test/mirage-bridge.test.ts +54 -0
- package/packages/core/test/module-search.test.ts +78 -0
- package/packages/core/test/plugin-check.test.ts +16 -0
- package/packages/core/test/plugin-stars.test.ts +55 -0
- package/packages/core/test/profiles.integration.test.ts +49 -15
- package/packages/core/test/prompt-library.test.ts +56 -0
- package/packages/core/test/readme-gen.test.ts +45 -0
- package/packages/core/test/recall-unread.test.ts +35 -0
- package/packages/core/test/registry.test.ts +48 -0
- package/packages/core/test/reverse-skill.test.ts +40 -0
- package/packages/core/test/runtime-doctor.test.ts +55 -0
- package/packages/core/test/runtime-fixture.ts +4 -4
- package/packages/core/test/runtime.test.ts +90 -1
- package/packages/core/test/secure-audit.test.ts +16 -0
- package/packages/core/test/services.test.ts +2024 -5
- package/packages/core/test/session-bookmarks.test.ts +62 -0
- package/packages/core/test/session-bridge.test.ts +103 -0
- package/packages/core/test/session-compare.test.ts +94 -0
- package/packages/core/test/session-export.test.ts +54 -0
- package/packages/core/test/session-search.test.ts +30 -0
- package/packages/core/test/skill-catalog.test.ts +18 -0
- package/packages/core/test/skill-guard.test.ts +21 -0
- package/packages/core/test/stdio-args.test.ts +178 -0
- package/packages/core/test/theme-studio.test.ts +39 -0
- package/packages/core/test/token-guard.test.ts +34 -0
- package/packages/core/test/turn-rewind.test.ts +19 -0
- package/packages/core/test/vision-toolkit.test.ts +38 -0
- package/packages/core/test/workspace-git-status.test.ts +37 -0
- package/packages/core/test/workspace-navigator.test.ts +33 -0
- package/packages/core/test/workspace-path.test.ts +34 -0
- package/packages/core/tsconfig.build.json +1 -3
- package/packages/core/tsconfig.json +1 -4
- package/packages/host-webserver/LICENSE +9 -0
- package/packages/host-webserver/dist/index.js +1 -1
- package/packages/host-webserver/dist/index.js.map +1 -1
- package/packages/host-webserver/package.json +17 -7
- package/packages/host-webserver/src/index.ts +1 -1
- package/packages/host-webserver/test/index.test.ts +4 -1
- package/packages/host-webserver/tsconfig.build.json +1 -1
- package/packages/host-webserver/tsconfig.json +1 -1
- package/apps/web/dist/assets/index-C4tLweAB.js +0 -20
- package/apps/web/dist/assets/index-DPgRbQ4_.css +0 -1
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { rm } from "node:fs/promises";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
4
|
-
import { isAbsolute, relative, resolve } from "node:path";
|
|
4
|
+
import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
5
6
|
import type { Context } from "@deepseek-ai/cordis";
|
|
6
|
-
import { SessionManager, type AgentSessionEvent } from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { SessionManager, type AgentSessionEvent, type ExtensionUIContext } from "@earendil-works/pi-coding-agent";
|
|
7
8
|
import type Loader from "@deepseek-ai/cordis-plugin-loader";
|
|
8
|
-
import type { PiRuntimeService, PiModelsService, PiHarnessLaunch } from "@pi-harness/core";
|
|
9
|
+
import type { PiPluginUiRegistry, PiRuntimeService, PiModelsService, PiHarnessLaunch } from "@pi-harness/core";
|
|
9
10
|
import type { WebServer } from "@pi-harness/host-webserver";
|
|
11
|
+
import {
|
|
12
|
+
MARKETPLACE_CAPABILITIES,
|
|
13
|
+
MARKETPLACE_CATEGORIES,
|
|
14
|
+
MARKETPLACE_PLUGINS,
|
|
15
|
+
attachMarketplaceStatistics,
|
|
16
|
+
createMarketplaceStatisticsLoader,
|
|
17
|
+
paginateMarketplace,
|
|
18
|
+
searchMarketplace,
|
|
19
|
+
needsMarketplacePackageInstall,
|
|
20
|
+
sortMarketplaceByRecommendation,
|
|
21
|
+
type MarketplacePlugin,
|
|
22
|
+
} from "./marketplace.js";
|
|
23
|
+
import { parseGitWorktrees, type WorkspaceSummary } from "./workspaces.js";
|
|
10
24
|
|
|
11
25
|
interface ApiServices {
|
|
12
26
|
readonly runtime: PiRuntimeService;
|
|
@@ -14,8 +28,11 @@ interface ApiServices {
|
|
|
14
28
|
readonly launch: PiHarnessLaunch;
|
|
15
29
|
readonly webServer: WebServer;
|
|
16
30
|
readonly loader: Loader | undefined;
|
|
31
|
+
readonly pluginUi: PiPluginUiRegistry | undefined;
|
|
17
32
|
}
|
|
18
33
|
|
|
34
|
+
const loadMarketplaceStatistics = createMarketplaceStatisticsLoader();
|
|
35
|
+
|
|
19
36
|
function sendJson(response: ServerResponse, status: number, payload: unknown): void {
|
|
20
37
|
const body = JSON.stringify(payload);
|
|
21
38
|
response.writeHead(status, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", "content-length": Buffer.byteLength(body) });
|
|
@@ -54,6 +71,7 @@ function jsonSafe(value: unknown, seen = new WeakSet<object>()): unknown {
|
|
|
54
71
|
|
|
55
72
|
function createStatus(services: ApiServices, events: readonly AgentSessionEvent[]) {
|
|
56
73
|
const activeModel = services.runtime.session.model ?? services.models.model;
|
|
74
|
+
const cwd = activeCwd(services);
|
|
57
75
|
return {
|
|
58
76
|
status: services.runtime.session.isStreaming ? "running" : "ready",
|
|
59
77
|
model: activeModel.provider + "/" + activeModel.id,
|
|
@@ -61,21 +79,292 @@ function createStatus(services: ApiServices, events: readonly AgentSessionEvent[
|
|
|
61
79
|
events: events.length,
|
|
62
80
|
sessionId: services.runtime.session.sessionId,
|
|
63
81
|
sessionFile: services.runtime.session.sessionFile,
|
|
64
|
-
cwd
|
|
82
|
+
cwd,
|
|
65
83
|
agentDir: services.launch.agentDir,
|
|
66
84
|
plugins: services.loader ? [...services.loader.entries()].filter((entry) => !entry.disabled).map((entry) => entry.options.name) : [],
|
|
67
85
|
};
|
|
68
86
|
}
|
|
69
87
|
|
|
88
|
+
function activeCwd(services: ApiServices): string {
|
|
89
|
+
const runtimeCwd = services.runtime.sessionRuntime?.cwd;
|
|
90
|
+
return typeof runtimeCwd === "string" && runtimeCwd.length > 0 ? runtimeCwd : services.launch.cwd;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function piConfig(services: ApiServices) {
|
|
94
|
+
const settings = services.runtime.session.settingsManager;
|
|
95
|
+
const global = settings.getGlobalSettings();
|
|
96
|
+
const compaction = settings.getCompactionSettings();
|
|
97
|
+
return {
|
|
98
|
+
path: join(services.launch.agentDir, "settings.json"),
|
|
99
|
+
scope: "global" as const,
|
|
100
|
+
source: JSON.stringify(global, null, 2) + "\n",
|
|
101
|
+
settings: {
|
|
102
|
+
defaultProvider: global.defaultProvider,
|
|
103
|
+
defaultModel: global.defaultModel,
|
|
104
|
+
defaultThinkingLevel: global.defaultThinkingLevel,
|
|
105
|
+
transport: settings.getTransport(),
|
|
106
|
+
steeringMode: settings.getSteeringMode(),
|
|
107
|
+
followUpMode: settings.getFollowUpMode(),
|
|
108
|
+
hideThinkingBlock: settings.getHideThinkingBlock(),
|
|
109
|
+
compaction,
|
|
110
|
+
retry: settings.getRetrySettings(),
|
|
111
|
+
terminal: {
|
|
112
|
+
showImages: settings.getShowImages(),
|
|
113
|
+
imageAutoResize: settings.getImageAutoResize(),
|
|
114
|
+
autocompleteMaxVisible: settings.getAutocompleteMaxVisible(),
|
|
115
|
+
},
|
|
116
|
+
advanced: {
|
|
117
|
+
quietStartup: settings.getQuietStartup(),
|
|
118
|
+
projectTrust: settings.getDefaultProjectTrust(),
|
|
119
|
+
showCacheMissNotices: settings.getShowCacheMissNotices(),
|
|
120
|
+
enableAnalytics: settings.getEnableAnalytics(),
|
|
121
|
+
enableInstallTelemetry: settings.getEnableInstallTelemetry(),
|
|
122
|
+
shellPath: settings.getShellPath(),
|
|
123
|
+
doubleEscapeAction: settings.getDoubleEscapeAction(),
|
|
124
|
+
treeFilterMode: settings.getTreeFilterMode(),
|
|
125
|
+
mermaid: settings.getMermaidRenderingMode(),
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface SessionMetadata {
|
|
132
|
+
readonly archived?: boolean;
|
|
133
|
+
readonly pinned?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
type SessionMetadataMap = Record<string, SessionMetadata>;
|
|
137
|
+
|
|
138
|
+
function sessionMetadataFile(manager: SessionManager): string {
|
|
139
|
+
return resolve(manager.getSessionDir(), ".pi-harness-session-meta.json");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function readSessionMetadata(manager: SessionManager): Promise<SessionMetadataMap> {
|
|
143
|
+
try {
|
|
144
|
+
const parsed: unknown = JSON.parse(await readFile(sessionMetadataFile(manager), "utf8"));
|
|
145
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
146
|
+
return parsed as SessionMetadataMap;
|
|
147
|
+
} catch {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function writeSessionMetadata(manager: SessionManager, metadata: SessionMetadataMap): Promise<void> {
|
|
153
|
+
await mkdir(manager.getSessionDir(), { recursive: true });
|
|
154
|
+
await writeFile(sessionMetadataFile(manager), JSON.stringify(metadata, null, 2) + "\n", "utf8");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function sessionPathInDirectory(path: string, manager: SessionManager): boolean {
|
|
158
|
+
const root = resolve(manager.getSessionDir());
|
|
159
|
+
const target = resolve(path);
|
|
160
|
+
const relativePath = relative(root, target);
|
|
161
|
+
return relativePath !== "" && !isAbsolute(relativePath) && relativePath !== ".." && !relativePath.startsWith(".." + "/") && target.endsWith(".jsonl");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const webSessionUi = {
|
|
165
|
+
select: (_title: string, options: string[]) => Promise.resolve(options[0]),
|
|
166
|
+
confirm: () => Promise.resolve(true),
|
|
167
|
+
input: () => Promise.resolve(undefined),
|
|
168
|
+
notify: () => {},
|
|
169
|
+
onTerminalInput: () => () => {},
|
|
170
|
+
setStatus: () => {},
|
|
171
|
+
setWorkingMessage: () => {},
|
|
172
|
+
setWorkingVisible: () => {},
|
|
173
|
+
setWorkingIndicator: () => {},
|
|
174
|
+
setHiddenThinkingLabel: () => {},
|
|
175
|
+
setWidget: () => {},
|
|
176
|
+
setFooter: () => {},
|
|
177
|
+
setHeader: () => {},
|
|
178
|
+
setTitle: () => {},
|
|
179
|
+
} as unknown as ExtensionUIContext;
|
|
180
|
+
|
|
181
|
+
async function runWebSessionChange<T>(services: ApiServices, action: () => Promise<T & { cancelled: boolean }>): Promise<T & { cancelled: boolean }> {
|
|
182
|
+
const runner = services.runtime.session.extensionRunner;
|
|
183
|
+
runner.setUIContext(webSessionUi, "rpc");
|
|
184
|
+
try {
|
|
185
|
+
const result = await action();
|
|
186
|
+
if (result.cancelled) runner.setUIContext(undefined, "print");
|
|
187
|
+
return result;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
runner.setUIContext(undefined, "print");
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
70
194
|
function modelSummary(model: { provider: string; id: string; name?: string; reasoning?: boolean; contextWindow?: number }, active: boolean) {
|
|
71
|
-
return {
|
|
195
|
+
return {
|
|
196
|
+
provider: model.provider,
|
|
197
|
+
id: model.id,
|
|
198
|
+
name: model.name ?? model.id,
|
|
199
|
+
reasoning: model.reasoning ?? false,
|
|
200
|
+
contextWindow: model.contextWindow ?? null,
|
|
201
|
+
active,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function visibleProviderIds(
|
|
206
|
+
runtime: Pick<PiModelsService["runtime"], "getModels"> &
|
|
207
|
+
Partial<Pick<PiModelsService["runtime"], "getProviders" | "getProviderAuthStatus" | "getRegisteredProviderConfig">>,
|
|
208
|
+
activeProvider: string,
|
|
209
|
+
): Set<string> {
|
|
210
|
+
const providers = typeof runtime.getProviders === "function" ? runtime.getProviders() : [{ id: activeProvider, name: activeProvider }];
|
|
211
|
+
return new Set(
|
|
212
|
+
providers
|
|
213
|
+
.filter((provider) => {
|
|
214
|
+
if (provider.id === activeProvider) return true;
|
|
215
|
+
if (typeof runtime.getProviderAuthStatus !== "function") return false;
|
|
216
|
+
const auth = runtime.getProviderAuthStatus(provider.id);
|
|
217
|
+
if (typeof auth !== "object" || auth === null || (auth as { configured?: unknown }).configured !== true) return false;
|
|
218
|
+
if (typeof runtime.getRegisteredProviderConfig === "function") return runtime.getRegisteredProviderConfig(provider.id) !== undefined;
|
|
219
|
+
return true;
|
|
220
|
+
})
|
|
221
|
+
.map((provider) => provider.id),
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
type LoaderEntrySummary = { options: { id: string; name: string; disabled?: boolean | null }; fiber?: { state: unknown } };
|
|
226
|
+
|
|
227
|
+
function marketplacePluginForEntry(entry: LoaderEntrySummary): MarketplacePlugin | undefined {
|
|
228
|
+
return MARKETPLACE_PLUGINS.find((plugin) => plugin.packageName === entry.options.name);
|
|
72
229
|
}
|
|
73
230
|
|
|
74
|
-
function pluginSummary(entry:
|
|
231
|
+
function pluginSummary(entry: LoaderEntrySummary) {
|
|
75
232
|
const states = ["pending", "loading", "active", "failed", "disposed", "unloading"];
|
|
233
|
+
const marketplacePlugin = marketplacePluginForEntry(entry);
|
|
76
234
|
const rawState = entry.fiber?.state;
|
|
77
|
-
const state =
|
|
78
|
-
|
|
235
|
+
const state =
|
|
236
|
+
typeof rawState === "number"
|
|
237
|
+
? (states[rawState] ?? String(rawState))
|
|
238
|
+
: typeof rawState === "string"
|
|
239
|
+
? rawState
|
|
240
|
+
: rawState === undefined || rawState === null
|
|
241
|
+
? "unloaded"
|
|
242
|
+
: "unknown";
|
|
243
|
+
return {
|
|
244
|
+
id: entry.options.id,
|
|
245
|
+
name: entry.options.name,
|
|
246
|
+
enabled: !entry.options.disabled,
|
|
247
|
+
state,
|
|
248
|
+
removable: entry.options.id.startsWith("marketplace-") || marketplacePlugin !== undefined,
|
|
249
|
+
category: marketplacePlugin?.category,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function pluginLoaded(services: ApiServices, packageName: string): boolean {
|
|
254
|
+
return services.loader !== undefined && [...services.loader.entries()].some((entry) => entry.options.name === packageName && !entry.disabled);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function registerPluginPanels(context: Context, services: ApiServices): () => void {
|
|
258
|
+
if (services.pluginUi === undefined) return () => {};
|
|
259
|
+
const disposers = [
|
|
260
|
+
services.pluginUi.register({
|
|
261
|
+
id: "console-logger-panel",
|
|
262
|
+
pluginId: "@deepseek-ai/cordis-plugin-logger-console",
|
|
263
|
+
title: "运行时日志",
|
|
264
|
+
description: "查看最近的生命周期和运行时诊断输出。",
|
|
265
|
+
icon: "▤",
|
|
266
|
+
visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-logger-console"),
|
|
267
|
+
read: () => ({
|
|
268
|
+
total: context.logger.buffer.length,
|
|
269
|
+
items: context.logger.buffer.slice(-40).map((message) => ({
|
|
270
|
+
time: new Date(message.ts).toISOString(),
|
|
271
|
+
level: message.type,
|
|
272
|
+
source: message.name,
|
|
273
|
+
args: message.args,
|
|
274
|
+
})),
|
|
275
|
+
}),
|
|
276
|
+
}),
|
|
277
|
+
services.pluginUi.register({
|
|
278
|
+
id: "plugin-group-panel",
|
|
279
|
+
pluginId: "@deepseek-ai/cordis-plugin-group",
|
|
280
|
+
title: "插件树",
|
|
281
|
+
description: "查看当前运行时加载的插件树和生命周期状态。",
|
|
282
|
+
icon: "⌘",
|
|
283
|
+
visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-group"),
|
|
284
|
+
read: () => ({
|
|
285
|
+
entries:
|
|
286
|
+
services.loader === undefined
|
|
287
|
+
? []
|
|
288
|
+
: [...services.loader.entries()].map((entry) => ({
|
|
289
|
+
id: entry.id,
|
|
290
|
+
name: entry.options.name.replace(/^@deepseek-ai\/cordis-plugin-/i, "plugin-").replace(/^cordis:/i, "runtime:"),
|
|
291
|
+
state: pluginSummary(entry).state,
|
|
292
|
+
enabled: !entry.disabled,
|
|
293
|
+
})),
|
|
294
|
+
}),
|
|
295
|
+
}),
|
|
296
|
+
services.pluginUi.register({
|
|
297
|
+
id: "timer-service-panel",
|
|
298
|
+
pluginId: "@deepseek-ai/cordis-plugin-timer",
|
|
299
|
+
title: "定时器服务",
|
|
300
|
+
description: "确认定时器服务已注册,并查看可用的生命周期绑定 API。",
|
|
301
|
+
icon: "◷",
|
|
302
|
+
visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-timer"),
|
|
303
|
+
read: () => ({
|
|
304
|
+
registered: context.reflect.get("timer") !== undefined,
|
|
305
|
+
capabilities: ["timeout", "interval", "throttle", "debounce"],
|
|
306
|
+
}),
|
|
307
|
+
}),
|
|
308
|
+
];
|
|
309
|
+
return () => disposers.reverse().forEach((dispose) => dispose());
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function runProcess(executable: string, args: readonly string[], cwd: string): Promise<{ stdout: string; stderr: string }> {
|
|
313
|
+
return new Promise((resolveProcess, rejectProcess) => {
|
|
314
|
+
execFile(executable, [...args], { cwd, timeout: 120_000, maxBuffer: 2 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
315
|
+
if (error) {
|
|
316
|
+
rejectProcess(new Error(`${executable} ${args.join(" ")} failed: ${stderr || error.message}`, { cause: error }));
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
resolveProcess({ stdout, stderr });
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async function appendMarketplaceProfile(configPath: string, plugin: MarketplacePlugin): Promise<string> {
|
|
325
|
+
const source = await readFile(configPath, "utf8");
|
|
326
|
+
if (source.includes(`name: ${JSON.stringify(plugin.packageName)}`)) return source;
|
|
327
|
+
const entryId = `marketplace-${plugin.id}`;
|
|
328
|
+
const config = JSON.stringify(plugin.profile.config);
|
|
329
|
+
const group = plugin.profile.group === true ? "\n group: true" : "";
|
|
330
|
+
const entry = `\n- id: ${entryId}\n name: ${JSON.stringify(plugin.packageName)}${group}\n config: ${config}\n`;
|
|
331
|
+
await writeFile(configPath, source.replace(/\s*$/, "") + entry, "utf8");
|
|
332
|
+
return source;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async function updateMarketplaceProfile(configPath: string, entryId: string, update: { disabled?: boolean; remove?: boolean }): Promise<string> {
|
|
336
|
+
const source = await readFile(configPath, "utf8");
|
|
337
|
+
const escapedId = entryId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
338
|
+
const pattern = new RegExp(`^([ \\t]*)- id: ${escapedId}[ \\t]*(?:\\r?\\n|$)`, "m");
|
|
339
|
+
const match = source.match(pattern);
|
|
340
|
+
if (match === null) throw new Error(`Installed plugin profile entry was not found: ${entryId}`);
|
|
341
|
+
const indent = match[1] ?? "";
|
|
342
|
+
const start = match.index ?? 0;
|
|
343
|
+
let end = source.length;
|
|
344
|
+
const linePattern = /^([ \t]*)(?=\S)/gm;
|
|
345
|
+
linePattern.lastIndex = start + match[0].length;
|
|
346
|
+
for (let line = linePattern.exec(source); line !== null; line = linePattern.exec(source)) {
|
|
347
|
+
const lineIndent = line[1] ?? "";
|
|
348
|
+
const content = source.slice(line.index + lineIndent.length);
|
|
349
|
+
if (lineIndent.length < indent.length || (lineIndent === indent && content.startsWith("- "))) {
|
|
350
|
+
end = line.index;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const originalBlock = source.slice(start, end);
|
|
355
|
+
if (update.remove === true) {
|
|
356
|
+
await writeFile(configPath, source.slice(0, start) + source.slice(end), "utf8");
|
|
357
|
+
return source;
|
|
358
|
+
}
|
|
359
|
+
const childIndent = `${indent} `;
|
|
360
|
+
const disabledPattern = new RegExp(`^${childIndent}disabled: .*\\r?\\n`, "m");
|
|
361
|
+
let block = originalBlock.replace(disabledPattern, "");
|
|
362
|
+
if (update.disabled === true) {
|
|
363
|
+
const namePattern = new RegExp(`^(${childIndent}name: .*\\r?\\n)`, "m");
|
|
364
|
+
block = block.replace(namePattern, `$1${childIndent}disabled: true\n`);
|
|
365
|
+
}
|
|
366
|
+
await writeFile(configPath, source.slice(0, start) + block + source.slice(end), "utf8");
|
|
367
|
+
return source;
|
|
79
368
|
}
|
|
80
369
|
|
|
81
370
|
function writeSse(response: ServerResponse, payload: unknown): void {
|
|
@@ -90,7 +379,9 @@ function gitStatus(cwd: string): Promise<string> {
|
|
|
90
379
|
|
|
91
380
|
function gitDiff(cwd: string, path: string): Promise<string> {
|
|
92
381
|
return new Promise((resolveOutput) => {
|
|
93
|
-
execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, maxBuffer: 1024 * 1024 }, (error, stdout) =>
|
|
382
|
+
execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, maxBuffer: 1024 * 1024 }, (error, stdout) =>
|
|
383
|
+
resolveOutput(error && stdout.length === 0 ? "" : stdout),
|
|
384
|
+
);
|
|
94
385
|
});
|
|
95
386
|
}
|
|
96
387
|
|
|
@@ -103,8 +394,62 @@ function gitCommand(cwd: string, args: readonly string[]): Promise<{ stdout: str
|
|
|
103
394
|
});
|
|
104
395
|
}
|
|
105
396
|
|
|
397
|
+
interface EveryApiCliAuthStatus {
|
|
398
|
+
configured: false;
|
|
399
|
+
source: "everyapi-cli";
|
|
400
|
+
label: string;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function probeEveryApiCliAuth(): Promise<EveryApiCliAuthStatus> {
|
|
404
|
+
const executable = process.env.EVERYAPI_CLI_PATH?.trim() || "everyapi";
|
|
405
|
+
return new Promise((resolveStatus) => {
|
|
406
|
+
execFile(executable, ["auth", "status"], { timeout: 3_000, maxBuffer: 128 * 1024 }, (error) => {
|
|
407
|
+
resolveStatus({
|
|
408
|
+
configured: false,
|
|
409
|
+
source: "everyapi-cli",
|
|
410
|
+
label: error ? "未检测到 EveryAPI CLI 登录" : "EveryAPI CLI 已登录,但 relay key 未注入当前进程",
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
async function listWorkspaces(cwd: string): Promise<readonly WorkspaceSummary[]> {
|
|
417
|
+
const result = await gitCommand(cwd, ["worktree", "list", "--porcelain"]);
|
|
418
|
+
const parsed = result.code === 0 ? parseGitWorktrees(result.stdout, cwd) : [];
|
|
419
|
+
if (parsed.some((item) => item.current)) return parsed;
|
|
420
|
+
return [{ path: resolve(cwd), branch: "current", current: true, name: resolve(cwd).split("/").pop() ?? resolve(cwd) }, ...parsed];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
async function isDirectory(path: string): Promise<boolean> {
|
|
424
|
+
try {
|
|
425
|
+
return (await stat(path)).isDirectory();
|
|
426
|
+
} catch {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function pickDirectory(): Promise<string> {
|
|
432
|
+
return new Promise((resolvePath, reject) => {
|
|
433
|
+
execFile(
|
|
434
|
+
"osascript",
|
|
435
|
+
["-e", 'POSIX path of (choose folder with prompt "选择 Pi 工作区")'],
|
|
436
|
+
{ timeout: 120_000, maxBuffer: 64 * 1024 },
|
|
437
|
+
(error, stdout, stderr) => {
|
|
438
|
+
if (error) {
|
|
439
|
+
reject(new Error(stderr.trim() || "目录选择已取消"));
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const path = stdout.trim();
|
|
443
|
+
if (!path) reject(new Error("目录选择已取消"));
|
|
444
|
+
else resolvePath(path);
|
|
445
|
+
},
|
|
446
|
+
);
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
106
450
|
function workspacePaths(root: string, paths: unknown): string[] | Error {
|
|
107
|
-
if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || path.trim() === ""))
|
|
451
|
+
if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || path.trim() === ""))
|
|
452
|
+
return new Error("paths must be a non-empty array of strings");
|
|
108
453
|
const normalized: string[] = [];
|
|
109
454
|
for (const path of paths) {
|
|
110
455
|
const requested = path as string;
|
|
@@ -121,12 +466,14 @@ export default {
|
|
|
121
466
|
inject: ["webServer", "piRuntime", "piModels", "piHarnessLaunch"],
|
|
122
467
|
apply(context: Context) {
|
|
123
468
|
const services: ApiServices = {
|
|
124
|
-
runtime: context.piRuntime,
|
|
125
|
-
models: context.piModels,
|
|
126
|
-
launch: context.piHarnessLaunch,
|
|
469
|
+
runtime: context.reflect.get("piRuntime") as PiRuntimeService,
|
|
470
|
+
models: context.reflect.get("piModels") as PiModelsService,
|
|
471
|
+
launch: context.reflect.get("piHarnessLaunch") as PiHarnessLaunch,
|
|
127
472
|
webServer: context.webServer,
|
|
128
473
|
loader: context.reflect.get("loader") as Loader | undefined,
|
|
474
|
+
pluginUi: context.reflect.get("piPluginUi") as PiPluginUiRegistry | undefined,
|
|
129
475
|
};
|
|
476
|
+
const disposePluginPanels = registerPluginPanels(context, services);
|
|
130
477
|
let busy = false;
|
|
131
478
|
const events: AgentSessionEvent[] = [];
|
|
132
479
|
const eventClients = new Set<ServerResponse>();
|
|
@@ -141,7 +488,7 @@ export default {
|
|
|
141
488
|
}
|
|
142
489
|
};
|
|
143
490
|
const unsubscribeEvents = services.runtime.sessionRuntime
|
|
144
|
-
? context.on("pi/session-event", handleEvent)
|
|
491
|
+
? context.on("pi/session-event" as never, handleEvent as never)
|
|
145
492
|
: services.runtime.session.subscribe(handleEvent);
|
|
146
493
|
const disposeStatus = services.webServer.register({
|
|
147
494
|
path: "/api/status",
|
|
@@ -149,26 +496,238 @@ export default {
|
|
|
149
496
|
sendJson(response, 200, createStatus(services, events));
|
|
150
497
|
},
|
|
151
498
|
});
|
|
499
|
+
const disposeConfig = services.webServer.register({
|
|
500
|
+
path: "/api/config",
|
|
501
|
+
async handler(request, response) {
|
|
502
|
+
if (request.method === "GET") {
|
|
503
|
+
sendJson(response, 200, piConfig(services));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
if (request.method !== "POST") {
|
|
507
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
try {
|
|
511
|
+
const payload = JSON.parse(await bodyText(request)) as Record<string, unknown>;
|
|
512
|
+
const settings = services.runtime.session.settingsManager;
|
|
513
|
+
if (typeof payload.defaultProvider === "string" && payload.defaultProvider.trim()) settings.setDefaultProvider(payload.defaultProvider.trim());
|
|
514
|
+
if (typeof payload.defaultModel === "string" && payload.defaultModel.trim()) settings.setDefaultModel(payload.defaultModel.trim());
|
|
515
|
+
if (
|
|
516
|
+
payload.defaultThinkingLevel === "off" ||
|
|
517
|
+
payload.defaultThinkingLevel === "minimal" ||
|
|
518
|
+
payload.defaultThinkingLevel === "low" ||
|
|
519
|
+
payload.defaultThinkingLevel === "medium" ||
|
|
520
|
+
payload.defaultThinkingLevel === "high" ||
|
|
521
|
+
payload.defaultThinkingLevel === "xhigh" ||
|
|
522
|
+
payload.defaultThinkingLevel === "max"
|
|
523
|
+
)
|
|
524
|
+
settings.setDefaultThinkingLevel(payload.defaultThinkingLevel);
|
|
525
|
+
if (payload.transport === "sse" || payload.transport === "websocket" || payload.transport === "auto") settings.setTransport(payload.transport);
|
|
526
|
+
if (payload.steeringMode === "all" || payload.steeringMode === "one-at-a-time") settings.setSteeringMode(payload.steeringMode);
|
|
527
|
+
if (payload.followUpMode === "all" || payload.followUpMode === "one-at-a-time") settings.setFollowUpMode(payload.followUpMode);
|
|
528
|
+
if (typeof payload.hideThinkingBlock === "boolean") settings.setHideThinkingBlock(payload.hideThinkingBlock);
|
|
529
|
+
if (typeof payload.retry === "object" && payload.retry !== null) {
|
|
530
|
+
const retry = payload.retry as Record<string, unknown>;
|
|
531
|
+
if (typeof retry.enabled === "boolean") settings.setRetryEnabled(retry.enabled);
|
|
532
|
+
}
|
|
533
|
+
if (typeof payload.terminal === "object" && payload.terminal !== null) {
|
|
534
|
+
const terminal = payload.terminal as Record<string, unknown>;
|
|
535
|
+
if (typeof terminal.showImages === "boolean") settings.setShowImages(terminal.showImages);
|
|
536
|
+
if (typeof terminal.imageAutoResize === "boolean") settings.setImageAutoResize(terminal.imageAutoResize);
|
|
537
|
+
if (typeof terminal.autocompleteMaxVisible === "number" && Number.isInteger(terminal.autocompleteMaxVisible))
|
|
538
|
+
settings.setAutocompleteMaxVisible(Math.min(20, Math.max(3, terminal.autocompleteMaxVisible)));
|
|
539
|
+
}
|
|
540
|
+
if (typeof payload.advanced === "object" && payload.advanced !== null) {
|
|
541
|
+
const advanced = payload.advanced as Record<string, unknown>;
|
|
542
|
+
if (typeof advanced.quietStartup === "boolean") settings.setQuietStartup(advanced.quietStartup);
|
|
543
|
+
if (advanced.projectTrust === "ask" || advanced.projectTrust === "always" || advanced.projectTrust === "never")
|
|
544
|
+
settings.setDefaultProjectTrust(advanced.projectTrust);
|
|
545
|
+
if (typeof advanced.showCacheMissNotices === "boolean") settings.setShowCacheMissNotices(advanced.showCacheMissNotices);
|
|
546
|
+
if (typeof advanced.enableInstallTelemetry === "boolean") settings.setEnableInstallTelemetry(advanced.enableInstallTelemetry);
|
|
547
|
+
if (typeof advanced.shellPath === "string") settings.setShellPath(advanced.shellPath.trim() || undefined);
|
|
548
|
+
if (advanced.doubleEscapeAction === "fork" || advanced.doubleEscapeAction === "tree" || advanced.doubleEscapeAction === "none")
|
|
549
|
+
settings.setDoubleEscapeAction(advanced.doubleEscapeAction);
|
|
550
|
+
if (
|
|
551
|
+
advanced.treeFilterMode === "default" ||
|
|
552
|
+
advanced.treeFilterMode === "no-tools" ||
|
|
553
|
+
advanced.treeFilterMode === "user-only" ||
|
|
554
|
+
advanced.treeFilterMode === "labeled-only" ||
|
|
555
|
+
advanced.treeFilterMode === "all"
|
|
556
|
+
)
|
|
557
|
+
settings.setTreeFilterMode(advanced.treeFilterMode);
|
|
558
|
+
if (advanced.mermaid === "off" || advanced.mermaid === "final" || advanced.mermaid === "streaming")
|
|
559
|
+
settings.setMermaidRenderingMode(advanced.mermaid);
|
|
560
|
+
}
|
|
561
|
+
if (
|
|
562
|
+
typeof payload.compaction === "object" &&
|
|
563
|
+
payload.compaction !== null &&
|
|
564
|
+
typeof (payload.compaction as Record<string, unknown>).enabled === "boolean"
|
|
565
|
+
)
|
|
566
|
+
settings.setCompactionEnabled((payload.compaction as Record<string, boolean>).enabled === true);
|
|
567
|
+
await settings.flush();
|
|
568
|
+
sendJson(response, 200, piConfig(services));
|
|
569
|
+
} catch (error) {
|
|
570
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
});
|
|
574
|
+
const disposeConfigReload = services.webServer.register({
|
|
575
|
+
path: "/api/config/reload",
|
|
576
|
+
async handler(request, response) {
|
|
577
|
+
if (request.method !== "POST") {
|
|
578
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
try {
|
|
582
|
+
await services.runtime.session.settingsManager.reload();
|
|
583
|
+
sendJson(response, 200, piConfig(services));
|
|
584
|
+
} catch (error) {
|
|
585
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
});
|
|
589
|
+
const disposeConfigSource = services.webServer.register({
|
|
590
|
+
path: "/api/config/source",
|
|
591
|
+
async handler(request, response) {
|
|
592
|
+
if (request.method !== "POST") {
|
|
593
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
const payload = JSON.parse(await bodyText(request)) as { source?: unknown };
|
|
598
|
+
if (typeof payload.source !== "string" || payload.source.length > 128 * 1024) {
|
|
599
|
+
sendJson(response, 400, { error: "source must be a JSON document smaller than 128 KiB" });
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
const parsed: unknown = JSON.parse(payload.source);
|
|
603
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
604
|
+
sendJson(response, 400, { error: "settings source must contain a JSON object" });
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
const path = join(services.launch.agentDir, "settings.json");
|
|
608
|
+
await writeFile(path, JSON.stringify(parsed, null, 2) + "\n", "utf8");
|
|
609
|
+
await services.runtime.session.settingsManager.reload();
|
|
610
|
+
sendJson(response, 200, piConfig(services));
|
|
611
|
+
} catch (error) {
|
|
612
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
});
|
|
152
616
|
const disposeModels = services.webServer.register({
|
|
153
617
|
path: "/api/models",
|
|
154
618
|
handler(_request, response) {
|
|
155
619
|
const active = services.runtime.session.model ?? services.models.model;
|
|
156
|
-
|
|
620
|
+
const visible = visibleProviderIds(services.models.runtime, active.provider);
|
|
621
|
+
sendJson(
|
|
622
|
+
response,
|
|
623
|
+
200,
|
|
624
|
+
jsonSafe({
|
|
625
|
+
items: services.models.runtime
|
|
626
|
+
.getModels()
|
|
627
|
+
.filter((model) => visible.has(model.provider))
|
|
628
|
+
.map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)),
|
|
629
|
+
}),
|
|
630
|
+
);
|
|
157
631
|
},
|
|
158
632
|
});
|
|
159
633
|
const disposeProviders = services.webServer.register({
|
|
160
634
|
path: "/api/providers",
|
|
161
635
|
handler(_request, response) {
|
|
162
636
|
const active = services.runtime.session.model ?? services.models.model;
|
|
163
|
-
const runtime = services.models.runtime as typeof services.models.runtime & {
|
|
637
|
+
const runtime = services.models.runtime as typeof services.models.runtime & {
|
|
638
|
+
getProviders?: () => readonly { id: string; name?: string }[];
|
|
639
|
+
getProviderAuthStatus?: (provider: string) => unknown;
|
|
640
|
+
};
|
|
164
641
|
const providers = typeof runtime.getProviders === "function" ? runtime.getProviders() : [{ id: active.provider, name: active.provider }];
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
642
|
+
const visibleIds = visibleProviderIds(runtime, active.provider);
|
|
643
|
+
const visible = providers.filter((provider) => visibleIds.has(provider.id));
|
|
644
|
+
sendJson(
|
|
645
|
+
response,
|
|
646
|
+
200,
|
|
647
|
+
jsonSafe({
|
|
648
|
+
items: visible.map((provider) => ({
|
|
649
|
+
provider: provider.id,
|
|
650
|
+
name: provider.name ?? provider.id,
|
|
651
|
+
active: provider.id === active.provider,
|
|
652
|
+
auth: typeof runtime.getProviderAuthStatus === "function" ? runtime.getProviderAuthStatus(provider.id) : undefined,
|
|
653
|
+
activeModel: provider.id === active.provider ? modelSummary(active, true) : undefined,
|
|
654
|
+
models: services.models.runtime
|
|
655
|
+
.getModels(provider.id)
|
|
656
|
+
.map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)),
|
|
657
|
+
})),
|
|
658
|
+
}),
|
|
659
|
+
);
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
const disposeProviderAdd = services.webServer.register({
|
|
663
|
+
path: "/api/providers/add",
|
|
664
|
+
async handler(request, response) {
|
|
665
|
+
if (request.method !== "POST") {
|
|
666
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
try {
|
|
670
|
+
const payload = JSON.parse(await bodyText(request)) as {
|
|
671
|
+
provider?: unknown;
|
|
672
|
+
name?: unknown;
|
|
673
|
+
baseUrl?: unknown;
|
|
674
|
+
api?: unknown;
|
|
675
|
+
apiKey?: unknown;
|
|
676
|
+
model?: unknown;
|
|
677
|
+
};
|
|
678
|
+
const provider = typeof payload.provider === "string" ? payload.provider.trim() : "";
|
|
679
|
+
const name = typeof payload.name === "string" && payload.name.trim() !== "" ? payload.name.trim() : provider;
|
|
680
|
+
const baseUrl = typeof payload.baseUrl === "string" ? payload.baseUrl.trim() : "";
|
|
681
|
+
const apiKey = typeof payload.apiKey === "string" ? payload.apiKey.trim() : "";
|
|
682
|
+
const model = typeof payload.model === "string" ? payload.model.trim() : "";
|
|
683
|
+
const api = payload.api === "openai-responses" ? "openai-responses" : "openai-completions";
|
|
684
|
+
if (!/^[a-z0-9][a-z0-9._-]{1,63}$/i.test(provider)) {
|
|
685
|
+
sendJson(response, 400, { error: "provider must be 2-64 characters using letters, numbers, ., _, or -" });
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (!/^https?:\/\/[^\s]+$/i.test(baseUrl)) {
|
|
689
|
+
sendJson(response, 400, { error: "baseUrl must be an http(s) URL" });
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (!apiKey || !model) {
|
|
693
|
+
sendJson(response, 400, { error: "apiKey and model are required" });
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const runtime = services.models.runtime;
|
|
697
|
+
if (runtime.getProvider(provider) !== undefined) {
|
|
698
|
+
sendJson(response, 409, { error: `Provider already exists: ${provider}` });
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
runtime.registerProvider(provider, {
|
|
702
|
+
name,
|
|
703
|
+
baseUrl,
|
|
704
|
+
api,
|
|
705
|
+
models: [
|
|
706
|
+
{
|
|
707
|
+
id: model,
|
|
708
|
+
name: model,
|
|
709
|
+
api,
|
|
710
|
+
reasoning: false,
|
|
711
|
+
input: ["text"],
|
|
712
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
713
|
+
contextWindow: 128000,
|
|
714
|
+
maxTokens: 8192,
|
|
715
|
+
},
|
|
716
|
+
],
|
|
717
|
+
});
|
|
718
|
+
await runtime.setRuntimeApiKey(provider, apiKey);
|
|
719
|
+
sendJson(response, 201, {
|
|
720
|
+
provider: {
|
|
721
|
+
provider,
|
|
722
|
+
name,
|
|
723
|
+
active: false,
|
|
724
|
+
auth: runtime.getProviderAuthStatus(provider),
|
|
725
|
+
models: runtime.getModels(provider).map((item) => modelSummary(item, false)),
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
} catch (error) {
|
|
729
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
730
|
+
}
|
|
172
731
|
},
|
|
173
732
|
});
|
|
174
733
|
const disposeProviderTest = services.webServer.register({
|
|
@@ -190,6 +749,11 @@ export default {
|
|
|
190
749
|
return;
|
|
191
750
|
}
|
|
192
751
|
const auth = await runtime.checkAuth(payload.provider);
|
|
752
|
+
if (payload.provider === "everyapi" && auth === undefined && !process.env.EVERYAPI_RELAY_KEY?.trim()) {
|
|
753
|
+
const cliAuth = await probeEveryApiCliAuth();
|
|
754
|
+
sendJson(response, 200, { provider: payload.provider, reachable: false, auth: cliAuth });
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
193
757
|
sendJson(response, 200, jsonSafe({ provider: payload.provider, reachable: auth !== undefined, auth }));
|
|
194
758
|
} catch (error) {
|
|
195
759
|
sendJson(response, 502, { error: errorText(error) });
|
|
@@ -228,14 +792,289 @@ export default {
|
|
|
228
792
|
sendJson(response, 200, jsonSafe({ items }));
|
|
229
793
|
},
|
|
230
794
|
});
|
|
795
|
+
const disposePluginUi = services.webServer.register({
|
|
796
|
+
path: "/api/plugin-ui",
|
|
797
|
+
async handler(request, response) {
|
|
798
|
+
if (request.method !== "GET") {
|
|
799
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
const items = services.pluginUi === undefined ? [] : await services.pluginUi.snapshot();
|
|
804
|
+
sendJson(response, 200, jsonSafe({ items }));
|
|
805
|
+
} catch (error) {
|
|
806
|
+
sendJson(response, 500, { error: errorText(error) });
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
});
|
|
810
|
+
const disposeMarketplace = services.webServer.register({
|
|
811
|
+
path: "/api/marketplace",
|
|
812
|
+
async handler(request, response) {
|
|
813
|
+
if (request.method !== "GET") {
|
|
814
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
const url = new URL(request.url ?? "/api/marketplace", "http://localhost");
|
|
818
|
+
const query = url.searchParams.get("q") ?? "";
|
|
819
|
+
const capability = url.searchParams.get("capability") ?? "";
|
|
820
|
+
const category = url.searchParams.get("category") ?? "";
|
|
821
|
+
const page = Number(url.searchParams.get("page") ?? "0");
|
|
822
|
+
const pageSize = Number(url.searchParams.get("pageSize") ?? "24");
|
|
823
|
+
const sort = url.searchParams.get("sort") ?? "";
|
|
824
|
+
if (
|
|
825
|
+
query.length > 120 ||
|
|
826
|
+
capability.length > 80 ||
|
|
827
|
+
category.length > 80 ||
|
|
828
|
+
!Number.isInteger(page) ||
|
|
829
|
+
page < 0 ||
|
|
830
|
+
!Number.isInteger(pageSize) ||
|
|
831
|
+
pageSize < 1 ||
|
|
832
|
+
pageSize > 100 ||
|
|
833
|
+
(sort !== "" && sort !== "recommended")
|
|
834
|
+
) {
|
|
835
|
+
sendJson(response, 400, { error: "Invalid marketplace query" });
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
const filtered = searchMarketplace(query, capability, category);
|
|
839
|
+
const items =
|
|
840
|
+
sort === "recommended"
|
|
841
|
+
? sortMarketplaceByRecommendation(attachMarketplaceStatistics(filtered, await loadMarketplaceStatistics(MARKETPLACE_PLUGINS)))
|
|
842
|
+
: filtered;
|
|
843
|
+
sendJson(response, 200, {
|
|
844
|
+
...paginateMarketplace(items, page, pageSize),
|
|
845
|
+
capabilities: MARKETPLACE_CAPABILITIES,
|
|
846
|
+
categories: MARKETPLACE_CATEGORIES,
|
|
847
|
+
});
|
|
848
|
+
},
|
|
849
|
+
});
|
|
850
|
+
let marketplaceMutationInFlight = false;
|
|
851
|
+
const disposeMarketplaceInstall = services.webServer.register({
|
|
852
|
+
path: "/api/marketplace/install",
|
|
853
|
+
async handler(request, response) {
|
|
854
|
+
if (request.method !== "POST") {
|
|
855
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
if (marketplaceMutationInFlight) {
|
|
859
|
+
sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const loader = services.loader;
|
|
863
|
+
const configPath = services.launch.configPath;
|
|
864
|
+
if (loader === undefined || configPath === undefined) {
|
|
865
|
+
sendJson(response, 501, { error: "Plugin installation is unavailable for this runtime" });
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
marketplaceMutationInFlight = true;
|
|
869
|
+
try {
|
|
870
|
+
const payload = JSON.parse(await bodyText(request)) as { id?: unknown };
|
|
871
|
+
if (typeof payload.id !== "string" || payload.id.trim() === "") {
|
|
872
|
+
sendJson(response, 400, { error: "id is required" });
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === payload.id);
|
|
876
|
+
if (plugin === undefined) {
|
|
877
|
+
sendJson(response, 404, { error: "Marketplace plugin was not found" });
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
const existing = [...loader.entries()].find((entry) => entry.options.name === plugin.packageName);
|
|
881
|
+
if (existing !== undefined) {
|
|
882
|
+
sendJson(response, 409, { error: "Plugin is already installed", plugin });
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
const packageJsonPath = join(services.launch.cwd, "package.json");
|
|
886
|
+
const packageLockPath = join(services.launch.cwd, "package-lock.json");
|
|
887
|
+
const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
|
|
888
|
+
const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
|
|
889
|
+
let profileBefore: string | undefined;
|
|
890
|
+
let entryId: string | undefined;
|
|
891
|
+
try {
|
|
892
|
+
if (needsMarketplacePackageInstall(plugin)) {
|
|
893
|
+
await runProcess("npm", ["install", "--save-exact", "--package-lock=false", `${plugin.packageName}@${plugin.version}`], services.launch.cwd);
|
|
894
|
+
}
|
|
895
|
+
profileBefore = await appendMarketplaceProfile(configPath, plugin);
|
|
896
|
+
if (!needsMarketplacePackageInstall(plugin)) {
|
|
897
|
+
sendJson(response, 200, { plugin, installed: false, restartRequired: true });
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
entryId = await loader.create({
|
|
901
|
+
id: `marketplace-${plugin.id}`,
|
|
902
|
+
name: plugin.packageName,
|
|
903
|
+
...(plugin.profile.group === true ? { group: true } : {}),
|
|
904
|
+
config: plugin.profile.config,
|
|
905
|
+
} as never);
|
|
906
|
+
const entry = loader.resolve(entryId);
|
|
907
|
+
if (entry.fiber === undefined) throw new Error(`Plugin ${plugin.packageName} did not create a runtime fiber`);
|
|
908
|
+
await entry.fiber.await();
|
|
909
|
+
sendJson(response, 200, { plugin, installed: true });
|
|
910
|
+
} catch (error) {
|
|
911
|
+
if (entryId !== undefined) await loader.remove(entryId).catch(() => {});
|
|
912
|
+
if (profileBefore !== undefined) await writeFile(configPath, profileBefore, "utf8").catch(() => {});
|
|
913
|
+
if (packageJsonBefore !== undefined) await writeFile(packageJsonPath, packageJsonBefore, "utf8").catch(() => {});
|
|
914
|
+
if (packageLockBefore !== undefined) await writeFile(packageLockPath, packageLockBefore, "utf8").catch(() => {});
|
|
915
|
+
sendJson(response, 502, { error: errorText(error) });
|
|
916
|
+
}
|
|
917
|
+
} catch (error) {
|
|
918
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
919
|
+
} finally {
|
|
920
|
+
marketplaceMutationInFlight = false;
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
});
|
|
924
|
+
const disposePluginToggle = services.webServer.register({
|
|
925
|
+
path: "/api/plugins/toggle",
|
|
926
|
+
async handler(request, response) {
|
|
927
|
+
if (request.method !== "POST") {
|
|
928
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
const configPath = services.launch.configPath;
|
|
932
|
+
const loader = services.loader;
|
|
933
|
+
if (configPath === undefined || loader === undefined) {
|
|
934
|
+
sendJson(response, 501, { error: "Plugin configuration is unavailable for this runtime" });
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (marketplaceMutationInFlight) {
|
|
938
|
+
sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
marketplaceMutationInFlight = true;
|
|
942
|
+
try {
|
|
943
|
+
const payload = JSON.parse(await bodyText(request)) as { id?: unknown; enabled?: unknown };
|
|
944
|
+
if (typeof payload.id !== "string" || typeof payload.enabled !== "boolean") {
|
|
945
|
+
sendJson(response, 400, { error: "A marketplace plugin id and enabled boolean are required" });
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const entry = [...loader.entries()].find((item) => item.id === payload.id || item.options.id === payload.id);
|
|
949
|
+
if (entry === undefined) {
|
|
950
|
+
sendJson(response, 404, { error: "Installed plugin was not found" });
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const plugin = marketplacePluginForEntry(entry);
|
|
954
|
+
if (plugin === undefined) {
|
|
955
|
+
sendJson(response, 403, { error: "Built-in plugins cannot be changed" });
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
const profileEntryId = entry.options.id;
|
|
959
|
+
const before = await updateMarketplaceProfile(configPath, profileEntryId, { disabled: !payload.enabled });
|
|
960
|
+
try {
|
|
961
|
+
await entry.update({ disabled: !payload.enabled });
|
|
962
|
+
sendJson(response, 200, { plugin: pluginSummary(entry) });
|
|
963
|
+
} catch (error) {
|
|
964
|
+
await writeFile(configPath, before, "utf8").catch(() => {});
|
|
965
|
+
sendJson(response, 502, { error: errorText(error) });
|
|
966
|
+
}
|
|
967
|
+
} catch (error) {
|
|
968
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
969
|
+
} finally {
|
|
970
|
+
marketplaceMutationInFlight = false;
|
|
971
|
+
}
|
|
972
|
+
},
|
|
973
|
+
});
|
|
974
|
+
const disposePluginUninstall = services.webServer.register({
|
|
975
|
+
path: "/api/plugins/uninstall",
|
|
976
|
+
async handler(request, response) {
|
|
977
|
+
if (request.method !== "POST") {
|
|
978
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
const configPath = services.launch.configPath;
|
|
982
|
+
const loader = services.loader;
|
|
983
|
+
if (configPath === undefined || loader === undefined) {
|
|
984
|
+
sendJson(response, 501, { error: "Plugin configuration is unavailable for this runtime" });
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
if (marketplaceMutationInFlight) {
|
|
988
|
+
sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
marketplaceMutationInFlight = true;
|
|
992
|
+
try {
|
|
993
|
+
const payload = JSON.parse(await bodyText(request)) as { id?: unknown };
|
|
994
|
+
if (typeof payload.id !== "string") {
|
|
995
|
+
sendJson(response, 400, { error: "A marketplace plugin id is required" });
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
const entry = [...loader.entries()].find((item) => item.id === payload.id || item.options.id === payload.id);
|
|
999
|
+
if (entry === undefined) {
|
|
1000
|
+
sendJson(response, 404, { error: "Installed plugin was not found" });
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
const plugin = marketplacePluginForEntry(entry);
|
|
1004
|
+
if (plugin === undefined) {
|
|
1005
|
+
sendJson(response, 403, { error: "Only marketplace plugins can be uninstalled" });
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
const profileEntryId = entry.options.id;
|
|
1009
|
+
const profileBefore = await readFile(configPath, "utf8");
|
|
1010
|
+
const packageJsonPath = join(services.launch.cwd, "package.json");
|
|
1011
|
+
const packageLockPath = join(services.launch.cwd, "package-lock.json");
|
|
1012
|
+
const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
|
|
1013
|
+
const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
|
|
1014
|
+
await entry.parent.remove(entry.options.id);
|
|
1015
|
+
entry.parent.tree.write();
|
|
1016
|
+
try {
|
|
1017
|
+
await updateMarketplaceProfile(configPath, profileEntryId, { remove: true });
|
|
1018
|
+
if (needsMarketplacePackageInstall(plugin)) await runProcess("npm", ["uninstall", "--package-lock=false", plugin.packageName], services.launch.cwd);
|
|
1019
|
+
sendJson(response, 200, { uninstalled: true, id: payload.id });
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
await writeFile(configPath, profileBefore, "utf8").catch(() => {});
|
|
1022
|
+
if (packageJsonBefore !== undefined) await writeFile(packageJsonPath, packageJsonBefore, "utf8").catch(() => {});
|
|
1023
|
+
if (packageLockBefore !== undefined) await writeFile(packageLockPath, packageLockBefore, "utf8").catch(() => {});
|
|
1024
|
+
const options = entry.options as { name: string; config?: unknown; group?: boolean | null };
|
|
1025
|
+
await loader
|
|
1026
|
+
.create({ id: entry.options.id, name: options.name, config: options.config, ...(options.group ? { group: true } : {}) } as never)
|
|
1027
|
+
.catch(() => {});
|
|
1028
|
+
sendJson(response, 502, { error: errorText(error) });
|
|
1029
|
+
}
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1032
|
+
} finally {
|
|
1033
|
+
marketplaceMutationInFlight = false;
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
});
|
|
231
1037
|
const disposeCommands = services.webServer.register({
|
|
232
1038
|
path: "/api/commands",
|
|
233
1039
|
handler(_request, response) {
|
|
234
1040
|
const commands = services.runtime.session.extensionRunner.getRegisteredCommands();
|
|
235
|
-
const items = commands.map((command) => ({
|
|
1041
|
+
const items = commands.map((command) => ({
|
|
1042
|
+
name: command.name,
|
|
1043
|
+
invocationName: command.invocationName,
|
|
1044
|
+
description: command.description,
|
|
1045
|
+
source: command.sourceInfo.path,
|
|
1046
|
+
}));
|
|
236
1047
|
sendJson(response, 200, jsonSafe({ items }));
|
|
237
1048
|
},
|
|
238
1049
|
});
|
|
1050
|
+
const disposeWorkspaces = services.webServer.register({
|
|
1051
|
+
path: "/api/workspaces",
|
|
1052
|
+
async handler(_request, response) {
|
|
1053
|
+
try {
|
|
1054
|
+
sendJson(response, 200, { items: await listWorkspaces(activeCwd(services)) });
|
|
1055
|
+
} catch (error) {
|
|
1056
|
+
sendJson(response, 500, { error: errorText(error) });
|
|
1057
|
+
}
|
|
1058
|
+
},
|
|
1059
|
+
});
|
|
1060
|
+
const disposePickDirectory = services.webServer.register({
|
|
1061
|
+
path: "/api/workspaces/pick",
|
|
1062
|
+
async handler(request, response) {
|
|
1063
|
+
if (request.method !== "POST") {
|
|
1064
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
if (process.platform !== "darwin") {
|
|
1068
|
+
sendJson(response, 501, { error: "Native directory picker is only available on macOS" });
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
try {
|
|
1072
|
+
sendJson(response, 200, { path: await pickDirectory() });
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
sendJson(response, 409, { error: errorText(error) });
|
|
1075
|
+
}
|
|
1076
|
+
},
|
|
1077
|
+
});
|
|
239
1078
|
const disposeModel = services.webServer.register({
|
|
240
1079
|
path: "/api/model",
|
|
241
1080
|
async handler(request, response) {
|
|
@@ -272,11 +1111,19 @@ export default {
|
|
|
272
1111
|
const disposeFiles = services.webServer.register({
|
|
273
1112
|
path: "/api/files",
|
|
274
1113
|
async handler(_request, response) {
|
|
275
|
-
const output = await gitStatus(services
|
|
276
|
-
const items = output
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
1114
|
+
const output = await gitStatus(activeCwd(services));
|
|
1115
|
+
const items = output
|
|
1116
|
+
.split("\n")
|
|
1117
|
+
.map((line) => line.trimEnd())
|
|
1118
|
+
.filter((line) => line.length > 0)
|
|
1119
|
+
.map((line) => {
|
|
1120
|
+
const status = line.slice(0, 2).trim() || "??";
|
|
1121
|
+
return {
|
|
1122
|
+
path: line.slice(3),
|
|
1123
|
+
status,
|
|
1124
|
+
label: status === "??" ? "untracked" : status.includes("D") ? "deleted" : status.includes("A") ? "added" : "modified",
|
|
1125
|
+
};
|
|
1126
|
+
});
|
|
280
1127
|
sendJson(response, 200, { items });
|
|
281
1128
|
},
|
|
282
1129
|
});
|
|
@@ -293,7 +1140,7 @@ export default {
|
|
|
293
1140
|
sendJson(response, 400, { error: "path is required" });
|
|
294
1141
|
return;
|
|
295
1142
|
}
|
|
296
|
-
const root = resolve(services
|
|
1143
|
+
const root = resolve(activeCwd(services));
|
|
297
1144
|
const absolute = resolve(root, requested);
|
|
298
1145
|
const relativePath = relative(root, absolute);
|
|
299
1146
|
if (isAbsolute(relativePath) || relativePath === ".." || relativePath.startsWith(".." + "/")) {
|
|
@@ -312,7 +1159,7 @@ export default {
|
|
|
312
1159
|
}
|
|
313
1160
|
try {
|
|
314
1161
|
const payload = JSON.parse(await bodyText(request)) as { paths?: unknown; message?: unknown };
|
|
315
|
-
const paths = workspacePaths(resolve(services
|
|
1162
|
+
const paths = workspacePaths(resolve(activeCwd(services)), payload.paths);
|
|
316
1163
|
if (paths instanceof Error) {
|
|
317
1164
|
sendJson(response, 400, { error: paths.message });
|
|
318
1165
|
return;
|
|
@@ -321,7 +1168,7 @@ export default {
|
|
|
321
1168
|
sendJson(response, 400, { error: "message is required" });
|
|
322
1169
|
return;
|
|
323
1170
|
}
|
|
324
|
-
const root = resolve(services
|
|
1171
|
+
const root = resolve(activeCwd(services));
|
|
325
1172
|
const add = await gitCommand(root, ["add", "-A", "--", ...paths]);
|
|
326
1173
|
if (add.code !== 0) {
|
|
327
1174
|
sendJson(response, 409, { error: add.stderr.trim() || "Unable to stage workspace files" });
|
|
@@ -352,7 +1199,7 @@ export default {
|
|
|
352
1199
|
sendJson(response, 400, { error: "confirm must be true to discard workspace changes" });
|
|
353
1200
|
return;
|
|
354
1201
|
}
|
|
355
|
-
const root = resolve(services
|
|
1202
|
+
const root = resolve(activeCwd(services));
|
|
356
1203
|
const paths = workspacePaths(root, payload.paths);
|
|
357
1204
|
if (paths instanceof Error) {
|
|
358
1205
|
sendJson(response, 400, { error: paths.message });
|
|
@@ -364,7 +1211,10 @@ export default {
|
|
|
364
1211
|
sendJson(response, 409, { error: restore.stderr.trim() || "Unable to restore workspace files" });
|
|
365
1212
|
return;
|
|
366
1213
|
}
|
|
367
|
-
for (const path of untracked.stdout
|
|
1214
|
+
for (const path of untracked.stdout
|
|
1215
|
+
.split("\n")
|
|
1216
|
+
.map((item) => item.trim())
|
|
1217
|
+
.filter(Boolean)) {
|
|
368
1218
|
await rm(resolve(root, path), { recursive: true, force: true });
|
|
369
1219
|
}
|
|
370
1220
|
sendJson(response, 200, { reverted: true, paths });
|
|
@@ -376,7 +1226,12 @@ export default {
|
|
|
376
1226
|
const disposeEvents = services.webServer.register({
|
|
377
1227
|
path: "/api/events",
|
|
378
1228
|
handler(_request, response) {
|
|
379
|
-
response.writeHead(200, {
|
|
1229
|
+
response.writeHead(200, {
|
|
1230
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
1231
|
+
"cache-control": "no-cache, no-store",
|
|
1232
|
+
connection: "keep-alive",
|
|
1233
|
+
"x-accel-buffering": "no",
|
|
1234
|
+
});
|
|
380
1235
|
writeSse(response, { type: "snapshot", sessionId: services.runtime.session.sessionId, events });
|
|
381
1236
|
eventClients.add(response);
|
|
382
1237
|
const heartbeat = setInterval(() => {
|
|
@@ -448,13 +1303,17 @@ export default {
|
|
|
448
1303
|
handler(_request, response) {
|
|
449
1304
|
const session = services.runtime.session;
|
|
450
1305
|
const sessionManager = session.sessionManager;
|
|
451
|
-
sendJson(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
1306
|
+
sendJson(
|
|
1307
|
+
response,
|
|
1308
|
+
200,
|
|
1309
|
+
jsonSafe({
|
|
1310
|
+
sessionId: session.sessionId,
|
|
1311
|
+
sessionFile: session.sessionFile,
|
|
1312
|
+
messages: session.messages,
|
|
1313
|
+
entries: typeof sessionManager?.getEntries === "function" ? sessionManager.getEntries() : [],
|
|
1314
|
+
events,
|
|
1315
|
+
}),
|
|
1316
|
+
);
|
|
458
1317
|
},
|
|
459
1318
|
});
|
|
460
1319
|
const disposeNewSession = services.webServer.register({
|
|
@@ -469,14 +1328,40 @@ export default {
|
|
|
469
1328
|
return;
|
|
470
1329
|
}
|
|
471
1330
|
try {
|
|
1331
|
+
const raw = await bodyText(request);
|
|
1332
|
+
const payload = raw.trim() ? (JSON.parse(raw) as { cwd?: unknown }) : {};
|
|
1333
|
+
const currentCwd = activeCwd(services);
|
|
1334
|
+
const requestedCwd = typeof payload.cwd === "string" ? resolve(payload.cwd) : resolve(currentCwd);
|
|
1335
|
+
const workspaces = await listWorkspaces(currentCwd);
|
|
1336
|
+
const workspace =
|
|
1337
|
+
workspaces.find((item) => item.path === requestedCwd) ??
|
|
1338
|
+
(typeof payload.cwd === "string" && (await isDirectory(requestedCwd))
|
|
1339
|
+
? { path: requestedCwd, branch: "directory", current: false, name: basename(requestedCwd) || requestedCwd }
|
|
1340
|
+
: undefined);
|
|
1341
|
+
if (!workspace) {
|
|
1342
|
+
sendJson(response, 400, { error: "Workspace is not available" });
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
472
1345
|
if (services.runtime.sessionRuntime) {
|
|
473
|
-
|
|
1346
|
+
let result;
|
|
1347
|
+
if (workspace.current) {
|
|
1348
|
+
result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.newSession());
|
|
1349
|
+
} else {
|
|
1350
|
+
const manager = services.runtime.session.sessionManager;
|
|
1351
|
+
if (!manager || typeof manager.isPersisted !== "function" || !manager.isPersisted()) {
|
|
1352
|
+
sendJson(response, 409, { error: "Workspace switching requires JSONL session storage" });
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const created = SessionManager.create(workspace.path, manager.getSessionDir());
|
|
1356
|
+
const sessionFile = created.newSession();
|
|
1357
|
+
if (!sessionFile) throw new Error("Unable to create a workspace session");
|
|
1358
|
+
result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(sessionFile, { cwdOverride: workspace.path }));
|
|
1359
|
+
}
|
|
474
1360
|
if (result.cancelled) {
|
|
475
1361
|
sendJson(response, 409, { error: "Session creation was cancelled by an extension" });
|
|
476
1362
|
return;
|
|
477
1363
|
}
|
|
478
|
-
}
|
|
479
|
-
else {
|
|
1364
|
+
} else {
|
|
480
1365
|
const session = services.runtime.session;
|
|
481
1366
|
session.sessionManager.newSession();
|
|
482
1367
|
session.agent.state.messages = [];
|
|
@@ -484,7 +1369,16 @@ export default {
|
|
|
484
1369
|
events.length = 0;
|
|
485
1370
|
const session = services.runtime.session;
|
|
486
1371
|
for (const client of eventClients) writeSse(client, { type: "session", sessionId: session.sessionId, events: [] });
|
|
487
|
-
sendJson(
|
|
1372
|
+
sendJson(
|
|
1373
|
+
response,
|
|
1374
|
+
200,
|
|
1375
|
+
jsonSafe({
|
|
1376
|
+
sessionId: session.sessionId,
|
|
1377
|
+
sessionFile: session.sessionFile,
|
|
1378
|
+
messages: services.runtime.sessionRuntime ? session.messages : [],
|
|
1379
|
+
events: [],
|
|
1380
|
+
}),
|
|
1381
|
+
);
|
|
488
1382
|
} catch (error) {
|
|
489
1383
|
sendJson(response, 500, { error: errorText(error) });
|
|
490
1384
|
}
|
|
@@ -509,41 +1403,344 @@ export default {
|
|
|
509
1403
|
return;
|
|
510
1404
|
}
|
|
511
1405
|
const items = await SessionManager.list(services.launch.cwd, manager.getSessionDir());
|
|
512
|
-
const target = items.find(
|
|
1406
|
+
const target = items.find(
|
|
1407
|
+
(item) =>
|
|
1408
|
+
(typeof payload.path === "string" && item.path === payload.path) || (typeof payload.sessionId === "string" && item.id === payload.sessionId),
|
|
1409
|
+
);
|
|
513
1410
|
if (target === undefined) {
|
|
514
1411
|
sendJson(response, 404, { error: "Session not found" });
|
|
515
1412
|
return;
|
|
516
1413
|
}
|
|
517
1414
|
if (services.runtime.sessionRuntime) {
|
|
518
|
-
const result = await services.runtime.sessionRuntime.switchSession(target.path, { cwdOverride: target.cwd });
|
|
1415
|
+
const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(target.path, { cwdOverride: target.cwd }));
|
|
519
1416
|
if (result.cancelled) {
|
|
520
1417
|
sendJson(response, 409, { error: "Session switch was cancelled by an extension" });
|
|
521
1418
|
return;
|
|
522
1419
|
}
|
|
523
|
-
}
|
|
524
|
-
else {
|
|
1420
|
+
} else {
|
|
525
1421
|
manager.setSessionFile(target.path);
|
|
526
1422
|
if (typeof services.runtime.session.reload === "function") await services.runtime.session.reload();
|
|
527
1423
|
else services.runtime.session.agent.state.messages = manager.buildSessionContext().messages;
|
|
528
1424
|
}
|
|
529
1425
|
events.length = 0;
|
|
530
1426
|
for (const client of eventClients) writeSse(client, { type: "session", sessionId: services.runtime.session.sessionId, events: [] });
|
|
531
|
-
sendJson(
|
|
1427
|
+
sendJson(
|
|
1428
|
+
response,
|
|
1429
|
+
200,
|
|
1430
|
+
jsonSafe({
|
|
1431
|
+
sessionId: services.runtime.session.sessionId,
|
|
1432
|
+
sessionFile: services.runtime.session.sessionFile,
|
|
1433
|
+
messages: services.runtime.session.messages,
|
|
1434
|
+
events: [],
|
|
1435
|
+
}),
|
|
1436
|
+
);
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1439
|
+
}
|
|
1440
|
+
},
|
|
1441
|
+
});
|
|
1442
|
+
const disposeRenameSession = services.webServer.register({
|
|
1443
|
+
path: "/api/session/rename",
|
|
1444
|
+
async handler(request, response) {
|
|
1445
|
+
if (request.method !== "POST") {
|
|
1446
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
try {
|
|
1450
|
+
const payload = JSON.parse(await bodyText(request)) as { path?: unknown; name?: unknown };
|
|
1451
|
+
const manager = services.runtime.session.sessionManager;
|
|
1452
|
+
const path = typeof payload.path === "string" ? payload.path : services.runtime.session.sessionFile;
|
|
1453
|
+
const name = typeof payload.name === "string" ? payload.name.trim() : "";
|
|
1454
|
+
if (!path || !sessionPathInDirectory(path, manager)) {
|
|
1455
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
if (name.length > 120) {
|
|
1459
|
+
sendJson(response, 400, { error: "Session name must be at most 120 characters" });
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
SessionManager.open(path, manager.getSessionDir()).appendSessionInfo(name);
|
|
1463
|
+
sendJson(response, 200, { path, name: name || undefined });
|
|
532
1464
|
} catch (error) {
|
|
533
1465
|
sendJson(response, 400, { error: errorText(error) });
|
|
534
1466
|
}
|
|
535
1467
|
},
|
|
536
1468
|
});
|
|
1469
|
+
const disposeDeleteSession = services.webServer.register({
|
|
1470
|
+
path: "/api/session/delete",
|
|
1471
|
+
async handler(request, response) {
|
|
1472
|
+
if (request.method !== "POST") {
|
|
1473
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
try {
|
|
1477
|
+
const payload = JSON.parse(await bodyText(request)) as { path?: unknown; confirm?: unknown };
|
|
1478
|
+
const manager = services.runtime.session.sessionManager;
|
|
1479
|
+
const path = typeof payload.path === "string" ? payload.path : "";
|
|
1480
|
+
if (payload.confirm !== true) {
|
|
1481
|
+
sendJson(response, 400, { error: "confirm must be true to delete a session" });
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
if (!sessionPathInDirectory(path, manager)) {
|
|
1485
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
if (path === services.runtime.session.sessionFile) {
|
|
1489
|
+
if (services.runtime.session.isStreaming) {
|
|
1490
|
+
sendJson(response, 409, { error: "Cannot delete the active session while a prompt is running" });
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.newSession());
|
|
1494
|
+
if (result.cancelled) {
|
|
1495
|
+
sendJson(response, 409, { error: "Session deletion was cancelled by an extension" });
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
events.length = 0;
|
|
1499
|
+
}
|
|
1500
|
+
await unlink(path);
|
|
1501
|
+
const metadata = await readSessionMetadata(manager);
|
|
1502
|
+
delete metadata[path];
|
|
1503
|
+
await writeSessionMetadata(manager, metadata);
|
|
1504
|
+
sendJson(response, 200, { deleted: true, path, sessionFile: services.runtime.session.sessionFile });
|
|
1505
|
+
} catch (error) {
|
|
1506
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1507
|
+
}
|
|
1508
|
+
},
|
|
1509
|
+
});
|
|
1510
|
+
const disposeSessionMetadata = services.webServer.register({
|
|
1511
|
+
path: "/api/session/metadata",
|
|
1512
|
+
async handler(request, response) {
|
|
1513
|
+
if (request.method !== "POST") {
|
|
1514
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
try {
|
|
1518
|
+
const payload = JSON.parse(await bodyText(request)) as { path?: unknown; archived?: unknown; pinned?: unknown };
|
|
1519
|
+
const manager = services.runtime.session.sessionManager;
|
|
1520
|
+
const path = typeof payload.path === "string" ? payload.path : "";
|
|
1521
|
+
if (!sessionPathInDirectory(path, manager)) {
|
|
1522
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
const metadata = await readSessionMetadata(manager);
|
|
1526
|
+
const currentMetadata = metadata[path] ?? {};
|
|
1527
|
+
const nextMetadata: SessionMetadata = {
|
|
1528
|
+
...currentMetadata,
|
|
1529
|
+
...(payload.archived === undefined ? {} : { archived: payload.archived === true }),
|
|
1530
|
+
...(payload.pinned === undefined ? {} : { pinned: payload.pinned === true }),
|
|
1531
|
+
};
|
|
1532
|
+
metadata[path] = nextMetadata;
|
|
1533
|
+
await writeSessionMetadata(manager, metadata);
|
|
1534
|
+
sendJson(response, 200, { path, metadata: metadata[path] });
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1537
|
+
}
|
|
1538
|
+
},
|
|
1539
|
+
});
|
|
1540
|
+
const disposeBatchSessions = services.webServer.register({
|
|
1541
|
+
path: "/api/sessions/batch",
|
|
1542
|
+
async handler(request, response) {
|
|
1543
|
+
if (request.method !== "POST") {
|
|
1544
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
try {
|
|
1548
|
+
const payload = JSON.parse(await bodyText(request)) as { action?: unknown; paths?: unknown; confirm?: unknown };
|
|
1549
|
+
const action = payload.action;
|
|
1550
|
+
const paths = Array.isArray(payload.paths) ? payload.paths.filter((path): path is string => typeof path === "string") : [];
|
|
1551
|
+
const manager = services.runtime.session.sessionManager;
|
|
1552
|
+
if (
|
|
1553
|
+
(action !== "delete" && action !== "archive" && action !== "unarchive" && action !== "pin" && action !== "unpin") ||
|
|
1554
|
+
paths.length === 0 ||
|
|
1555
|
+
paths.length > 100
|
|
1556
|
+
) {
|
|
1557
|
+
sendJson(response, 400, { error: "action and 1-100 session paths are required" });
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
if (action === "delete" && payload.confirm !== true) {
|
|
1561
|
+
sendJson(response, 400, { error: "confirm must be true to delete sessions" });
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
if (paths.some((path) => !sessionPathInDirectory(path, manager))) {
|
|
1565
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
if (action === "delete" && paths.includes(services.runtime.session.sessionFile ?? "")) {
|
|
1569
|
+
sendJson(response, 409, { error: "Cannot batch-delete the active session" });
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
const metadata = await readSessionMetadata(manager);
|
|
1573
|
+
for (const path of paths) {
|
|
1574
|
+
if (action === "delete") {
|
|
1575
|
+
await unlink(path);
|
|
1576
|
+
delete metadata[path];
|
|
1577
|
+
} else {
|
|
1578
|
+
const current = metadata[path] ?? {};
|
|
1579
|
+
metadata[path] = {
|
|
1580
|
+
...current,
|
|
1581
|
+
...(action === "archive" || action === "unarchive" ? { archived: action === "archive" } : {}),
|
|
1582
|
+
...(action === "pin" || action === "unpin" ? { pinned: action === "pin" } : {}),
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
await writeSessionMetadata(manager, metadata);
|
|
1587
|
+
sendJson(response, 200, { action, count: paths.length });
|
|
1588
|
+
} catch (error) {
|
|
1589
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1590
|
+
}
|
|
1591
|
+
},
|
|
1592
|
+
});
|
|
1593
|
+
const disposeForkSession = services.webServer.register({
|
|
1594
|
+
path: "/api/session/fork",
|
|
1595
|
+
async handler(request, response) {
|
|
1596
|
+
if (request.method !== "POST") {
|
|
1597
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
try {
|
|
1601
|
+
const payload = JSON.parse(await bodyText(request)) as { path?: unknown; cwd?: unknown };
|
|
1602
|
+
const manager = services.runtime.session.sessionManager;
|
|
1603
|
+
const sourcePath = typeof payload.path === "string" ? payload.path : "";
|
|
1604
|
+
if (!sessionPathInDirectory(sourcePath, manager)) {
|
|
1605
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
const sessions = await SessionManager.list(services.launch.cwd, manager.getSessionDir());
|
|
1609
|
+
const source = sessions.find((item) => item.path === sourcePath);
|
|
1610
|
+
if (!source) {
|
|
1611
|
+
sendJson(response, 404, { error: "Session not found" });
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
const targetCwd = typeof payload.cwd === "string" && payload.cwd.trim() ? resolve(payload.cwd) : source.cwd || activeCwd(services);
|
|
1615
|
+
const forked = SessionManager.forkFrom(source.path, targetCwd, manager.getSessionDir());
|
|
1616
|
+
sendJson(response, 200, { sessionId: forked.getSessionId(), sessionFile: forked.getSessionFile(), cwd: targetCwd });
|
|
1617
|
+
} catch (error) {
|
|
1618
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
1621
|
+
});
|
|
1622
|
+
const disposeImportSession = services.webServer.register({
|
|
1623
|
+
path: "/api/session/import",
|
|
1624
|
+
async handler(request, response) {
|
|
1625
|
+
if (request.method !== "POST") {
|
|
1626
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
if (services.runtime.session.isStreaming) {
|
|
1630
|
+
sendJson(response, 409, { error: "Cannot import a session while a prompt is running" });
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
try {
|
|
1634
|
+
const payload = JSON.parse(await bodyText(request)) as { path?: unknown; content?: unknown; filename?: unknown; cwd?: unknown };
|
|
1635
|
+
const suppliedPath = typeof payload.path === "string" ? payload.path : "";
|
|
1636
|
+
const content = typeof payload.content === "string" ? payload.content : undefined;
|
|
1637
|
+
if ((!suppliedPath || !isAbsolute(suppliedPath)) && content === undefined) {
|
|
1638
|
+
sendJson(response, 400, { error: "A JSONL file path or file content is required" });
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
const manager = services.runtime.session.sessionManager;
|
|
1642
|
+
if (!manager.isPersisted()) {
|
|
1643
|
+
sendJson(response, 409, { error: "Session importing requires JSONL session storage" });
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
const targetCwd = typeof payload.cwd === "string" && payload.cwd.trim() ? resolve(payload.cwd) : activeCwd(services);
|
|
1647
|
+
const temporaryDirectory = content === undefined ? undefined : await mkdtemp(join(tmpdir(), "pi-harness-import-"));
|
|
1648
|
+
const importPath =
|
|
1649
|
+
suppliedPath ||
|
|
1650
|
+
join(temporaryDirectory as string, basename(typeof payload.filename === "string" && payload.filename.trim() ? payload.filename : "import.jsonl"));
|
|
1651
|
+
try {
|
|
1652
|
+
if (content !== undefined) {
|
|
1653
|
+
if (Buffer.byteLength(content, "utf8") > 10 * 1024 * 1024) {
|
|
1654
|
+
sendJson(response, 413, { error: "Imported session must be at most 10 MiB" });
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
await writeFile(importPath, content, "utf8");
|
|
1658
|
+
}
|
|
1659
|
+
const imported = SessionManager.forkFrom(importPath, targetCwd, manager.getSessionDir());
|
|
1660
|
+
const importedPath = imported.getSessionFile();
|
|
1661
|
+
if (!importedPath) throw new Error("Unable to persist imported session");
|
|
1662
|
+
const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(importedPath, { cwdOverride: targetCwd }));
|
|
1663
|
+
if (result.cancelled) {
|
|
1664
|
+
sendJson(response, 409, { error: "Session import was cancelled by an extension" });
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
events.length = 0;
|
|
1668
|
+
sendJson(response, 200, {
|
|
1669
|
+
sessionId: services.runtime.session.sessionId,
|
|
1670
|
+
sessionFile: services.runtime.session.sessionFile,
|
|
1671
|
+
messages: services.runtime.session.messages.length,
|
|
1672
|
+
});
|
|
1673
|
+
} finally {
|
|
1674
|
+
if (temporaryDirectory) await rm(temporaryDirectory, { recursive: true, force: true });
|
|
1675
|
+
}
|
|
1676
|
+
} catch (error) {
|
|
1677
|
+
sendJson(response, 400, { error: errorText(error) });
|
|
1678
|
+
}
|
|
1679
|
+
},
|
|
1680
|
+
});
|
|
1681
|
+
const disposeExportSession = services.webServer.register({
|
|
1682
|
+
path: "/api/session/export",
|
|
1683
|
+
async handler(request, response) {
|
|
1684
|
+
try {
|
|
1685
|
+
const url = new URL(request.url ?? "/api/session/export", "http://localhost");
|
|
1686
|
+
const manager = services.runtime.session.sessionManager;
|
|
1687
|
+
const path = url.searchParams.get("path") ?? services.runtime.session.sessionFile;
|
|
1688
|
+
if (!path || !sessionPathInDirectory(path, manager)) {
|
|
1689
|
+
sendJson(response, 400, { error: "Invalid session path" });
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
const content = await readFile(path, "utf8");
|
|
1693
|
+
response.writeHead(200, {
|
|
1694
|
+
"content-type": "application/x-ndjson; charset=utf-8",
|
|
1695
|
+
"content-disposition": `attachment; filename="${basename(path)}"`,
|
|
1696
|
+
"cache-control": "no-store",
|
|
1697
|
+
});
|
|
1698
|
+
response.end(content);
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
sendJson(response, 404, { error: errorText(error) });
|
|
1701
|
+
}
|
|
1702
|
+
},
|
|
1703
|
+
});
|
|
537
1704
|
const disposeSessions = services.webServer.register({
|
|
538
1705
|
path: "/api/sessions",
|
|
539
1706
|
async handler(_request, response) {
|
|
540
1707
|
try {
|
|
541
1708
|
const session = services.runtime.session;
|
|
542
1709
|
const manager = session.sessionManager;
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
1710
|
+
const url = new URL(_request.url ?? "/api/sessions", "http://localhost");
|
|
1711
|
+
const page = Math.max(0, Number.parseInt(url.searchParams.get("page") ?? "0", 10) || 0);
|
|
1712
|
+
const pageSize = Math.min(100, Math.max(1, Number.parseInt(url.searchParams.get("pageSize") ?? "50", 10) || 50));
|
|
1713
|
+
const includeArchived = url.searchParams.get("includeArchived") === "true";
|
|
1714
|
+
const metadata = await readSessionMetadata(manager);
|
|
1715
|
+
const items =
|
|
1716
|
+
typeof manager.isPersisted === "function" && manager.isPersisted() ? await SessionManager.list(services.launch.cwd, manager.getSessionDir()) : [];
|
|
1717
|
+
const filtered = items.filter((item) => includeArchived || metadata[item.path]?.archived !== true);
|
|
1718
|
+
const sorted = filtered.sort(
|
|
1719
|
+
(a, b) => Number(metadata[b.path]?.pinned === true) - Number(metadata[a.path]?.pinned === true) || b.modified.getTime() - a.modified.getTime(),
|
|
1720
|
+
);
|
|
1721
|
+
const paged = sorted.slice(page * pageSize, (page + 1) * pageSize);
|
|
1722
|
+
sendJson(
|
|
1723
|
+
response,
|
|
1724
|
+
200,
|
|
1725
|
+
jsonSafe({
|
|
1726
|
+
items: paged.map((item) => ({
|
|
1727
|
+
sessionId: item.id,
|
|
1728
|
+
path: item.path,
|
|
1729
|
+
name: item.name,
|
|
1730
|
+
cwd: item.cwd,
|
|
1731
|
+
created: item.created,
|
|
1732
|
+
modified: item.modified,
|
|
1733
|
+
messageCount: item.messageCount,
|
|
1734
|
+
firstMessage: item.firstMessage,
|
|
1735
|
+
archived: metadata[item.path]?.archived === true,
|
|
1736
|
+
pinned: metadata[item.path]?.pinned === true,
|
|
1737
|
+
})),
|
|
1738
|
+
total: sorted.length,
|
|
1739
|
+
page,
|
|
1740
|
+
pageSize,
|
|
1741
|
+
hasNext: (page + 1) * pageSize < sorted.length,
|
|
1742
|
+
}),
|
|
1743
|
+
);
|
|
547
1744
|
} catch (error) {
|
|
548
1745
|
sendJson(response, 500, { error: errorText(error) });
|
|
549
1746
|
}
|
|
@@ -551,14 +1748,26 @@ export default {
|
|
|
551
1748
|
});
|
|
552
1749
|
context.effect(() => () => {
|
|
553
1750
|
disposeStatus();
|
|
1751
|
+
disposeConfig();
|
|
1752
|
+
disposeConfigReload();
|
|
1753
|
+
disposeConfigSource();
|
|
554
1754
|
disposeEvents();
|
|
555
1755
|
disposeModels();
|
|
556
1756
|
disposeProviders();
|
|
557
1757
|
disposeProviderTest();
|
|
558
1758
|
disposeProviderRefresh();
|
|
1759
|
+
disposeProviderAdd();
|
|
559
1760
|
disposePlugins();
|
|
1761
|
+
disposePluginUi();
|
|
1762
|
+
disposePluginPanels();
|
|
1763
|
+
disposeMarketplace();
|
|
1764
|
+
disposeMarketplaceInstall();
|
|
1765
|
+
disposePluginToggle();
|
|
1766
|
+
disposePluginUninstall();
|
|
560
1767
|
disposeCommands();
|
|
561
1768
|
disposeModel();
|
|
1769
|
+
disposeWorkspaces();
|
|
1770
|
+
disposePickDirectory();
|
|
562
1771
|
disposeFiles();
|
|
563
1772
|
disposeFileDiff();
|
|
564
1773
|
disposeFileCommit();
|
|
@@ -568,6 +1777,13 @@ export default {
|
|
|
568
1777
|
disposeSession();
|
|
569
1778
|
disposeNewSession();
|
|
570
1779
|
disposeOpenSession();
|
|
1780
|
+
disposeRenameSession();
|
|
1781
|
+
disposeDeleteSession();
|
|
1782
|
+
disposeSessionMetadata();
|
|
1783
|
+
disposeBatchSessions();
|
|
1784
|
+
disposeForkSession();
|
|
1785
|
+
disposeImportSession();
|
|
1786
|
+
disposeExportSession();
|
|
571
1787
|
disposeSessions();
|
|
572
1788
|
unsubscribeEvents();
|
|
573
1789
|
for (const response of eventClients) response.end();
|