@pi-harness/pi-harness 0.1.21 → 0.1.23
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 +1 -1
- package/apps/web/dist/assets/index-Bo9CNI_U.js +22 -0
- package/apps/web/dist/index.html +1 -1
- package/apps/web/package.json +6 -6
- package/apps/web/server-dist/bin.js +18 -5
- package/apps/web/server-dist/bin.js.map +1 -1
- package/apps/web/src/server/bin.ts +18 -5
- package/apps/web/test/bin.test.ts +90 -0
- package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/index.js +204 -66
- 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 +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +3 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +3 -13
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +2 -5
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +2 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +4 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +3 -13
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +3 -13
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +3 -12
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +3 -11
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +2 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +3 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +2 -6
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +3 -13
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +3 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +2 -6
- package/node_modules/@pi-harness/api-gateway/package.json +1 -1
- package/node_modules/@pi-harness/cli/dist/node-stdio.d.ts.map +1 -1
- package/node_modules/@pi-harness/cli/dist/node-stdio.js +3 -1
- package/node_modules/@pi-harness/cli/dist/node-stdio.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 +6 -1
- 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.map +1 -1
- package/node_modules/@pi-harness/host-webserver/dist/index.js +52 -3
- 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 +3 -0
- package/node_modules/@pi-harness/web-app/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/web-app/dist/index.js +9 -5
- 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 +204 -66
- package/packages/api-gateway/dist/index.js.map +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +3 -8
- package/packages/api-gateway/dist/marketplace-entries/official/archify.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +3 -13
- package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +2 -5
- package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +2 -8
- package/packages/api-gateway/dist/marketplace-entries/official/context.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/genui.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +4 -11
- package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +3 -13
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/memory.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +3 -13
- package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +3 -12
- package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +3 -11
- package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +2 -7
- package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +3 -9
- package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +2 -6
- package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +3 -13
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +3 -10
- package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +2 -6
- package/packages/api-gateway/package.json +1 -1
- package/packages/api-gateway/src/index.ts +227 -68
- package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/annotation.json +3 -8
- package/packages/api-gateway/src/marketplace-entries/official/archify.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/at-file.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +3 -13
- package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +2 -5
- package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +2 -8
- package/packages/api-gateway/src/marketplace-entries/official/context.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/genui.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +4 -11
- package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +3 -13
- package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/memory.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/modlens.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/module-search.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/openpets.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +3 -13
- package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/session-export.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/session-search.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +3 -12
- package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/synapse.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +3 -11
- package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +2 -7
- package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +3 -9
- package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +2 -6
- package/packages/api-gateway/src/marketplace-entries/official/web-research.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +3 -13
- package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +3 -10
- package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +2 -6
- package/packages/api-gateway/test/index.test.ts +363 -1
- package/packages/api-gateway/test/marketplace-schema.test.ts +139 -0
- package/packages/api-gateway/test/release-contract.test.ts +77 -0
- package/packages/api-gateway/test/release-package.test.ts +1 -1
- package/packages/api-gateway/test/release-version.test.ts +6 -4
- package/packages/bundle-web-app/dist/index.d.ts +3 -0
- package/packages/bundle-web-app/dist/index.d.ts.map +1 -1
- package/packages/bundle-web-app/dist/index.js +9 -5
- 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 +12 -5
- package/packages/bundle-web-app/test/index.test.ts +33 -2
- package/packages/cli/dist/node-stdio.d.ts.map +1 -1
- package/packages/cli/dist/node-stdio.js +3 -1
- 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 +6 -1
- package/packages/cli/dist/relaunch.js.map +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/node-stdio.ts +6 -3
- package/packages/cli/src/relaunch.ts +5 -1
- package/packages/cli/test/node-stdio.test.ts +43 -0
- package/packages/cli/test/relaunch.test.ts +35 -0
- package/packages/host-webserver/dist/index.d.ts.map +1 -1
- package/packages/host-webserver/dist/index.js +52 -3
- 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 +57 -3
- package/packages/host-webserver/test/index.test.ts +129 -1
- package/apps/web/dist/assets/index-e92yZuUr.js +0 -22
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { mkdir, mkdtemp, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
|
-
import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { atomicWriteFile } from "@pi-harness/core";
|
|
6
7
|
import { MARKETPLACE_CAPABILITIES, MARKETPLACE_CATEGORIES, MARKETPLACE_PLUGINS, attachMarketplaceStatistics, createMarketplaceStatisticsLoader, paginateMarketplace, searchMarketplace, needsMarketplacePackageInstall, sortMarketplaceByRecommendation, } from "./marketplace.js";
|
|
7
8
|
import { parseGitWorktrees } from "./workspaces.js";
|
|
8
9
|
const loadMarketplaceStatistics = createMarketplaceStatisticsLoader();
|
|
10
|
+
const DEFAULT_BODY_LIMIT_BYTES = 64 * 1024;
|
|
11
|
+
const IMPORT_CONTENT_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
12
|
+
// The import body carries the JSONL content as a JSON string, so quotes and newlines are escaped; leave headroom above the content limit for that overhead.
|
|
13
|
+
const IMPORT_BODY_LIMIT_BYTES = 16 * 1024 * 1024;
|
|
14
|
+
// Retained trajectory events are replayed to every SSE client and returned by /api/session, so the array must stay bounded.
|
|
15
|
+
const MAX_RETAINED_EVENTS = 2000;
|
|
16
|
+
const GIT_TIMEOUT_MS = 15_000;
|
|
17
|
+
class PayloadTooLargeError extends Error {
|
|
18
|
+
constructor() {
|
|
19
|
+
super("Request body is too large");
|
|
20
|
+
this.name = "PayloadTooLargeError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
9
23
|
function sendJson(response, status, payload) {
|
|
10
24
|
const body = JSON.stringify(payload);
|
|
11
25
|
response.writeHead(status, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", "content-length": Buffer.byteLength(body) });
|
|
12
26
|
response.end(body);
|
|
13
27
|
}
|
|
14
|
-
async function bodyText(request) {
|
|
28
|
+
async function bodyText(request, maxBytes = DEFAULT_BODY_LIMIT_BYTES) {
|
|
15
29
|
const chunks = [];
|
|
16
30
|
let length = 0;
|
|
17
31
|
for await (const chunk of request) {
|
|
18
32
|
const input = chunk;
|
|
19
33
|
const value = typeof input === "string" ? input : Buffer.from(input).toString("utf8");
|
|
20
34
|
length += Buffer.byteLength(value);
|
|
21
|
-
if (length >
|
|
22
|
-
throw new
|
|
35
|
+
if (length > maxBytes)
|
|
36
|
+
throw new PayloadTooLargeError();
|
|
23
37
|
chunks.push(value);
|
|
24
38
|
}
|
|
25
39
|
return chunks.join("");
|
|
@@ -106,26 +120,63 @@ function piConfig(services) {
|
|
|
106
120
|
function sessionMetadataFile(manager) {
|
|
107
121
|
return resolve(manager.getSessionDir(), ".pi-harness-session-meta.json");
|
|
108
122
|
}
|
|
109
|
-
|
|
123
|
+
// A missing file is the normal first-run state. Any other read or parse 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.
|
|
124
|
+
async function readSessionMetadata(manager, logger) {
|
|
125
|
+
const file = sessionMetadataFile(manager);
|
|
126
|
+
let raw;
|
|
110
127
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
raw = await readFile(file, "utf8");
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error.code === "ENOENT")
|
|
113
132
|
return {};
|
|
133
|
+
await quarantineSessionMetadata(file, logger, error);
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(raw);
|
|
138
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
139
|
+
throw new Error("session metadata must be a JSON object");
|
|
114
140
|
return parsed;
|
|
115
141
|
}
|
|
116
|
-
catch {
|
|
142
|
+
catch (error) {
|
|
143
|
+
await quarantineSessionMetadata(file, logger, error);
|
|
117
144
|
return {};
|
|
118
145
|
}
|
|
119
146
|
}
|
|
147
|
+
async function quarantineSessionMetadata(file, logger, error) {
|
|
148
|
+
const quarantined = `${file}.corrupt-${Date.now()}`;
|
|
149
|
+
try {
|
|
150
|
+
await rename(file, quarantined);
|
|
151
|
+
logger.warn(`Session metadata at ${file} is unreadable (${errorText(error)}); moved it to ${quarantined} and starting from an empty map`);
|
|
152
|
+
}
|
|
153
|
+
catch (renameError) {
|
|
154
|
+
logger.warn(`Session metadata at ${file} is unreadable (${errorText(error)}) and could not be quarantined: ${errorText(renameError)}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
120
157
|
async function writeSessionMetadata(manager, metadata) {
|
|
121
158
|
await mkdir(manager.getSessionDir(), { recursive: true });
|
|
122
|
-
await
|
|
159
|
+
await atomicWriteFile(sessionMetadataFile(manager), JSON.stringify(metadata, null, 2) + "\n", { encoding: "utf8" });
|
|
160
|
+
}
|
|
161
|
+
// Every read-modify-write of the metadata file runs through this chain so concurrent requests cannot interleave and drop each other's updates.
|
|
162
|
+
let sessionMetadataQueue = Promise.resolve();
|
|
163
|
+
function mutateSessionMetadata(manager, logger, mutate) {
|
|
164
|
+
const operation = sessionMetadataQueue
|
|
165
|
+
.catch(() => undefined)
|
|
166
|
+
.then(async () => {
|
|
167
|
+
const metadata = await readSessionMetadata(manager, logger);
|
|
168
|
+
const result = await mutate(metadata);
|
|
169
|
+
await writeSessionMetadata(manager, metadata);
|
|
170
|
+
return result;
|
|
171
|
+
});
|
|
172
|
+
sessionMetadataQueue = operation;
|
|
173
|
+
return operation;
|
|
123
174
|
}
|
|
124
175
|
function sessionPathInDirectory(path, manager) {
|
|
125
176
|
const root = resolve(manager.getSessionDir());
|
|
126
177
|
const target = resolve(path);
|
|
127
178
|
const relativePath = relative(root, target);
|
|
128
|
-
return relativePath !== "" && !isAbsolute(relativePath) && relativePath !== ".." && !relativePath.startsWith(".." +
|
|
179
|
+
return relativePath !== "" && !isAbsolute(relativePath) && relativePath !== ".." && !relativePath.startsWith(".." + sep) && target.endsWith(".jsonl");
|
|
129
180
|
}
|
|
130
181
|
const webSessionUi = {
|
|
131
182
|
select: (_title, options) => Promise.resolve(options[0]),
|
|
@@ -412,21 +463,52 @@ async function updateMarketplaceProfile(configPath, entryId, update) {
|
|
|
412
463
|
function writeSse(response, payload) {
|
|
413
464
|
response.write(`data: ${JSON.stringify(jsonSafe(payload))}\n\n`);
|
|
414
465
|
}
|
|
466
|
+
// Node reports a maxBuffer overflow through a string error code and a timeout through `killed`; neither is a git exit status, so they must not be folded into an ordinary non-zero exit.
|
|
467
|
+
function gitTermination(error) {
|
|
468
|
+
if (error === null)
|
|
469
|
+
return undefined;
|
|
470
|
+
if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER")
|
|
471
|
+
return "output-limit";
|
|
472
|
+
if (error.killed === true)
|
|
473
|
+
return "timeout";
|
|
474
|
+
return undefined;
|
|
475
|
+
}
|
|
476
|
+
function gitTerminationMessage(command, termination) {
|
|
477
|
+
return termination === "timeout"
|
|
478
|
+
? `git ${command} timed out after ${GIT_TIMEOUT_MS / 1000} seconds`
|
|
479
|
+
: `git ${command} produced more output than the buffer limit allows`;
|
|
480
|
+
}
|
|
415
481
|
function gitStatus(cwd) {
|
|
416
|
-
return new Promise((
|
|
417
|
-
execFile("git", ["status", "--short", "--untracked-files=all"], { cwd, maxBuffer: 512 * 1024 }, (error, stdout) =>
|
|
482
|
+
return new Promise((resolveStatus, rejectStatus) => {
|
|
483
|
+
execFile("git", ["status", "--short", "--untracked-files=all"], { cwd, timeout: GIT_TIMEOUT_MS, maxBuffer: 512 * 1024 }, (error, stdout, stderr) => {
|
|
484
|
+
if (error === null) {
|
|
485
|
+
resolveStatus({ output: stdout, truncated: false });
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const termination = gitTermination(error);
|
|
489
|
+
if (termination === "output-limit") {
|
|
490
|
+
// Keep the complete lines that arrived before the kill; the final line may have been cut mid-path.
|
|
491
|
+
resolveStatus({ output: stdout.slice(0, stdout.lastIndexOf("\n") + 1), truncated: true });
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (termination === undefined && error.code === 128 && /not a git repository/i.test(stderr)) {
|
|
495
|
+
resolveStatus({ output: "", truncated: false });
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
rejectStatus(new Error(termination ? gitTerminationMessage("status", termination) : stderr.trim() || error.message, { cause: error }));
|
|
499
|
+
});
|
|
418
500
|
});
|
|
419
501
|
}
|
|
420
502
|
function gitDiff(cwd, path) {
|
|
421
503
|
return new Promise((resolveOutput) => {
|
|
422
|
-
execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, maxBuffer: 1024 * 1024 }, (error, stdout) => resolveOutput(error && stdout.length === 0 ? "" : stdout));
|
|
504
|
+
execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, timeout: GIT_TIMEOUT_MS, maxBuffer: 1024 * 1024 }, (error, stdout) => resolveOutput(error && stdout.length === 0 ? "" : stdout));
|
|
423
505
|
});
|
|
424
506
|
}
|
|
425
507
|
function gitCommand(cwd, args) {
|
|
426
508
|
return new Promise((resolveResult) => {
|
|
427
|
-
execFile("git", [...args], { cwd, maxBuffer: 2 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
509
|
+
execFile("git", [...args], { cwd, timeout: GIT_TIMEOUT_MS, maxBuffer: 2 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
428
510
|
const code = error && typeof error.code === "number" ? error.code : error ? 1 : 0;
|
|
429
|
-
resolveResult({ stdout, stderr, code });
|
|
511
|
+
resolveResult({ stdout, stderr, code, terminated: gitTermination(error) });
|
|
430
512
|
});
|
|
431
513
|
});
|
|
432
514
|
}
|
|
@@ -503,7 +585,12 @@ export default {
|
|
|
503
585
|
const events = [];
|
|
504
586
|
const eventClients = new Set();
|
|
505
587
|
const handleEvent = (event) => {
|
|
506
|
-
events.
|
|
588
|
+
// Streaming deltas reach clients live over SSE and each one carries the whole partial message, so only durable events are retained for snapshots.
|
|
589
|
+
if (event.type !== "message_update") {
|
|
590
|
+
events.push(event);
|
|
591
|
+
if (events.length > MAX_RETAINED_EVENTS)
|
|
592
|
+
events.splice(0, events.length - MAX_RETAINED_EVENTS);
|
|
593
|
+
}
|
|
507
594
|
for (const response of eventClients) {
|
|
508
595
|
if (response.writableEnded || response.destroyed) {
|
|
509
596
|
eventClients.delete(response);
|
|
@@ -639,7 +726,9 @@ export default {
|
|
|
639
726
|
return;
|
|
640
727
|
}
|
|
641
728
|
const path = join(services.launch.agentDir, "settings.json");
|
|
642
|
-
|
|
729
|
+
// Replace the file atomically so an interrupted write never leaves a truncated settings.json behind; keep the existing permission bits.
|
|
730
|
+
const mode = await stat(path).then((info) => info.mode & 0o777, () => 0o644);
|
|
731
|
+
await atomicWriteFile(path, JSON.stringify(parsed, null, 2) + "\n", { encoding: "utf8", mode });
|
|
643
732
|
await services.runtime.session.settingsManager.reload();
|
|
644
733
|
sendJson(response, 200, piConfig(services));
|
|
645
734
|
}
|
|
@@ -1149,8 +1238,15 @@ export default {
|
|
|
1149
1238
|
const disposeFiles = services.webServer.register({
|
|
1150
1239
|
path: "/api/files",
|
|
1151
1240
|
async handler(_request, response) {
|
|
1152
|
-
|
|
1153
|
-
|
|
1241
|
+
let status;
|
|
1242
|
+
try {
|
|
1243
|
+
status = await gitStatus(activeCwd(services));
|
|
1244
|
+
}
|
|
1245
|
+
catch (error) {
|
|
1246
|
+
sendJson(response, 500, { error: errorText(error) });
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
const items = status.output
|
|
1154
1250
|
.split("\n")
|
|
1155
1251
|
.map((line) => line.trimEnd())
|
|
1156
1252
|
.filter((line) => line.length > 0)
|
|
@@ -1162,7 +1258,7 @@ export default {
|
|
|
1162
1258
|
label: status === "??" ? "untracked" : status.includes("D") ? "deleted" : status.includes("A") ? "added" : "modified",
|
|
1163
1259
|
};
|
|
1164
1260
|
});
|
|
1165
|
-
sendJson(response, 200, { items });
|
|
1261
|
+
sendJson(response, 200, { items, ...(status.truncated ? { truncated: true } : {}) });
|
|
1166
1262
|
},
|
|
1167
1263
|
});
|
|
1168
1264
|
const disposeFileDiff = services.webServer.register({
|
|
@@ -1181,7 +1277,7 @@ export default {
|
|
|
1181
1277
|
const root = resolve(activeCwd(services));
|
|
1182
1278
|
const absolute = resolve(root, requested);
|
|
1183
1279
|
const relativePath = relative(root, absolute);
|
|
1184
|
-
if (isAbsolute(relativePath) || relativePath === ".." || relativePath.startsWith(".." +
|
|
1280
|
+
if (isAbsolute(relativePath) || relativePath === ".." || relativePath.startsWith(".." + sep)) {
|
|
1185
1281
|
sendJson(response, 400, { error: "path must stay inside the workspace" });
|
|
1186
1282
|
return;
|
|
1187
1283
|
}
|
|
@@ -1208,11 +1304,19 @@ export default {
|
|
|
1208
1304
|
}
|
|
1209
1305
|
const root = resolve(activeCwd(services));
|
|
1210
1306
|
const add = await gitCommand(root, ["add", "-A", "--", ...paths]);
|
|
1307
|
+
if (add.terminated) {
|
|
1308
|
+
sendJson(response, 500, { error: gitTerminationMessage("add", add.terminated) });
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1211
1311
|
if (add.code !== 0) {
|
|
1212
1312
|
sendJson(response, 409, { error: add.stderr.trim() || "Unable to stage workspace files" });
|
|
1213
1313
|
return;
|
|
1214
1314
|
}
|
|
1215
1315
|
const commit = await gitCommand(root, ["commit", "-m", payload.message.trim(), "--", ...paths]);
|
|
1316
|
+
if (commit.terminated) {
|
|
1317
|
+
sendJson(response, 500, { error: gitTerminationMessage("commit", commit.terminated) });
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1216
1320
|
if (commit.code !== 0) {
|
|
1217
1321
|
sendJson(response, 409, { error: commit.stdout.trim() || commit.stderr.trim() || "Nothing to commit" });
|
|
1218
1322
|
return;
|
|
@@ -1244,16 +1348,39 @@ export default {
|
|
|
1244
1348
|
sendJson(response, 400, { error: paths.message });
|
|
1245
1349
|
return;
|
|
1246
1350
|
}
|
|
1247
|
-
const untracked = await gitCommand(root, ["ls-files", "--others", "--exclude-standard", "--", ...paths]);
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1351
|
+
const untracked = await gitCommand(root, ["ls-files", "-z", "--others", "--exclude-standard", "--", ...paths]);
|
|
1352
|
+
// `git restore` refuses the whole request when any pathspec is unknown to it, so restore only the paths git tracks. `--with-tree=HEAD` keeps staged deletions in the list; it fails on an unborn HEAD, where the plain index listing is all there is.
|
|
1353
|
+
let tracked = await gitCommand(root, ["ls-files", "-z", "--with-tree=HEAD", "--", ...paths]);
|
|
1354
|
+
if (tracked.code !== 0 && tracked.terminated === undefined)
|
|
1355
|
+
tracked = await gitCommand(root, ["ls-files", "-z", "--", ...paths]);
|
|
1356
|
+
const listing = [untracked, tracked].find((result) => result.terminated !== undefined || result.code !== 0);
|
|
1357
|
+
if (listing) {
|
|
1358
|
+
if (listing.terminated)
|
|
1359
|
+
sendJson(response, 500, { error: gitTerminationMessage("ls-files", listing.terminated) });
|
|
1360
|
+
else
|
|
1361
|
+
sendJson(response, 409, { error: listing.stderr.trim() || "Unable to inspect workspace files" });
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
const untrackedPaths = untracked.stdout.split("\0").filter(Boolean);
|
|
1365
|
+
const trackedPaths = tracked.stdout.split("\0").filter(Boolean);
|
|
1366
|
+
const known = [...untrackedPaths, ...trackedPaths];
|
|
1367
|
+
const unknown = paths.filter((path) => !known.some((candidate) => candidate === path || candidate.startsWith(path + "/")));
|
|
1368
|
+
if (unknown.length > 0) {
|
|
1369
|
+
sendJson(response, 409, { error: `Paths did not match any file known to git: ${unknown.join(", ")}` });
|
|
1251
1370
|
return;
|
|
1252
1371
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
.
|
|
1256
|
-
|
|
1372
|
+
if (trackedPaths.length > 0) {
|
|
1373
|
+
const restore = await gitCommand(root, ["restore", "--worktree", "--staged", "--", ...trackedPaths]);
|
|
1374
|
+
if (restore.terminated) {
|
|
1375
|
+
sendJson(response, 500, { error: gitTerminationMessage("restore", restore.terminated) });
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
if (restore.code !== 0) {
|
|
1379
|
+
sendJson(response, 409, { error: restore.stderr.trim() || "Unable to restore workspace files" });
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
for (const path of untrackedPaths) {
|
|
1257
1384
|
await rm(resolve(root, path), { recursive: true, force: true });
|
|
1258
1385
|
}
|
|
1259
1386
|
sendJson(response, 200, { reverted: true, paths });
|
|
@@ -1291,6 +1418,10 @@ export default {
|
|
|
1291
1418
|
const disposePrompt = services.webServer.register({
|
|
1292
1419
|
path: "/api/prompt",
|
|
1293
1420
|
async handler(request, response) {
|
|
1421
|
+
if (request.method !== "POST") {
|
|
1422
|
+
sendJson(response, 405, { error: "Method not allowed" });
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1294
1425
|
if (busy) {
|
|
1295
1426
|
sendJson(response, 409, { error: "Another prompt is already running" });
|
|
1296
1427
|
return;
|
|
@@ -1541,9 +1672,9 @@ export default {
|
|
|
1541
1672
|
events.length = 0;
|
|
1542
1673
|
}
|
|
1543
1674
|
await unlink(path);
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1675
|
+
await mutateSessionMetadata(manager, context.logger, (metadata) => {
|
|
1676
|
+
delete metadata[path];
|
|
1677
|
+
});
|
|
1547
1678
|
sendJson(response, 200, { deleted: true, path, sessionFile: services.runtime.session.sessionFile });
|
|
1548
1679
|
}
|
|
1549
1680
|
catch (error) {
|
|
@@ -1566,16 +1697,17 @@ export default {
|
|
|
1566
1697
|
sendJson(response, 400, { error: "Invalid session path" });
|
|
1567
1698
|
return;
|
|
1568
1699
|
}
|
|
1569
|
-
const
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1700
|
+
const nextMetadata = await mutateSessionMetadata(manager, context.logger, (metadata) => {
|
|
1701
|
+
const currentMetadata = metadata[path] ?? {};
|
|
1702
|
+
const updated = {
|
|
1703
|
+
...currentMetadata,
|
|
1704
|
+
...(payload.archived === undefined ? {} : { archived: payload.archived === true }),
|
|
1705
|
+
...(payload.pinned === undefined ? {} : { pinned: payload.pinned === true }),
|
|
1706
|
+
};
|
|
1707
|
+
metadata[path] = updated;
|
|
1708
|
+
return updated;
|
|
1709
|
+
});
|
|
1710
|
+
sendJson(response, 200, { path, metadata: nextMetadata });
|
|
1579
1711
|
}
|
|
1580
1712
|
catch (error) {
|
|
1581
1713
|
sendJson(response, 400, { error: errorText(error) });
|
|
@@ -1612,22 +1744,22 @@ export default {
|
|
|
1612
1744
|
sendJson(response, 409, { error: "Cannot batch-delete the active session" });
|
|
1613
1745
|
return;
|
|
1614
1746
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1747
|
+
await mutateSessionMetadata(manager, context.logger, async (metadata) => {
|
|
1748
|
+
for (const path of paths) {
|
|
1749
|
+
if (action === "delete") {
|
|
1750
|
+
await unlink(path);
|
|
1751
|
+
delete metadata[path];
|
|
1752
|
+
}
|
|
1753
|
+
else {
|
|
1754
|
+
const current = metadata[path] ?? {};
|
|
1755
|
+
metadata[path] = {
|
|
1756
|
+
...current,
|
|
1757
|
+
...(action === "archive" || action === "unarchive" ? { archived: action === "archive" } : {}),
|
|
1758
|
+
...(action === "pin" || action === "unpin" ? { pinned: action === "pin" } : {}),
|
|
1759
|
+
};
|
|
1760
|
+
}
|
|
1628
1761
|
}
|
|
1629
|
-
}
|
|
1630
|
-
await writeSessionMetadata(manager, metadata);
|
|
1762
|
+
});
|
|
1631
1763
|
sendJson(response, 200, { action, count: paths.length });
|
|
1632
1764
|
}
|
|
1633
1765
|
catch (error) {
|
|
@@ -1677,11 +1809,16 @@ export default {
|
|
|
1677
1809
|
return;
|
|
1678
1810
|
}
|
|
1679
1811
|
try {
|
|
1680
|
-
const payload = JSON.parse(await bodyText(request));
|
|
1812
|
+
const payload = JSON.parse(await bodyText(request, IMPORT_BODY_LIMIT_BYTES));
|
|
1681
1813
|
const suppliedPath = typeof payload.path === "string" ? payload.path : "";
|
|
1682
1814
|
const content = typeof payload.content === "string" ? payload.content : undefined;
|
|
1683
|
-
|
|
1684
|
-
|
|
1815
|
+
// `path` reads an existing file and `content` is written to a private temporary file; accepting both would let the request choose where the content lands.
|
|
1816
|
+
if (suppliedPath && content !== undefined) {
|
|
1817
|
+
sendJson(response, 400, { error: "Provide either a JSONL file path or file content, not both" });
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
if (content === undefined && (!suppliedPath || !isAbsolute(suppliedPath) || !suppliedPath.endsWith(".jsonl"))) {
|
|
1821
|
+
sendJson(response, 400, { error: "An absolute .jsonl file path or file content is required" });
|
|
1685
1822
|
return;
|
|
1686
1823
|
}
|
|
1687
1824
|
const manager = services.runtime.session.sessionManager;
|
|
@@ -1691,11 +1828,12 @@ export default {
|
|
|
1691
1828
|
}
|
|
1692
1829
|
const targetCwd = typeof payload.cwd === "string" && payload.cwd.trim() ? resolve(payload.cwd) : activeCwd(services);
|
|
1693
1830
|
const temporaryDirectory = content === undefined ? undefined : await mkdtemp(join(tmpdir(), "pi-harness-import-"));
|
|
1694
|
-
const
|
|
1695
|
-
|
|
1831
|
+
const requestedName = basename(typeof payload.filename === "string" && payload.filename.trim() ? payload.filename : "import.jsonl");
|
|
1832
|
+
const importName = requestedName === "" || requestedName === "." || requestedName === ".." ? "import.jsonl" : requestedName;
|
|
1833
|
+
const importPath = temporaryDirectory === undefined ? suppliedPath : join(temporaryDirectory, importName);
|
|
1696
1834
|
try {
|
|
1697
1835
|
if (content !== undefined) {
|
|
1698
|
-
if (Buffer.byteLength(content, "utf8") >
|
|
1836
|
+
if (Buffer.byteLength(content, "utf8") > IMPORT_CONTENT_LIMIT_BYTES) {
|
|
1699
1837
|
sendJson(response, 413, { error: "Imported session must be at most 10 MiB" });
|
|
1700
1838
|
return;
|
|
1701
1839
|
}
|
|
@@ -1723,7 +1861,7 @@ export default {
|
|
|
1723
1861
|
}
|
|
1724
1862
|
}
|
|
1725
1863
|
catch (error) {
|
|
1726
|
-
sendJson(response, 400, { error: errorText(error) });
|
|
1864
|
+
sendJson(response, error instanceof PayloadTooLargeError ? 413 : 400, { error: errorText(error) });
|
|
1727
1865
|
}
|
|
1728
1866
|
},
|
|
1729
1867
|
});
|
|
@@ -1761,7 +1899,7 @@ export default {
|
|
|
1761
1899
|
const page = Math.max(0, Number.parseInt(url.searchParams.get("page") ?? "0", 10) || 0);
|
|
1762
1900
|
const pageSize = Math.min(100, Math.max(1, Number.parseInt(url.searchParams.get("pageSize") ?? "50", 10) || 50));
|
|
1763
1901
|
const includeArchived = url.searchParams.get("includeArchived") === "true";
|
|
1764
|
-
const metadata = await readSessionMetadata(manager);
|
|
1902
|
+
const metadata = await readSessionMetadata(manager, context.logger);
|
|
1765
1903
|
const items = typeof manager.isPersisted === "function" && manager.isPersisted() ? await SessionManager.list(services.launch.cwd, manager.getSessionDir()) : [];
|
|
1766
1904
|
const filtered = items.filter((item) => includeArchived || metadata[item.path]?.archived !== true);
|
|
1767
1905
|
const sorted = filtered.sort((a, b) => Number(metadata[b.path]?.pinned === true) - Number(metadata[a.path]?.pinned === true) || b.modified.getTime() - a.modified.getTime());
|