@pi-harness/pi-harness 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -9
- package/apps/web/dist/assets/index-Deo3hxmM.js +25 -0
- package/apps/web/dist/assets/index-xF647pQJ.css +2 -0
- package/apps/web/dist/index.html +2 -2
- package/apps/web/package.json +6 -6
- package/apps/web/profile/cordis.yml +1 -0
- package/apps/web/server-dist/bin.js +27 -2
- package/apps/web/server-dist/bin.js.map +1 -1
- package/apps/web/src/server/bin.ts +27 -2
- package/apps/web/test/bin.test.ts +228 -5
- package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/index.js +160 -69
- package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
- package/node_modules/@pi-harness/api-gateway/package.json +1 -1
- package/node_modules/@pi-harness/cli/dist/main.d.ts +1 -0
- package/node_modules/@pi-harness/cli/dist/main.d.ts.map +1 -1
- package/node_modules/@pi-harness/cli/dist/main.js +11 -0
- package/node_modules/@pi-harness/cli/dist/main.js.map +1 -1
- package/node_modules/@pi-harness/cli/dist/relaunch.d.ts.map +1 -1
- package/node_modules/@pi-harness/cli/dist/relaunch.js +2 -4
- package/node_modules/@pi-harness/cli/dist/relaunch.js.map +1 -1
- package/node_modules/@pi-harness/cli/package.json +1 -1
- package/node_modules/@pi-harness/host-webserver/dist/index.d.ts +1 -0
- package/node_modules/@pi-harness/host-webserver/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/host-webserver/dist/index.js +43 -7
- package/node_modules/@pi-harness/host-webserver/dist/index.js.map +1 -1
- package/node_modules/@pi-harness/host-webserver/package.json +1 -1
- package/node_modules/@pi-harness/web-app/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/web-app/dist/index.js +12 -3
- package/node_modules/@pi-harness/web-app/dist/index.js.map +1 -1
- package/node_modules/@pi-harness/web-app/package.json +1 -1
- package/package.json +7 -7
- package/packages/api-gateway/dist/index.d.ts.map +1 -1
- package/packages/api-gateway/dist/index.js +160 -69
- package/packages/api-gateway/dist/index.js.map +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
- package/packages/api-gateway/package.json +1 -1
- package/packages/api-gateway/src/index.ts +186 -88
- package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/openpets.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -1
- package/packages/api-gateway/test/index.test.ts +656 -4
- package/packages/api-gateway/test/packed-package.test.ts +70 -0
- package/packages/api-gateway/test/reference-docs.test.ts +50 -0
- package/packages/api-gateway/test/release-package.test.ts +32 -1
- package/packages/api-gateway/test/release-version.test.ts +40 -0
- package/packages/bundle-web-app/dist/index.d.ts.map +1 -1
- package/packages/bundle-web-app/dist/index.js +12 -3
- package/packages/bundle-web-app/dist/index.js.map +1 -1
- package/packages/bundle-web-app/package.json +1 -1
- package/packages/bundle-web-app/src/index.ts +13 -3
- package/packages/bundle-web-app/test/index.test.ts +83 -2
- 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 +11 -0
- package/packages/cli/dist/main.js.map +1 -1
- package/packages/cli/dist/relaunch.d.ts.map +1 -1
- package/packages/cli/dist/relaunch.js +2 -4
- package/packages/cli/dist/relaunch.js.map +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/main.ts +11 -0
- package/packages/cli/src/relaunch.ts +2 -3
- package/packages/cli/test/cli.test.ts +3 -1
- package/packages/cli/test/main.test.ts +134 -0
- package/packages/cli/test/relaunch.test.ts +86 -11
- package/packages/host-webserver/dist/index.d.ts +1 -0
- package/packages/host-webserver/dist/index.d.ts.map +1 -1
- package/packages/host-webserver/dist/index.js +43 -7
- package/packages/host-webserver/dist/index.js.map +1 -1
- package/packages/host-webserver/package.json +1 -1
- package/packages/host-webserver/src/index.ts +48 -8
- package/packages/host-webserver/test/index.test.ts +58 -5
- package/apps/web/dist/assets/index-BVI_IS-R.css +0 -2
- package/apps/web/dist/assets/index-Bo9CNI_U.js +0 -22
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFile, type ExecFileException } from "node:child_process";
|
|
2
|
-
import { mkdir, mkdtemp, readFile, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
4
|
-
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import type { Context } from "@deepseek-ai/cordis";
|
|
7
7
|
import { SessionManager, type AgentSessionEvent, type ExtensionUIContext } from "@earendil-works/pi-coding-agent";
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
paginateMarketplace,
|
|
19
19
|
searchMarketplace,
|
|
20
20
|
needsMarketplacePackageInstall,
|
|
21
|
+
marketplaceNpmPackageName,
|
|
21
22
|
sortMarketplaceByRecommendation,
|
|
22
23
|
type MarketplacePlugin,
|
|
23
24
|
} from "./marketplace.js";
|
|
@@ -41,6 +42,8 @@ const IMPORT_BODY_LIMIT_BYTES = 16 * 1024 * 1024;
|
|
|
41
42
|
// Retained trajectory events are replayed to every SSE client and returned by /api/session, so the array must stay bounded.
|
|
42
43
|
const MAX_RETAINED_EVENTS = 2000;
|
|
43
44
|
const GIT_TIMEOUT_MS = 15_000;
|
|
45
|
+
// Mutating commands run user hooks (pre-commit, lint-staged, test suites) and may stage large trees; killing them part-way leaves index.lock and a half-finished operation behind, so they get a far more generous bound than read-only queries.
|
|
46
|
+
const GIT_MUTATION_TIMEOUT_MS = 120_000;
|
|
44
47
|
|
|
45
48
|
class PayloadTooLargeError extends Error {
|
|
46
49
|
constructor() {
|
|
@@ -55,17 +58,18 @@ function sendJson(response: ServerResponse, status: number, payload: unknown): v
|
|
|
55
58
|
response.end(body);
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
// A multi-byte UTF-8 sequence can straddle a chunk boundary, so the raw bytes are collected and decoded once; decoding each chunk on its own would replace the split sequence with U+FFFD.
|
|
58
62
|
async function bodyText(request: IncomingMessage, maxBytes = DEFAULT_BODY_LIMIT_BYTES): Promise<string> {
|
|
59
|
-
const chunks:
|
|
63
|
+
const chunks: Buffer[] = [];
|
|
60
64
|
let length = 0;
|
|
61
65
|
for await (const chunk of request) {
|
|
62
66
|
const input: string | Uint8Array = chunk as string | Uint8Array;
|
|
63
|
-
const
|
|
64
|
-
length +=
|
|
67
|
+
const buffer = typeof input === "string" ? Buffer.from(input, "utf8") : Buffer.isBuffer(input) ? input : Buffer.from(input);
|
|
68
|
+
length += buffer.length;
|
|
65
69
|
if (length > maxBytes) throw new PayloadTooLargeError();
|
|
66
|
-
chunks.push(
|
|
70
|
+
chunks.push(buffer);
|
|
67
71
|
}
|
|
68
|
-
return chunks.
|
|
72
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
function errorText(error: unknown): string {
|
|
@@ -80,9 +84,14 @@ function jsonSafe(value: unknown, seen = new WeakSet<object>()): unknown {
|
|
|
80
84
|
if (value instanceof Date) return value.toISOString();
|
|
81
85
|
if (typeof value !== "object") return Object.prototype.toString.call(value);
|
|
82
86
|
if (seen.has(value)) return "[Circular]";
|
|
87
|
+
// Only the ancestors of the current node stay marked: a sibling that repeats the same object (Pi pushes one AgentMessage instance into both the message list and its events) is legitimate data, not a cycle.
|
|
83
88
|
seen.add(value);
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
try {
|
|
90
|
+
if (Array.isArray(value)) return value.map((item) => jsonSafe(item, seen));
|
|
91
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonSafe(item, seen)]));
|
|
92
|
+
} finally {
|
|
93
|
+
seen.delete(value);
|
|
94
|
+
}
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
function createStatus(services: ApiServices, events: readonly AgentSessionEvent[]) {
|
|
@@ -159,7 +168,7 @@ interface MetadataLogger {
|
|
|
159
168
|
warn(message: string): void;
|
|
160
169
|
}
|
|
161
170
|
|
|
162
|
-
// A missing file is the normal first-run state.
|
|
171
|
+
// A missing file is the normal first-run state. A parse or shape failure means the file exists but is unusable; it is renamed aside so the wreckage survives for recovery and the next write cannot silently replace the only copy. Any other read error (EMFILE, EBUSY, EISDIR, permissions) says nothing about the content, so it propagates and the caller's write is skipped instead of replacing a valid map with an empty one.
|
|
163
172
|
async function readSessionMetadata(manager: SessionManager, logger: MetadataLogger): Promise<SessionMetadataMap> {
|
|
164
173
|
const file = sessionMetadataFile(manager);
|
|
165
174
|
let raw: string;
|
|
@@ -167,8 +176,7 @@ async function readSessionMetadata(manager: SessionManager, logger: MetadataLogg
|
|
|
167
176
|
raw = await readFile(file, "utf8");
|
|
168
177
|
} catch (error) {
|
|
169
178
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return {};
|
|
170
|
-
|
|
171
|
-
return {};
|
|
179
|
+
throw error;
|
|
172
180
|
}
|
|
173
181
|
try {
|
|
174
182
|
const parsed: unknown = JSON.parse(raw);
|
|
@@ -195,27 +203,38 @@ async function writeSessionMetadata(manager: SessionManager, metadata: SessionMe
|
|
|
195
203
|
await atomicWriteFile(sessionMetadataFile(manager), JSON.stringify(metadata, null, 2) + "\n", { encoding: "utf8" });
|
|
196
204
|
}
|
|
197
205
|
|
|
198
|
-
// Every
|
|
206
|
+
// Every access to the metadata file runs through this chain so concurrent requests cannot interleave and drop each other's updates. Plain reads take the lock too: a read that finds corrupt bytes quarantines the file, and doing that outside the lock could rename away a valid map that a concurrent mutation had just written.
|
|
199
207
|
let sessionMetadataQueue: Promise<unknown> = Promise.resolve();
|
|
200
208
|
|
|
209
|
+
function withSessionMetadataLock<T>(operation: () => Promise<T>): Promise<T> {
|
|
210
|
+
const next = sessionMetadataQueue.catch(() => undefined).then(operation);
|
|
211
|
+
sessionMetadataQueue = next;
|
|
212
|
+
return next;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function readSessionMetadataLocked(manager: SessionManager, logger: MetadataLogger): Promise<SessionMetadataMap> {
|
|
216
|
+
return withSessionMetadataLock(() => readSessionMetadata(manager, logger));
|
|
217
|
+
}
|
|
218
|
+
|
|
201
219
|
function mutateSessionMetadata<T>(manager: SessionManager, logger: MetadataLogger, mutate: (metadata: SessionMetadataMap) => Promise<T> | T): Promise<T> {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
220
|
+
return withSessionMetadataLock(async () => {
|
|
221
|
+
const metadata = await readSessionMetadata(manager, logger);
|
|
222
|
+
const result = await mutate(metadata);
|
|
223
|
+
await writeSessionMetadata(manager, metadata);
|
|
224
|
+
return result;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// True when a path.relative() result points outside the directory it was computed from. All containment checks share this predicate so they agree on every platform separator.
|
|
229
|
+
function escapesRoot(relativePath: string): boolean {
|
|
230
|
+
return isAbsolute(relativePath) || relativePath === ".." || relativePath.startsWith(".." + sep);
|
|
212
231
|
}
|
|
213
232
|
|
|
214
233
|
function sessionPathInDirectory(path: string, manager: SessionManager): boolean {
|
|
215
234
|
const root = resolve(manager.getSessionDir());
|
|
216
235
|
const target = resolve(path);
|
|
217
236
|
const relativePath = relative(root, target);
|
|
218
|
-
return relativePath !== "" && !
|
|
237
|
+
return relativePath !== "" && !escapesRoot(relativePath) && target.endsWith(".jsonl");
|
|
219
238
|
}
|
|
220
239
|
|
|
221
240
|
const webSessionUi = {
|
|
@@ -350,6 +369,7 @@ function sanitizeLogValue(value: unknown, state: LogSanitizeState, depth = 0): u
|
|
|
350
369
|
if (typeof value !== "object") return Object.prototype.toString.call(value);
|
|
351
370
|
if (depth >= loggerPanelDepthLimit) return "[Max Depth]";
|
|
352
371
|
if (state.seen.has(value)) return "[Circular]";
|
|
372
|
+
// Unmarked once its subtree is done, so an object logged twice as a sibling is rendered twice instead of being mistaken for a cycle.
|
|
353
373
|
state.seen.add(value);
|
|
354
374
|
|
|
355
375
|
try {
|
|
@@ -379,6 +399,8 @@ function sanitizeLogValue(value: unknown, state: LogSanitizeState, depth = 0): u
|
|
|
379
399
|
return Object.fromEntries(entries);
|
|
380
400
|
} catch {
|
|
381
401
|
return "[Unavailable]";
|
|
402
|
+
} finally {
|
|
403
|
+
state.seen.delete(value);
|
|
382
404
|
}
|
|
383
405
|
}
|
|
384
406
|
|
|
@@ -519,39 +541,71 @@ function gitTermination(error: ExecFileException | null): GitTermination | undef
|
|
|
519
541
|
return undefined;
|
|
520
542
|
}
|
|
521
543
|
|
|
522
|
-
function gitTerminationMessage(command: string, termination: GitTermination): string {
|
|
544
|
+
function gitTerminationMessage(command: string, termination: GitTermination, timeoutMs = GIT_TIMEOUT_MS): string {
|
|
523
545
|
return termination === "timeout"
|
|
524
|
-
? `git ${command} timed out after ${
|
|
546
|
+
? `git ${command} timed out after ${timeoutMs / 1000} seconds`
|
|
525
547
|
: `git ${command} produced more output than the buffer limit allows`;
|
|
526
548
|
}
|
|
527
549
|
|
|
550
|
+
interface GitStatusEntry {
|
|
551
|
+
readonly path: string;
|
|
552
|
+
readonly status: string;
|
|
553
|
+
}
|
|
554
|
+
|
|
528
555
|
interface GitStatusResult {
|
|
529
|
-
readonly
|
|
556
|
+
readonly entries: readonly GitStatusEntry[];
|
|
530
557
|
readonly truncated: boolean;
|
|
531
558
|
}
|
|
532
559
|
|
|
533
|
-
|
|
560
|
+
// `-z` output is NUL-separated and never C-quoted, so non-ASCII names arrive verbatim and a rename carries its original path as the following field instead of an `old -> new` pair. The paths are relative to the repository root regardless of cwd, so they are rebased onto the cwd prefix to keep the contract with /api/files/diff, /api/files/commit and /api/files/revert, which resolve paths against the same cwd.
|
|
561
|
+
function parseGitStatus(output: string, prefix: string): GitStatusEntry[] {
|
|
562
|
+
const fields = output.split("\0");
|
|
563
|
+
const entries: GitStatusEntry[] = [];
|
|
564
|
+
for (let index = 0; index < fields.length; index += 1) {
|
|
565
|
+
const field = fields[index] ?? "";
|
|
566
|
+
if (field.length < 4) continue;
|
|
567
|
+
const code = field.slice(0, 2);
|
|
568
|
+
const path = field.slice(3);
|
|
569
|
+
if (code.startsWith("R") || code.startsWith("C")) index += 1;
|
|
570
|
+
entries.push({ path: prefix === "" ? path : posix.relative("/" + prefix, "/" + path), status: code.trim() || "??" });
|
|
571
|
+
}
|
|
572
|
+
return entries;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function gitStatusOutput(cwd: string): Promise<{ output: string; truncated: boolean }> {
|
|
534
576
|
return new Promise((resolveStatus, rejectStatus) => {
|
|
535
|
-
execFile(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
577
|
+
execFile(
|
|
578
|
+
"git",
|
|
579
|
+
["status", "--porcelain", "-z", "--untracked-files=all"],
|
|
580
|
+
{ cwd, timeout: GIT_TIMEOUT_MS, maxBuffer: 512 * 1024 },
|
|
581
|
+
(error, stdout, stderr) => {
|
|
582
|
+
if (error === null) {
|
|
583
|
+
resolveStatus({ output: stdout, truncated: false });
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const termination = gitTermination(error);
|
|
587
|
+
if (termination === "output-limit") {
|
|
588
|
+
// Keep the complete entries that arrived before the kill; the final entry may have been cut mid-path.
|
|
589
|
+
resolveStatus({ output: stdout.slice(0, stdout.lastIndexOf("\0") + 1), truncated: true });
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (termination === undefined && error.code === 128 && /not a git repository/i.test(stderr)) {
|
|
593
|
+
resolveStatus({ output: "", truncated: false });
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
rejectStatus(new Error(termination ? gitTerminationMessage("status", termination) : stderr.trim() || error.message, { cause: error }));
|
|
597
|
+
},
|
|
598
|
+
);
|
|
552
599
|
});
|
|
553
600
|
}
|
|
554
601
|
|
|
602
|
+
async function gitStatus(cwd: string): Promise<GitStatusResult> {
|
|
603
|
+
const { output, truncated } = await gitStatusOutput(cwd);
|
|
604
|
+
if (output === "") return { entries: [], truncated };
|
|
605
|
+
const prefix = await gitCommand(cwd, ["rev-parse", "--show-prefix"]);
|
|
606
|
+
return { entries: parseGitStatus(output, prefix.code === 0 ? prefix.stdout.trim() : ""), truncated };
|
|
607
|
+
}
|
|
608
|
+
|
|
555
609
|
function gitDiff(cwd: string, path: string): Promise<string> {
|
|
556
610
|
return new Promise((resolveOutput) => {
|
|
557
611
|
execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, timeout: GIT_TIMEOUT_MS, maxBuffer: 1024 * 1024 }, (error, stdout) =>
|
|
@@ -567,9 +621,9 @@ interface GitCommandResult {
|
|
|
567
621
|
readonly terminated: GitTermination | undefined;
|
|
568
622
|
}
|
|
569
623
|
|
|
570
|
-
function gitCommand(cwd: string, args: readonly string[]): Promise<GitCommandResult> {
|
|
624
|
+
function gitCommand(cwd: string, args: readonly string[], timeoutMs = GIT_TIMEOUT_MS): Promise<GitCommandResult> {
|
|
571
625
|
return new Promise((resolveResult) => {
|
|
572
|
-
execFile("git", [...args], { cwd, timeout:
|
|
626
|
+
execFile("git", [...args], { cwd, timeout: timeoutMs, maxBuffer: 2 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
573
627
|
const code = error && typeof error.code === "number" ? error.code : error ? 1 : 0;
|
|
574
628
|
resolveResult({ stdout, stderr, code, terminated: gitTermination(error) });
|
|
575
629
|
});
|
|
@@ -610,6 +664,26 @@ async function isDirectory(path: string): Promise<boolean> {
|
|
|
610
664
|
}
|
|
611
665
|
}
|
|
612
666
|
|
|
667
|
+
async function isFile(path: string): Promise<boolean> {
|
|
668
|
+
try {
|
|
669
|
+
return (await stat(path)).isFile();
|
|
670
|
+
} catch {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// The loader resolves a bare plugin specifier from the profile file upwards (`createRequire(profilePath).resolve(name)`), never from the shell the harness was started in, so a marketplace package has to land in the package that owns the profile or it installs successfully and then fails to load.
|
|
676
|
+
async function marketplaceInstallDirectory(configPath: string, fallback: string): Promise<string> {
|
|
677
|
+
let directory = dirname(resolve(configPath));
|
|
678
|
+
let parent = dirname(directory);
|
|
679
|
+
while (parent !== directory) {
|
|
680
|
+
if (await isFile(join(directory, "package.json"))) return directory;
|
|
681
|
+
directory = parent;
|
|
682
|
+
parent = dirname(directory);
|
|
683
|
+
}
|
|
684
|
+
return fallback;
|
|
685
|
+
}
|
|
686
|
+
|
|
613
687
|
function pickDirectory(): Promise<string> {
|
|
614
688
|
return new Promise((resolvePath, reject) => {
|
|
615
689
|
execFile(
|
|
@@ -637,7 +711,7 @@ function workspacePaths(root: string, paths: unknown): string[] | Error {
|
|
|
637
711
|
const requested = path as string;
|
|
638
712
|
const absolute = resolve(root, requested);
|
|
639
713
|
const relativePath = relative(root, absolute);
|
|
640
|
-
if (
|
|
714
|
+
if (escapesRoot(relativePath)) return new Error("path must stay inside the workspace");
|
|
641
715
|
normalized.push(relativePath);
|
|
642
716
|
}
|
|
643
717
|
return [...new Set(normalized)];
|
|
@@ -790,8 +864,8 @@ export default {
|
|
|
790
864
|
sendJson(response, 400, { error: "settings source must contain a JSON object" });
|
|
791
865
|
return;
|
|
792
866
|
}
|
|
793
|
-
|
|
794
|
-
|
|
867
|
+
// Replace the file atomically so an interrupted write never leaves a truncated settings.json behind; keep the existing permission bits. The rename must land on the resolved target, otherwise a symlinked settings.json (dotfiles repositories) would be replaced by a detached regular file.
|
|
868
|
+
const path = await realpath(join(services.launch.agentDir, "settings.json")).catch(() => join(services.launch.agentDir, "settings.json"));
|
|
795
869
|
const mode = await stat(path).then(
|
|
796
870
|
(info) => info.mode & 0o777,
|
|
797
871
|
() => 0o644,
|
|
@@ -1073,15 +1147,17 @@ export default {
|
|
|
1073
1147
|
sendJson(response, 409, { error: "Plugin is already installed", plugin });
|
|
1074
1148
|
return;
|
|
1075
1149
|
}
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1150
|
+
const installDirectory = await marketplaceInstallDirectory(configPath, services.launch.cwd);
|
|
1151
|
+
const packageJsonPath = join(installDirectory, "package.json");
|
|
1152
|
+
const packageLockPath = join(installDirectory, "package-lock.json");
|
|
1078
1153
|
const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
|
|
1079
1154
|
const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
|
|
1080
1155
|
let profileBefore: string | undefined;
|
|
1081
1156
|
let entryId: string | undefined;
|
|
1082
1157
|
try {
|
|
1083
1158
|
if (needsMarketplacePackageInstall(plugin)) {
|
|
1084
|
-
|
|
1159
|
+
const specifier = `${marketplaceNpmPackageName(plugin.packageName)}@${plugin.version}`;
|
|
1160
|
+
await runProcess("npm", ["install", "--save-exact", "--package-lock=false", specifier], installDirectory);
|
|
1085
1161
|
}
|
|
1086
1162
|
profileBefore = await appendMarketplaceProfile(configPath, plugin);
|
|
1087
1163
|
if (!needsMarketplacePackageInstall(plugin)) {
|
|
@@ -1101,8 +1177,11 @@ export default {
|
|
|
1101
1177
|
} catch (error) {
|
|
1102
1178
|
if (entryId !== undefined) await loader.remove(entryId).catch(() => {});
|
|
1103
1179
|
if (profileBefore !== undefined) await writeFile(configPath, profileBefore, "utf8").catch(() => {});
|
|
1104
|
-
|
|
1105
|
-
if (
|
|
1180
|
+
// A manifest npm created for this install is removed rather than left behind; restoring is only possible when one existed before.
|
|
1181
|
+
if (packageJsonBefore === undefined) await unlink(packageJsonPath).catch(() => {});
|
|
1182
|
+
else await writeFile(packageJsonPath, packageJsonBefore, "utf8").catch(() => {});
|
|
1183
|
+
if (packageLockBefore === undefined) await unlink(packageLockPath).catch(() => {});
|
|
1184
|
+
else await writeFile(packageLockPath, packageLockBefore, "utf8").catch(() => {});
|
|
1106
1185
|
sendJson(response, 502, { error: errorText(error) });
|
|
1107
1186
|
}
|
|
1108
1187
|
} catch (error) {
|
|
@@ -1198,15 +1277,17 @@ export default {
|
|
|
1198
1277
|
}
|
|
1199
1278
|
const profileEntryId = entry.options.id;
|
|
1200
1279
|
const profileBefore = await readFile(configPath, "utf8");
|
|
1201
|
-
const
|
|
1202
|
-
const
|
|
1280
|
+
const installDirectory = await marketplaceInstallDirectory(configPath, services.launch.cwd);
|
|
1281
|
+
const packageJsonPath = join(installDirectory, "package.json");
|
|
1282
|
+
const packageLockPath = join(installDirectory, "package-lock.json");
|
|
1203
1283
|
const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
|
|
1204
1284
|
const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
|
|
1205
1285
|
await entry.parent.remove(entry.options.id);
|
|
1206
1286
|
entry.parent.tree.write();
|
|
1207
1287
|
try {
|
|
1208
1288
|
await updateMarketplaceProfile(configPath, profileEntryId, { remove: true });
|
|
1209
|
-
if (needsMarketplacePackageInstall(plugin))
|
|
1289
|
+
if (needsMarketplacePackageInstall(plugin))
|
|
1290
|
+
await runProcess("npm", ["uninstall", "--package-lock=false", marketplaceNpmPackageName(plugin.packageName)], installDirectory);
|
|
1210
1291
|
sendJson(response, 200, { uninstalled: true, id: payload.id });
|
|
1211
1292
|
} catch (error) {
|
|
1212
1293
|
await writeFile(configPath, profileBefore, "utf8").catch(() => {});
|
|
@@ -1309,18 +1390,11 @@ export default {
|
|
|
1309
1390
|
sendJson(response, 500, { error: errorText(error) });
|
|
1310
1391
|
return;
|
|
1311
1392
|
}
|
|
1312
|
-
const items = status.
|
|
1313
|
-
.
|
|
1314
|
-
|
|
1315
|
-
.
|
|
1316
|
-
|
|
1317
|
-
const status = line.slice(0, 2).trim() || "??";
|
|
1318
|
-
return {
|
|
1319
|
-
path: line.slice(3),
|
|
1320
|
-
status,
|
|
1321
|
-
label: status === "??" ? "untracked" : status.includes("D") ? "deleted" : status.includes("A") ? "added" : "modified",
|
|
1322
|
-
};
|
|
1323
|
-
});
|
|
1393
|
+
const items = status.entries.map((entry) => ({
|
|
1394
|
+
path: entry.path,
|
|
1395
|
+
status: entry.status,
|
|
1396
|
+
label: entry.status === "??" ? "untracked" : entry.status.includes("D") ? "deleted" : entry.status.includes("A") ? "added" : "modified",
|
|
1397
|
+
}));
|
|
1324
1398
|
sendJson(response, 200, { items, ...(status.truncated ? { truncated: true } : {}) });
|
|
1325
1399
|
},
|
|
1326
1400
|
});
|
|
@@ -1340,7 +1414,7 @@ export default {
|
|
|
1340
1414
|
const root = resolve(activeCwd(services));
|
|
1341
1415
|
const absolute = resolve(root, requested);
|
|
1342
1416
|
const relativePath = relative(root, absolute);
|
|
1343
|
-
if (
|
|
1417
|
+
if (escapesRoot(relativePath)) {
|
|
1344
1418
|
sendJson(response, 400, { error: "path must stay inside the workspace" });
|
|
1345
1419
|
return;
|
|
1346
1420
|
}
|
|
@@ -1366,18 +1440,18 @@ export default {
|
|
|
1366
1440
|
return;
|
|
1367
1441
|
}
|
|
1368
1442
|
const root = resolve(activeCwd(services));
|
|
1369
|
-
const add = await gitCommand(root, ["add", "-A", "--", ...paths]);
|
|
1443
|
+
const add = await gitCommand(root, ["add", "-A", "--", ...paths], GIT_MUTATION_TIMEOUT_MS);
|
|
1370
1444
|
if (add.terminated) {
|
|
1371
|
-
sendJson(response, 500, { error: gitTerminationMessage("add", add.terminated) });
|
|
1445
|
+
sendJson(response, 500, { error: gitTerminationMessage("add", add.terminated, GIT_MUTATION_TIMEOUT_MS) });
|
|
1372
1446
|
return;
|
|
1373
1447
|
}
|
|
1374
1448
|
if (add.code !== 0) {
|
|
1375
1449
|
sendJson(response, 409, { error: add.stderr.trim() || "Unable to stage workspace files" });
|
|
1376
1450
|
return;
|
|
1377
1451
|
}
|
|
1378
|
-
const commit = await gitCommand(root, ["commit", "-m", payload.message.trim(), "--", ...paths]);
|
|
1452
|
+
const commit = await gitCommand(root, ["commit", "-m", payload.message.trim(), "--", ...paths], GIT_MUTATION_TIMEOUT_MS);
|
|
1379
1453
|
if (commit.terminated) {
|
|
1380
|
-
sendJson(response, 500, { error: gitTerminationMessage("commit", commit.terminated) });
|
|
1454
|
+
sendJson(response, 500, { error: gitTerminationMessage("commit", commit.terminated, GIT_MUTATION_TIMEOUT_MS) });
|
|
1381
1455
|
return;
|
|
1382
1456
|
}
|
|
1383
1457
|
if (commit.code !== 0) {
|
|
@@ -1429,9 +1503,9 @@ export default {
|
|
|
1429
1503
|
return;
|
|
1430
1504
|
}
|
|
1431
1505
|
if (trackedPaths.length > 0) {
|
|
1432
|
-
const restore = await gitCommand(root, ["restore", "--worktree", "--staged", "--", ...trackedPaths]);
|
|
1506
|
+
const restore = await gitCommand(root, ["restore", "--worktree", "--staged", "--", ...trackedPaths], GIT_MUTATION_TIMEOUT_MS);
|
|
1433
1507
|
if (restore.terminated) {
|
|
1434
|
-
sendJson(response, 500, { error: gitTerminationMessage("restore", restore.terminated) });
|
|
1508
|
+
sendJson(response, 500, { error: gitTerminationMessage("restore", restore.terminated, GIT_MUTATION_TIMEOUT_MS) });
|
|
1435
1509
|
return;
|
|
1436
1510
|
}
|
|
1437
1511
|
if (restore.code !== 0) {
|
|
@@ -1803,20 +1877,44 @@ export default {
|
|
|
1803
1877
|
sendJson(response, 409, { error: "Cannot batch-delete the active session" });
|
|
1804
1878
|
return;
|
|
1805
1879
|
}
|
|
1806
|
-
|
|
1880
|
+
if (action === "delete") {
|
|
1881
|
+
// The unlinks run outside the metadata mutation: a failure halfway through must not discard the key removals for the files that are already gone from disk.
|
|
1882
|
+
const removed: string[] = [];
|
|
1883
|
+
const failed: { path: string; error: string }[] = [];
|
|
1807
1884
|
for (const path of paths) {
|
|
1808
|
-
|
|
1885
|
+
try {
|
|
1809
1886
|
await unlink(path);
|
|
1810
|
-
|
|
1811
|
-
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
...(action === "archive" || action === "unarchive" ? { archived: action === "archive" } : {}),
|
|
1816
|
-
...(action === "pin" || action === "unpin" ? { pinned: action === "pin" } : {}),
|
|
1817
|
-
};
|
|
1887
|
+
removed.push(path);
|
|
1888
|
+
} catch (error) {
|
|
1889
|
+
// A session another tab already deleted leaves nothing to unlink, but its metadata entry still has to go.
|
|
1890
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") removed.push(path);
|
|
1891
|
+
else failed.push({ path, error: errorText(error) });
|
|
1818
1892
|
}
|
|
1819
1893
|
}
|
|
1894
|
+
await mutateSessionMetadata(manager, context.logger, (metadata) => {
|
|
1895
|
+
for (const path of removed) delete metadata[path];
|
|
1896
|
+
});
|
|
1897
|
+
if (failed.length > 0) {
|
|
1898
|
+
sendJson(response, 409, {
|
|
1899
|
+
error: `Some sessions could not be deleted: ${failed.map((item) => item.path).join(", ")}`,
|
|
1900
|
+
action,
|
|
1901
|
+
count: removed.length,
|
|
1902
|
+
failed,
|
|
1903
|
+
});
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
sendJson(response, 200, { action, count: removed.length });
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
await mutateSessionMetadata(manager, context.logger, (metadata) => {
|
|
1910
|
+
for (const path of paths) {
|
|
1911
|
+
const current = metadata[path] ?? {};
|
|
1912
|
+
metadata[path] = {
|
|
1913
|
+
...current,
|
|
1914
|
+
...(action === "archive" || action === "unarchive" ? { archived: action === "archive" } : {}),
|
|
1915
|
+
...(action === "pin" || action === "unpin" ? { pinned: action === "pin" } : {}),
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1820
1918
|
});
|
|
1821
1919
|
sendJson(response, 200, { action, count: paths.length });
|
|
1822
1920
|
} catch (error) {
|
|
@@ -1955,7 +2053,7 @@ export default {
|
|
|
1955
2053
|
const page = Math.max(0, Number.parseInt(url.searchParams.get("page") ?? "0", 10) || 0);
|
|
1956
2054
|
const pageSize = Math.min(100, Math.max(1, Number.parseInt(url.searchParams.get("pageSize") ?? "50", 10) || 50));
|
|
1957
2055
|
const includeArchived = url.searchParams.get("includeArchived") === "true";
|
|
1958
|
-
const metadata = await
|
|
2056
|
+
const metadata = await readSessionMetadataLocked(manager, context.logger);
|
|
1959
2057
|
const items =
|
|
1960
2058
|
typeof manager.isPersisted === "function" && manager.isPersisted() ? await SessionManager.list(services.launch.cwd, manager.getSessionDir()) : [];
|
|
1961
2059
|
const filtered = items.filter((item) => includeArchived || metadata[item.path]?.archived !== true);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "agent-teams",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/agent-teams",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Agent Team Board",
|
|
6
6
|
"description": "Maintain a bounded, session-local collaboration ledger of named roles, dependency-aware tasks, and mailbox notes without spawning agents or sending external messages.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "anchored-standard",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/anchored-standard",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Anchored Standard",
|
|
6
6
|
"description": "Audit agent trajectories against an explicit tool-call allowlist and flag activity outside the anchored run.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "annotation",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/annotation",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Annotations",
|
|
6
6
|
"description": "Capture bounded selections and notes from the conversation for later agent context.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "archify",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/archify",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Architecture Map",
|
|
6
6
|
"description": "Build a bounded, read-only architecture map from workspace components and package dependencies.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "at-file",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/at-file",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "@file Context",
|
|
6
6
|
"description": "Attach a bounded 256 KiB strict UTF-8 workspace file using canonical workspace path confinement and no-follow regular-file reads, framing it as offline, read-only, untrusted model context with closing-tag neutralization and cancellable sequential execution.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "auto-mode",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/auto-mode",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Auto Mode",
|
|
6
6
|
"description": "Execute argv commands under a safe policy that blocks shell wrappers and requires confirmation for risky operations.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "better-sidebar",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/better-sidebar",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Better Sidebar",
|
|
6
6
|
"description": "Show a compact workspace, Git, and session overview beside the conversation without modifying files.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "browser-fetch",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/browser-fetch",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Browser Fetch",
|
|
6
6
|
"description": "Fetch public HTTP and HTTPS pages as bounded text with descriptor-safe inputs, DNS pinning, per-redirect private-network validation, textual MIME enforcement, cancellation, a whole-request timeout, and validated fail-closed panel reporting.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "browser-session",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/browser-session",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Browser Session",
|
|
6
6
|
"description": "Control a loopback-only Chrome DevTools session with descriptor-safe commands, bounded discovery, cancellable operations, screenshot metadata protection, and validated fail-closed panel previews.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "canvas-draw",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/canvas-draw",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Canvas Draw",
|
|
6
6
|
"description": "Generate validated, bounded Mermaid flowchart source from structured nodes and edges in the workspace UI.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "change-verifier",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/change-verifier",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Change Verifier",
|
|
6
6
|
"description": "Combine project tests and Git change review into one explicit verification gate before handoff.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "cleaner",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/cleaner",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Cleaner",
|
|
6
6
|
"description": "Strict descriptor-safe configuration and parameters, display-safe bounded Pi Harness Git capsule inventory, removal with explicit confirmation and retention controls, symlink and replacement defenses, cancellable serialization, and a fail-closed normalized panel.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "cli-notifier",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/cli-notifier",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "CLI Notifier",
|
|
6
6
|
"description": "Send local desktop notifications when an agent turn completes, fails, or is aborted, and when context compaction fails.",
|
|
7
7
|
"author": "Pi Harness",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "code2skill",
|
|
3
3
|
"packageName": "@pi-harness/core/plugins/code2skill",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"name": "Code2Skill",
|
|
6
6
|
"description": "Package selected workspace source files into a bounded local Pi skill with a generated SKILL.md manifest and preserved references.",
|
|
7
7
|
"author": "Pi Harness",
|