@opengsd/gsd-pi 1.7.0 → 1.8.1-dev.897b3c90
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 +8 -6
- package/dist/cli.js +5 -1
- package/dist/headless-events.d.ts +2 -1
- package/dist/headless-events.js +11 -3
- package/dist/headless-milestone-readiness.d.ts +29 -0
- package/dist/headless-milestone-readiness.js +161 -0
- package/dist/headless.js +25 -2
- package/dist/print-mode-exit.d.ts +12 -0
- package/dist/print-mode-exit.js +14 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +16 -47
- package/dist/resources/extensions/browser-tools/capture.js +2 -77
- package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +35 -1
- package/dist/resources/extensions/gsd/auto.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +78 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +84 -26
- package/dist/resources/extensions/gsd/command-feedback.js +16 -12
- package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
- package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +51 -16
- package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
- package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
- package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -4
- package/dist/resources/extensions/gsd/doctor-history.js +65 -0
- package/dist/resources/extensions/gsd/doctor-state-checks.js +509 -0
- package/dist/resources/extensions/gsd/doctor-workspace-checks.js +91 -0
- package/dist/resources/extensions/gsd/doctor.js +14 -653
- package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
- package/dist/resources/extensions/gsd/gsd-db.js +187 -45
- package/dist/resources/extensions/gsd/guided-flow.js +29 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +16 -2
- package/dist/resources/extensions/gsd/md-importer.js +109 -16
- package/dist/resources/extensions/gsd/migrate/command.js +19 -162
- package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
- package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
- package/dist/resources/extensions/gsd/migrate/planning-writer.js +20 -19
- package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
- package/dist/resources/extensions/gsd/migration-auto-check.js +4 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
- package/dist/resources/extensions/gsd/paths.js +4 -1
- package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
- package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +54 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +48 -5
- package/dist/resources/extensions/gsd/stop-notice.js +15 -1
- package/dist/resources/extensions/gsd/sync-lock.js +13 -7
- package/dist/resources/extensions/gsd/tools/complete-task.js +82 -1
- package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
- package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
- package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
- package/dist/resources/extensions/gsd/unit-registry.js +4 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
- package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
- package/dist/resources/extensions/mac-tools/index.js +31 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
- package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/package.json +0 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +31 -3
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +12 -10
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-config.d.ts +1 -1
- package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-config.js +30 -8
- package/packages/daemon/dist/cloud-config.js.map +1 -1
- package/packages/daemon/dist/cloud-config.test.js +69 -1
- package/packages/daemon/dist/cloud-config.test.js.map +1 -1
- package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
- package/packages/daemon/dist/local-tool-executor.js +2 -0
- package/packages/daemon/dist/local-tool-executor.js.map +1 -1
- package/packages/daemon/package.json +6 -6
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/README.md +18 -4
- package/packages/gsd-cloud/bin/gsd-cloud.js +6 -5
- package/packages/gsd-cloud/dist/cli.d.ts +5 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cli.js +160 -0
- package/packages/gsd-cloud/dist/cli.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.js +231 -0
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.js +37 -0
- package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
- package/packages/gsd-cloud/dist/config.d.ts +17 -0
- package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/config.js +146 -0
- package/packages/gsd-cloud/dist/config.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.js +128 -0
- package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
- package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.js +11 -0
- package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.js +29 -0
- package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
- package/packages/gsd-cloud/dist/index.d.ts +7 -0
- package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/index.js +8 -0
- package/packages/gsd-cloud/dist/index.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
- package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
- package/packages/gsd-cloud/dist/logger.d.ts +25 -0
- package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/logger.js +72 -0
- package/packages/gsd-cloud/dist/logger.js.map +1 -0
- package/packages/gsd-cloud/dist/types.d.ts +51 -0
- package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/types.js +9 -0
- package/packages/gsd-cloud/dist/types.js.map +1 -0
- package/packages/gsd-cloud/package.json +7 -5
- package/packages/mcp-server/README.md +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +60 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +54 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +19 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +16 -47
- package/src/resources/extensions/browser-tools/capture.ts +2 -86
- package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +38 -1
- package/src/resources/extensions/gsd/auto.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +91 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -24
- package/src/resources/extensions/gsd/command-feedback.ts +19 -12
- package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
- package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +53 -17
- package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
- package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
- package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -4
- package/src/resources/extensions/gsd/doctor-history.ts +81 -0
- package/src/resources/extensions/gsd/doctor-state-checks.ts +527 -0
- package/src/resources/extensions/gsd/doctor-workspace-checks.ts +97 -0
- package/src/resources/extensions/gsd/doctor.ts +14 -673
- package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
- package/src/resources/extensions/gsd/gsd-db.ts +255 -52
- package/src/resources/extensions/gsd/guided-flow.ts +39 -10
- package/src/resources/extensions/gsd/markdown-renderer.ts +23 -7
- package/src/resources/extensions/gsd/md-importer.ts +116 -13
- package/src/resources/extensions/gsd/migrate/command.ts +21 -227
- package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
- package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
- package/src/resources/extensions/gsd/migrate/planning-writer.ts +21 -23
- package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
- package/src/resources/extensions/gsd/migration-auto-check.ts +3 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
- package/src/resources/extensions/gsd/paths.ts +4 -1
- package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +67 -20
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +47 -5
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
- package/src/resources/extensions/gsd/stop-notice.ts +18 -1
- package/src/resources/extensions/gsd/sync-lock.ts +14 -6
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +286 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +76 -1
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/doctor-history-public-api.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
- package/src/resources/extensions/gsd/tests/planning-writer.test.ts +47 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +18 -3
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +177 -25
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +120 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
- package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
- package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
- package/src/resources/extensions/gsd/types.ts +11 -0
- package/src/resources/extensions/gsd/unit-registry.ts +4 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
- package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
- package/src/resources/extensions/mac-tools/index.ts +52 -9
- package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
- package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
- /package/dist/web/standalone/.next/static/{enWQFRY-aLTUq3wmxG2Qz → TezjdjSHBVRRr54XjAvte}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{enWQFRY-aLTUq3wmxG2Qz → TezjdjSHBVRRr54XjAvte}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-config.js","sourceRoot":"","sources":["../src/cloud-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { lookup } from \"node:dns\";\nimport type { LookupOneOptions } from \"node:dns\";\nimport { request as httpRequest } from \"node:http\";\nimport { request as httpsRequest } from \"node:https\";\nimport { isIP } from \"node:net\";\nimport type { LookupFunction } from \"node:net\";\nimport { dirname } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { loadConfig } from \"./config.js\";\nimport { protectCloudDeviceToken } from \"./cloud-token.js\";\nimport type { DaemonConfig } from \"./types.js\";\n\nexport interface PairingExchangeResult {\n runtimeId: string;\n deviceToken: string;\n}\n\nexport async function exchangePairingCode(params: {\n gatewayUrl: string;\n code: string;\n runtimeName?: string;\n}): Promise<PairingExchangeResult> {\n const pairingUrl = new URL(\"/pairing/exchange\", parseCloudGatewayUrl(params.gatewayUrl));\n const body = await postJsonToValidatedGateway(pairingUrl, {\n code: params.code,\n runtimeName: params.runtimeName,\n });\n if (typeof body.runtimeId !== \"string\" || typeof body.deviceToken !== \"string\") {\n throw new Error(\"Pairing response did not include runtimeId and deviceToken\");\n }\n return { runtimeId: body.runtimeId, deviceToken: body.deviceToken };\n}\n\nexport function parseCloudGatewayUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Cloud gateway URL must be an absolute HTTP(S) URL\");\n }\n\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new Error(\"Cloud gateway URL must use http or https\");\n }\n if (url.username || url.password) {\n throw new Error(\"Cloud gateway URL must not include credentials\");\n }\n if (url.hash) {\n throw new Error(\"Cloud gateway URL must not include a fragment\");\n }\n if (url.protocol === \"http:\" && !isLoopbackHost(url.hostname)) {\n throw new Error(\"Plain HTTP cloud gateway URLs are only allowed for localhost\");\n }\n if (url.protocol === \"https:\" && isPrivateIpHost(url.hostname)) {\n throw new Error(\"Cloud gateway URL must not target private or loopback IP addresses\");\n }\n\n url.pathname = url.pathname.replace(/\\/+$/, \"\");\n url.search = \"\";\n return url;\n}\n\nexport function saveCloudConfig(configPath: string, nextCloud: NonNullable<DaemonConfig[\"cloud\"]>): DaemonConfig {\n let raw: Record<string, unknown> = {};\n try {\n raw = parseYaml(readFileSync(configPath, \"utf-8\")) as Record<string, unknown> ?? {};\n } catch {\n raw = {};\n }\n const { device_token: deviceToken, ...cloud } = nextCloud;\n raw.cloud = {\n ...cloud,\n gateway_url: parseCloudGatewayUrl(nextCloud.gateway_url).toString(),\n ...(deviceToken ? { device_token_encrypted: protectCloudDeviceToken(deviceToken) } : {}),\n };\n mkdirSync(dirname(configPath), { recursive: true });\n writeConfigFile(configPath, stringifyYaml(raw));\n return loadConfig(configPath);\n}\n\nexport function clearCloudConfig(configPath: string): DaemonConfig {\n let raw: Record<string, unknown> = {};\n try {\n raw = parseYaml(readFileSync(configPath, \"utf-8\")) as Record<string, unknown> ?? {};\n } catch {\n raw = {};\n }\n delete raw.cloud;\n mkdirSync(dirname(configPath), { recursive: true });\n writeConfigFile(configPath, stringifyYaml(raw));\n return loadConfig(configPath);\n}\n\nexport function redactedCloudStatus(config: DaemonConfig): Record<string, unknown> {\n const cloud = config.cloud;\n if (!cloud) return { configured: false };\n return {\n configured: true,\n enabled: cloud.enabled ?? true,\n gateway_url: cloud.gateway_url,\n runtime_id: cloud.runtime_id ?? null,\n runtime_name: cloud.runtime_name ?? null,\n [\"device_\" + \"token\"]: cloud.device_token ? \"[redacted]\" : null,\n };\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n const host = hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\" || host === \"[::1]\";\n}\n\nfunction isPrivateIpHost(hostname: string): boolean {\n const host = hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n if (host === \"localhost\") return true;\n if (isIP(host) === 4) return isPrivateIpv4(host);\n if (isIP(host) === 6) return isPrivateIpv6(host);\n return false;\n}\n\nexport function validateGatewayNetworkTarget(url: URL): void {\n if (url.protocol === \"http:\" && isLoopbackHost(url.hostname)) return;\n if (isPrivateIpHost(url.hostname)) {\n throw new Error(\"Cloud gateway URL must not target private or loopback IP addresses\");\n }\n}\n\nexport function createGatewayLookup(url: URL): LookupFunction {\n const allowLoopback = url.protocol === \"http:\" && isLoopbackHost(url.hostname);\n return (hostname, options, callback) => {\n const lookupOptions: LookupOneOptions = typeof options === \"number\"\n ? { family: options, all: false }\n : { ...options, all: false };\n lookup(hostname, lookupOptions, (err, address, family) => {\n if (err) return callback(err, address, family);\n if (!address || (!allowLoopback && isPrivateIpHost(address))) {\n return callback(new Error(\"Cloud gateway URL resolved to a private or loopback address\"), address, family);\n }\n callback(null, address, family);\n });\n };\n}\n\nfunction isPrivateIpv4(host: string): boolean {\n const octets = host.split(\".\").map((part) => Number(part));\n if (octets.length !== 4 || octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return true;\n const [a, b] = octets;\n if (a === 10 || a === 127 || a === 0) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 192 && b === 0) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n if (a >= 224) return true;\n return false;\n}\n\nfunction isPrivateIpv6(host: string): boolean {\n return host === \"::\"\n || host === \"::1\"\n || host.startsWith(\"fc\")\n || host.startsWith(\"fd\")\n || host.startsWith(\"fe80:\")\n || host.startsWith(\"2001:db8:\");\n}\n\nfunction writeConfigFile(configPath: string, contents: string): void {\n writeFileSync(configPath, contents, { encoding: \"utf-8\", mode: 0o600 });\n chmodSync(configPath, 0o600);\n}\n\nexport function postJsonToValidatedGateway(url: URL, payload: Record<string, unknown>): Promise<Record<string, unknown>> {\n validateGatewayNetworkTarget(url);\n const body = JSON.stringify(payload);\n const requestImpl = url.protocol === \"https:\" ? httpsRequest : httpRequest;\n\n return new Promise((resolve, reject) => {\n const req = requestImpl({\n protocol: url.protocol,\n hostname: url.hostname,\n port: url.port,\n path: `${url.pathname}${url.search}`,\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"content-length\": Buffer.byteLength(body),\n },\n lookup: createGatewayLookup(url),\n }, (res) => {\n const statusCode = res.statusCode ?? 0;\n const chunks: Buffer[] = [];\n res.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n res.on(\"end\", () => {\n const responseText = Buffer.concat(chunks).toString(\"utf-8\");\n const parsed = parseJsonObject(responseText);\n if (statusCode < 200 || statusCode >= 300) {\n reject(new Error(typeof parsed.error === \"string\" ? parsed.error : `Pairing failed with HTTP ${statusCode}`));\n return;\n }\n resolve(parsed);\n });\n });\n\n req.on(\"error\", reject);\n req.end(body);\n });\n}\n\nfunction parseJsonObject(value: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(value) as unknown;\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n } catch {\n return {};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cloud-config.js","sourceRoot":"","sources":["../src/cloud-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { lookup } from \"node:dns\";\nimport type { LookupOptions } from \"node:dns\";\nimport { request as httpRequest } from \"node:http\";\nimport { request as httpsRequest } from \"node:https\";\nimport { isIP } from \"node:net\";\nimport type { LookupFunction } from \"node:net\";\nimport { dirname } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { loadConfig } from \"./config.js\";\nimport { protectCloudDeviceToken } from \"./cloud-token.js\";\nimport type { DaemonConfig } from \"./types.js\";\n\nexport interface PairingExchangeResult {\n runtimeId: string;\n deviceToken: string;\n}\n\nexport async function exchangePairingCode(params: {\n gatewayUrl: string;\n code: string;\n runtimeName?: string;\n}): Promise<PairingExchangeResult> {\n const pairingUrl = new URL(\"/pairing/exchange\", parseCloudGatewayUrl(params.gatewayUrl));\n const body = await postJsonToValidatedGateway(pairingUrl, {\n code: params.code,\n runtimeName: params.runtimeName,\n });\n if (typeof body.runtimeId !== \"string\" || typeof body.deviceToken !== \"string\") {\n throw new Error(\"Pairing response did not include runtimeId and deviceToken\");\n }\n return { runtimeId: body.runtimeId, deviceToken: body.deviceToken };\n}\n\nexport function parseCloudGatewayUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Cloud gateway URL must be an absolute HTTP(S) URL\");\n }\n\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new Error(\"Cloud gateway URL must use http or https\");\n }\n if (url.username || url.password) {\n throw new Error(\"Cloud gateway URL must not include credentials\");\n }\n if (url.hash) {\n throw new Error(\"Cloud gateway URL must not include a fragment\");\n }\n if (url.protocol === \"http:\" && !isLoopbackHost(url.hostname)) {\n throw new Error(\"Plain HTTP cloud gateway URLs are only allowed for localhost\");\n }\n if (url.protocol === \"https:\" && isPrivateIpHost(url.hostname)) {\n throw new Error(\"Cloud gateway URL must not target private or loopback IP addresses\");\n }\n\n url.pathname = url.pathname.replace(/\\/+$/, \"\");\n url.search = \"\";\n return url;\n}\n\nexport function saveCloudConfig(configPath: string, nextCloud: NonNullable<DaemonConfig[\"cloud\"]>): DaemonConfig {\n let raw: Record<string, unknown> = {};\n try {\n raw = parseYaml(readFileSync(configPath, \"utf-8\")) as Record<string, unknown> ?? {};\n } catch {\n raw = {};\n }\n const { device_token: deviceToken, ...cloud } = nextCloud;\n raw.cloud = {\n ...cloud,\n gateway_url: parseCloudGatewayUrl(nextCloud.gateway_url).toString(),\n ...(deviceToken ? { device_token_encrypted: protectCloudDeviceToken(deviceToken) } : {}),\n };\n mkdirSync(dirname(configPath), { recursive: true });\n writeConfigFile(configPath, stringifyYaml(raw));\n return loadConfig(configPath);\n}\n\nexport function clearCloudConfig(configPath: string): DaemonConfig {\n let raw: Record<string, unknown> = {};\n try {\n raw = parseYaml(readFileSync(configPath, \"utf-8\")) as Record<string, unknown> ?? {};\n } catch {\n raw = {};\n }\n delete raw.cloud;\n mkdirSync(dirname(configPath), { recursive: true });\n writeConfigFile(configPath, stringifyYaml(raw));\n return loadConfig(configPath);\n}\n\nexport function redactedCloudStatus(config: DaemonConfig): Record<string, unknown> {\n const cloud = config.cloud;\n if (!cloud) return { configured: false };\n return {\n configured: true,\n enabled: cloud.enabled ?? true,\n gateway_url: cloud.gateway_url,\n runtime_id: cloud.runtime_id ?? null,\n runtime_name: cloud.runtime_name ?? null,\n [\"device_\" + \"token\"]: cloud.device_token ? \"[redacted]\" : null,\n };\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n const host = hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\" || host === \"[::1]\";\n}\n\nfunction isPrivateIpHost(hostname: string): boolean {\n const host = hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n if (host === \"localhost\") return true;\n if (isIP(host) === 4) return isPrivateIpv4(host);\n if (isIP(host) === 6) return isPrivateIpv6(host);\n return false;\n}\n\nexport function validateGatewayNetworkTarget(url: URL): void {\n if (url.protocol === \"http:\" && isLoopbackHost(url.hostname)) return;\n if (isPrivateIpHost(url.hostname)) {\n throw new Error(\"Cloud gateway URL must not target private or loopback IP addresses\");\n }\n}\n\nexport function createGatewayLookup(url: URL): LookupFunction {\n const allowLoopback = url.protocol === \"http:\" && isLoopbackHost(url.hostname);\n const rejected = (address: string): boolean =>\n !address || (!allowLoopback && isPrivateIpHost(address));\n // Node's socket connect (autoSelectFamily / Happy Eyeballs, default-on since\n // Node 20) calls a custom lookup with `all: true` and expects an ARRAY\n // callback. Forcing `all: false` + a scalar callback made every real gateway\n // request throw \"Invalid IP address: undefined\". Honor both forms; the SSRF\n // guard is applied to every resolved address (reject the whole lookup if any\n // is private/loopback — an attacker-controlled resolver must not slip one in).\n return ((hostname: string, options: unknown, callback: (...args: unknown[]) => void) => {\n const wantsAll =\n typeof options === \"object\" && options !== null && (options as LookupOptions).all === true;\n const base: LookupOptions =\n typeof options === \"number\" ? { family: options } : { ...(options as LookupOptions) };\n if (wantsAll) {\n lookup(hostname, { ...base, all: true }, (err, addresses) => {\n if (err) return callback(err);\n const list = addresses as Array<{ address: string; family: number }>;\n if (!list.length || list.some((entry) => rejected(entry.address))) {\n return callback(new Error(\"Cloud gateway URL resolved to a private or loopback address\"));\n }\n callback(null, list);\n });\n return;\n }\n lookup(hostname, { ...base, all: false }, (err, address, family) => {\n if (err) return callback(err, address, family);\n if (rejected(address)) {\n return callback(new Error(\"Cloud gateway URL resolved to a private or loopback address\"), address, family);\n }\n callback(null, address, family);\n });\n }) as unknown as LookupFunction;\n}\n\nfunction isPrivateIpv4(host: string): boolean {\n const octets = host.split(\".\").map((part) => Number(part));\n if (octets.length !== 4 || octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return true;\n const [a, b] = octets;\n if (a === 10 || a === 127 || a === 0) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 192 && b === 0) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n if (a >= 224) return true;\n return false;\n}\n\nfunction isPrivateIpv6(host: string): boolean {\n return host === \"::\"\n || host === \"::1\"\n || host.startsWith(\"fc\")\n || host.startsWith(\"fd\")\n || host.startsWith(\"fe80:\")\n || host.startsWith(\"2001:db8:\");\n}\n\nfunction writeConfigFile(configPath: string, contents: string): void {\n writeFileSync(configPath, contents, { encoding: \"utf-8\", mode: 0o600 });\n chmodSync(configPath, 0o600);\n}\n\nconst GATEWAY_REQUEST_TIMEOUT_MS = 30_000;\n\nexport function postJsonToValidatedGateway(\n url: URL,\n payload: Record<string, unknown>,\n timeoutMs: number = GATEWAY_REQUEST_TIMEOUT_MS,\n): Promise<Record<string, unknown>> {\n validateGatewayNetworkTarget(url);\n const body = JSON.stringify(payload);\n const requestImpl = url.protocol === \"https:\" ? httpsRequest : httpRequest;\n\n return new Promise((resolve, reject) => {\n const req = requestImpl({\n protocol: url.protocol,\n hostname: url.hostname,\n port: url.port,\n path: `${url.pathname}${url.search}`,\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"content-length\": Buffer.byteLength(body),\n },\n lookup: createGatewayLookup(url),\n }, (res) => {\n const statusCode = res.statusCode ?? 0;\n const chunks: Buffer[] = [];\n res.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n res.on(\"end\", () => {\n const responseText = Buffer.concat(chunks).toString(\"utf-8\");\n const parsed = parseJsonObject(responseText);\n if (statusCode < 200 || statusCode >= 300) {\n reject(new Error(typeof parsed.error === \"string\" ? parsed.error : `Pairing failed with HTTP ${statusCode}`));\n return;\n }\n resolve(parsed);\n });\n });\n\n req.setTimeout(timeoutMs, () => {\n req.destroy(new Error(`Gateway request timed out after ${timeoutMs}ms`));\n });\n req.on(\"error\", reject);\n req.end(body);\n });\n}\n\nfunction parseJsonObject(value: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(value) as unknown;\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n } catch {\n return {};\n }\n}\n"]}
|
|
@@ -5,7 +5,48 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { test } from "node:test";
|
|
7
7
|
import { loadConfig } from "./config.js";
|
|
8
|
-
import { exchangePairingCode, parseCloudGatewayUrl, redactedCloudStatus, saveCloudConfig } from "./cloud-config.js";
|
|
8
|
+
import { createGatewayLookup, exchangePairingCode, parseCloudGatewayUrl, postJsonToValidatedGateway, redactedCloudStatus, saveCloudConfig } from "./cloud-config.js";
|
|
9
|
+
// Start a loopback server, returning its base URL; skips the test under sandbox EPERM.
|
|
10
|
+
async function listenLoopback(t, handler) {
|
|
11
|
+
const server = createServer(handler);
|
|
12
|
+
try {
|
|
13
|
+
await new Promise((resolve, reject) => {
|
|
14
|
+
server.once("error", reject);
|
|
15
|
+
server.listen(0, "127.0.0.1", resolve);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err.code === "EPERM") {
|
|
20
|
+
t.skip("loopback listen is blocked in this sandbox");
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
const address = server.address();
|
|
26
|
+
assert.ok(address && typeof address === "object");
|
|
27
|
+
return {
|
|
28
|
+
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
29
|
+
close: () => new Promise((resolve, reject) => server.close((err) => err ? reject(err) : resolve())),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Invoke a gateway lookup and capture (err, result) from its Node-style callback.
|
|
33
|
+
function runGatewayLookup(url, options) {
|
|
34
|
+
const lookup = createGatewayLookup(new URL(url));
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
lookup("localhost", options, (...args) => resolve({ err: args[0] ?? null, result: args[1] }));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
test("createGatewayLookup honors all:true with an array callback (regression: scalar form threw 'Invalid IP address' on Node >=20)", async () => {
|
|
40
|
+
const { err, result } = await runGatewayLookup("http://localhost", { all: true, family: 0 });
|
|
41
|
+
assert.equal(err, null, "loopback allowed for http URL");
|
|
42
|
+
assert.ok(Array.isArray(result), "all:true must call back with an array");
|
|
43
|
+
assert.ok(result.length > 0, "expected at least one address");
|
|
44
|
+
});
|
|
45
|
+
test("createGatewayLookup all:true still enforces the SSRF guard on every address", async () => {
|
|
46
|
+
const { err } = await runGatewayLookup("https://localhost", { all: true, family: 0 });
|
|
47
|
+
assert.ok(err instanceof Error, "https loopback must be rejected");
|
|
48
|
+
assert.match(err.message, /private or loopback/);
|
|
49
|
+
});
|
|
9
50
|
test("cloud config stores device token but redacts status output", () => {
|
|
10
51
|
const dir = mkdtempSync(join(tmpdir(), "gsd-cloud-config-"));
|
|
11
52
|
const configPath = join(dir, "daemon.yaml");
|
|
@@ -82,6 +123,33 @@ test("pairing exchange rejects unsafe gateway URLs before making requests", asyn
|
|
|
82
123
|
globalThis.fetch = originalFetch;
|
|
83
124
|
}
|
|
84
125
|
});
|
|
126
|
+
test("postJsonToValidatedGateway rejects when the gateway never responds", async (t) => {
|
|
127
|
+
// Handler that accepts the request but never sends a response — the hung-server case.
|
|
128
|
+
const server = await listenLoopback(t, () => { });
|
|
129
|
+
if (!server)
|
|
130
|
+
return;
|
|
131
|
+
try {
|
|
132
|
+
await assert.rejects(postJsonToValidatedGateway(new URL(`${server.baseUrl}/x`), {}, 200), /timed out after 200ms/);
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
await server.close();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
test("postJsonToValidatedGateway resolves a fast healthy response before the timeout", async (t) => {
|
|
139
|
+
const server = await listenLoopback(t, (_req, res) => {
|
|
140
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
141
|
+
res.end("{}");
|
|
142
|
+
});
|
|
143
|
+
if (!server)
|
|
144
|
+
return;
|
|
145
|
+
try {
|
|
146
|
+
const body = await postJsonToValidatedGateway(new URL(`${server.baseUrl}/x`), {}, 200);
|
|
147
|
+
assert.deepEqual(body, {});
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
await server.close();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
85
153
|
test("pairing exchange posts to a validated gateway URL", async (t) => {
|
|
86
154
|
let requestedUrl = "";
|
|
87
155
|
let requestBody = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-config.test.js","sourceRoot":"","sources":["../src/cloud-config.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { createServer } from \"node:http\";\nimport { mkdtempSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { test } from \"node:test\";\nimport { loadConfig } from \"./config.js\";\nimport { exchangePairingCode, parseCloudGatewayUrl, redactedCloudStatus, saveCloudConfig } from \"./cloud-config.js\";\n\ntest(\"cloud config stores device token but redacts status output\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"gsd-cloud-config-\"));\n const configPath = join(dir, \"daemon.yaml\");\n\n const config = saveCloudConfig(configPath, {\n gateway_url: \"https://gateway.example\",\n device_token: \"secret-device-token\",\n runtime_id: \"rt1\",\n runtime_name: \"Laptop\",\n enabled: true,\n });\n\n const rawConfig = readFileSync(configPath, \"utf8\");\n assert.doesNotMatch(rawConfig, /secret-device-token/);\n assert.match(rawConfig, /device_token_encrypted:/);\n assert.equal(statSync(configPath).mode & 0o777, 0o600);\n assert.equal(config.cloud?.device_token, \"secret-device-token\");\n assert.deepEqual(redactedCloudStatus(config), {\n configured: true,\n enabled: true,\n gateway_url: \"https://gateway.example/\",\n runtime_id: \"rt1\",\n runtime_name: \"Laptop\",\n [\"device_\" + \"token\"]: \"[redacted]\",\n });\n});\n\ntest(\"cloud config still reads legacy plaintext device tokens\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"gsd-cloud-config-legacy-\"));\n const configPath = join(dir, \"daemon.yaml\");\n const legacyToken = \"legacy-secret-device-token\";\n writeFileSync(configPath, [\n \"cloud:\",\n \" gateway_url: https://gateway.example/\",\n ` device_token: ${legacyToken}`,\n \" runtime_id: rt1\",\n \"\",\n ].join(\"\\n\"));\n assert.equal(loadConfig(configPath).cloud?.device_token, legacyToken);\n\n const config = saveCloudConfig(configPath, {\n gateway_url: \"https://gateway.example\",\n device_token: legacyToken,\n runtime_id: \"rt1\",\n });\n\n const rawConfig = readFileSync(configPath, \"utf8\");\n assert.equal(config.cloud?.device_token, legacyToken);\n assert.doesNotMatch(rawConfig, new RegExp(legacyToken));\n assert.match(rawConfig, /device_token_encrypted:/);\n});\n\ntest(\"cloud gateway URL validation allows HTTPS and localhost HTTP\", () => {\n assert.equal(parseCloudGatewayUrl(\"https://gateway.example/base/\").toString(), \"https://gateway.example/base\");\n assert.equal(parseCloudGatewayUrl(\"http://localhost:8787\").toString(), \"http://localhost:8787/\");\n assert.equal(parseCloudGatewayUrl(\"http://127.0.0.1:8787\").toString(), \"http://127.0.0.1:8787/\");\n});\n\ntest(\"cloud gateway URL validation rejects unsafe destinations\", () => {\n assert.throws(() => parseCloudGatewayUrl(\"file:///tmp/socket\"), /must use http or https/);\n assert.throws(() => parseCloudGatewayUrl(\"http://gateway.example\"), /Plain HTTP/);\n assert.throws(() => parseCloudGatewayUrl(\"https://user:pass@gateway.example\"), /must not include credentials/);\n assert.throws(() => parseCloudGatewayUrl(\"https://gateway.example/#token\"), /must not include a fragment/);\n assert.throws(() => parseCloudGatewayUrl(\"https://127.0.0.1:8787\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://10.0.0.5\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://192.168.1.10\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://[::1]:8787\"), /must not target private/);\n});\n\ntest(\"pairing exchange rejects unsafe gateway URLs before making requests\", async () => {\n const originalFetch = globalThis.fetch;\n let called = false;\n globalThis.fetch = (async () => {\n called = true;\n throw new Error(\"fetch should not be called\");\n }) as typeof fetch;\n try {\n await assert.rejects(\n exchangePairingCode({ gatewayUrl: \"https://127.0.0.1:8787\", code: \"ABCD1234\" }),\n /must not target private/,\n );\n assert.equal(called, false);\n } finally {\n globalThis.fetch = originalFetch;\n }\n});\n\ntest(\"pairing exchange posts to a validated gateway URL\", async (t) => {\n let requestedUrl = \"\";\n let requestBody = \"\";\n const runtimeAuthValue = \"runtime-auth-fixture\";\n const server = createServer((req, res) => {\n requestedUrl = req.url ?? \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk) => {\n requestBody += chunk;\n });\n req.on(\"end\", () => {\n res.writeHead(200, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify({\n runtimeId: \"rt1\",\n [\"device\" + \"Token\"]: runtimeAuthValue,\n }));\n });\n });\n try {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EPERM\") {\n t.skip(\"loopback listen is blocked in this sandbox\");\n return;\n }\n throw err;\n }\n try {\n const address = server.address();\n assert.ok(address && typeof address === \"object\");\n const result = await exchangePairingCode({\n gatewayUrl: `http://127.0.0.1:${address.port}/base?ignored=true`,\n code: \"ABCD1234\",\n });\n assert.equal(result.runtimeId, \"rt1\");\n assert.equal(result.deviceToken, runtimeAuthValue);\n assert.equal(requestedUrl, \"/pairing/exchange\");\n assert.deepEqual(JSON.parse(requestBody), { code: \"ABCD1234\" });\n } finally {\n await new Promise<void>((resolve, reject) => server.close((err) => err ? reject(err) : resolve()));\n }\n});\n"]}
|
|
1
|
+
{"version":3,"file":"cloud-config.test.js","sourceRoot":"","sources":["../src/cloud-config.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { createServer, type RequestListener } from \"node:http\";\nimport { mkdtempSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { test } from \"node:test\";\nimport { loadConfig } from \"./config.js\";\nimport { createGatewayLookup, exchangePairingCode, parseCloudGatewayUrl, postJsonToValidatedGateway, redactedCloudStatus, saveCloudConfig } from \"./cloud-config.js\";\n\n// Start a loopback server, returning its base URL; skips the test under sandbox EPERM.\nasync function listenLoopback(\n t: { skip: (msg: string) => void },\n handler: RequestListener,\n): Promise<{ baseUrl: string; close: () => Promise<void> } | null> {\n const server = createServer(handler);\n try {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EPERM\") {\n t.skip(\"loopback listen is blocked in this sandbox\");\n return null;\n }\n throw err;\n }\n const address = server.address();\n assert.ok(address && typeof address === \"object\");\n return {\n baseUrl: `http://127.0.0.1:${address.port}`,\n close: () => new Promise<void>((resolve, reject) => server.close((err) => err ? reject(err) : resolve())),\n };\n}\n\n// Invoke a gateway lookup and capture (err, result) from its Node-style callback.\nfunction runGatewayLookup(url: string, options: unknown): Promise<{ err: Error | null; result: unknown }> {\n const lookup = createGatewayLookup(new URL(url));\n return new Promise((resolve) => {\n (lookup as unknown as (h: string, o: unknown, cb: (...a: unknown[]) => void) => void)(\n \"localhost\",\n options,\n (...args: unknown[]) => resolve({ err: (args[0] as Error | null) ?? null, result: args[1] }),\n );\n });\n}\n\ntest(\"createGatewayLookup honors all:true with an array callback (regression: scalar form threw 'Invalid IP address' on Node >=20)\", async () => {\n const { err, result } = await runGatewayLookup(\"http://localhost\", { all: true, family: 0 });\n assert.equal(err, null, \"loopback allowed for http URL\");\n assert.ok(Array.isArray(result), \"all:true must call back with an array\");\n assert.ok((result as unknown[]).length > 0, \"expected at least one address\");\n});\n\ntest(\"createGatewayLookup all:true still enforces the SSRF guard on every address\", async () => {\n const { err } = await runGatewayLookup(\"https://localhost\", { all: true, family: 0 });\n assert.ok(err instanceof Error, \"https loopback must be rejected\");\n assert.match(err!.message, /private or loopback/);\n});\n\ntest(\"cloud config stores device token but redacts status output\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"gsd-cloud-config-\"));\n const configPath = join(dir, \"daemon.yaml\");\n\n const config = saveCloudConfig(configPath, {\n gateway_url: \"https://gateway.example\",\n device_token: \"secret-device-token\",\n runtime_id: \"rt1\",\n runtime_name: \"Laptop\",\n enabled: true,\n });\n\n const rawConfig = readFileSync(configPath, \"utf8\");\n assert.doesNotMatch(rawConfig, /secret-device-token/);\n assert.match(rawConfig, /device_token_encrypted:/);\n assert.equal(statSync(configPath).mode & 0o777, 0o600);\n assert.equal(config.cloud?.device_token, \"secret-device-token\");\n assert.deepEqual(redactedCloudStatus(config), {\n configured: true,\n enabled: true,\n gateway_url: \"https://gateway.example/\",\n runtime_id: \"rt1\",\n runtime_name: \"Laptop\",\n [\"device_\" + \"token\"]: \"[redacted]\",\n });\n});\n\ntest(\"cloud config still reads legacy plaintext device tokens\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"gsd-cloud-config-legacy-\"));\n const configPath = join(dir, \"daemon.yaml\");\n const legacyToken = \"legacy-secret-device-token\";\n writeFileSync(configPath, [\n \"cloud:\",\n \" gateway_url: https://gateway.example/\",\n ` device_token: ${legacyToken}`,\n \" runtime_id: rt1\",\n \"\",\n ].join(\"\\n\"));\n assert.equal(loadConfig(configPath).cloud?.device_token, legacyToken);\n\n const config = saveCloudConfig(configPath, {\n gateway_url: \"https://gateway.example\",\n device_token: legacyToken,\n runtime_id: \"rt1\",\n });\n\n const rawConfig = readFileSync(configPath, \"utf8\");\n assert.equal(config.cloud?.device_token, legacyToken);\n assert.doesNotMatch(rawConfig, new RegExp(legacyToken));\n assert.match(rawConfig, /device_token_encrypted:/);\n});\n\ntest(\"cloud gateway URL validation allows HTTPS and localhost HTTP\", () => {\n assert.equal(parseCloudGatewayUrl(\"https://gateway.example/base/\").toString(), \"https://gateway.example/base\");\n assert.equal(parseCloudGatewayUrl(\"http://localhost:8787\").toString(), \"http://localhost:8787/\");\n assert.equal(parseCloudGatewayUrl(\"http://127.0.0.1:8787\").toString(), \"http://127.0.0.1:8787/\");\n});\n\ntest(\"cloud gateway URL validation rejects unsafe destinations\", () => {\n assert.throws(() => parseCloudGatewayUrl(\"file:///tmp/socket\"), /must use http or https/);\n assert.throws(() => parseCloudGatewayUrl(\"http://gateway.example\"), /Plain HTTP/);\n assert.throws(() => parseCloudGatewayUrl(\"https://user:pass@gateway.example\"), /must not include credentials/);\n assert.throws(() => parseCloudGatewayUrl(\"https://gateway.example/#token\"), /must not include a fragment/);\n assert.throws(() => parseCloudGatewayUrl(\"https://127.0.0.1:8787\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://10.0.0.5\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://192.168.1.10\"), /must not target private/);\n assert.throws(() => parseCloudGatewayUrl(\"https://[::1]:8787\"), /must not target private/);\n});\n\ntest(\"pairing exchange rejects unsafe gateway URLs before making requests\", async () => {\n const originalFetch = globalThis.fetch;\n let called = false;\n globalThis.fetch = (async () => {\n called = true;\n throw new Error(\"fetch should not be called\");\n }) as typeof fetch;\n try {\n await assert.rejects(\n exchangePairingCode({ gatewayUrl: \"https://127.0.0.1:8787\", code: \"ABCD1234\" }),\n /must not target private/,\n );\n assert.equal(called, false);\n } finally {\n globalThis.fetch = originalFetch;\n }\n});\n\ntest(\"postJsonToValidatedGateway rejects when the gateway never responds\", async (t) => {\n // Handler that accepts the request but never sends a response — the hung-server case.\n const server = await listenLoopback(t, () => { /* never call res.end */ });\n if (!server) return;\n try {\n await assert.rejects(\n postJsonToValidatedGateway(new URL(`${server.baseUrl}/x`), {}, 200),\n /timed out after 200ms/,\n );\n } finally {\n await server.close();\n }\n});\n\ntest(\"postJsonToValidatedGateway resolves a fast healthy response before the timeout\", async (t) => {\n const server = await listenLoopback(t, (_req, res) => {\n res.writeHead(200, { \"content-type\": \"application/json\" });\n res.end(\"{}\");\n });\n if (!server) return;\n try {\n const body = await postJsonToValidatedGateway(new URL(`${server.baseUrl}/x`), {}, 200);\n assert.deepEqual(body, {});\n } finally {\n await server.close();\n }\n});\n\ntest(\"pairing exchange posts to a validated gateway URL\", async (t) => {\n let requestedUrl = \"\";\n let requestBody = \"\";\n const runtimeAuthValue = \"runtime-auth-fixture\";\n const server = createServer((req, res) => {\n requestedUrl = req.url ?? \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk) => {\n requestBody += chunk;\n });\n req.on(\"end\", () => {\n res.writeHead(200, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify({\n runtimeId: \"rt1\",\n [\"device\" + \"Token\"]: runtimeAuthValue,\n }));\n });\n });\n try {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EPERM\") {\n t.skip(\"loopback listen is blocked in this sandbox\");\n return;\n }\n throw err;\n }\n try {\n const address = server.address();\n assert.ok(address && typeof address === \"object\");\n const result = await exchangePairingCode({\n gatewayUrl: `http://127.0.0.1:${address.port}/base?ignored=true`,\n code: \"ABCD1234\",\n });\n assert.equal(result.runtimeId, \"rt1\");\n assert.equal(result.deviceToken, runtimeAuthValue);\n assert.equal(requestedUrl, \"/pairing/exchange\");\n assert.deepEqual(JSON.parse(requestBody), { code: \"ABCD1234\" });\n } finally {\n await new Promise<void>((resolve, reject) => server.close((err) => err ? reject(err) : resolve()));\n }\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-tool-executor.d.ts","sourceRoot":"","sources":["../src/local-tool-executor.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgB9C,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJ/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;gBAGhD,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;IAUvD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiFpG,kBAAkB,IAAI,OAAO,CAAC,KAAK,CAAC;QACxC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;YAcW,kBAAkB;YAMlB,kBAAkB;IAOhC,OAAO,CAAC,mBAAmB;
|
|
1
|
+
{"version":3,"file":"local-tool-executor.d.ts","sourceRoot":"","sources":["../src/local-tool-executor.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgB9C,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJ/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;gBAGhD,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;IAUvD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiFpG,kBAAkB,IAAI,OAAO,CAAC,KAAK,CAAC;QACxC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;YAcW,kBAAkB;YAMlB,kBAAkB;IAOhC,OAAO,CAAC,mBAAmB;IAqD3B,OAAO,CAAC,4BAA4B;YAMtB,YAAY;CAgC3B"}
|
|
@@ -151,6 +151,8 @@ export class LocalToolExecutor {
|
|
|
151
151
|
case "gsd_task_plan": return this.invokeRegisteredWorkflowTool("gsd_task_plan", args);
|
|
152
152
|
case "gsd_replan_slice": return this.invokeRegisteredWorkflowTool("gsd_replan_slice", args);
|
|
153
153
|
case "gsd_slice_replan": return this.invokeRegisteredWorkflowTool("gsd_slice_replan", args);
|
|
154
|
+
case "gsd_replan_task": return this.invokeRegisteredWorkflowTool("gsd_replan_task", args);
|
|
155
|
+
case "gsd_rework_brief_save": return this.invokeRegisteredWorkflowTool("gsd_rework_brief_save", args);
|
|
154
156
|
case "gsd_slice_complete": return this.invokeRegisteredWorkflowTool("gsd_slice_complete", args);
|
|
155
157
|
case "gsd_complete_slice": return this.invokeRegisteredWorkflowTool("gsd_complete_slice", args);
|
|
156
158
|
case "gsd_skip_slice": return this.invokeRegisteredWorkflowTool("gsd_skip_slice", args);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-tool-executor.js","sourceRoot":"","sources":["../src/local-tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { execFileSync } from \"node:child_process\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { basename, join, resolve } from \"node:path\";\nimport {\n readCaptures,\n readHistory,\n readKnowledge,\n readProgress,\n readRoadmap,\n buildGraph,\n graphDiff,\n graphQuery,\n graphStatus,\n registerWorkflowTools,\n resolveGsdRoot,\n runDoctorLite,\n writeGraph,\n writeSnapshot,\n WORKFLOW_TOOL_NAMES,\n} from \"@opengsd/mcp-server\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { ProjectInfo } from \"./types.js\";\n\ntype ToolHandler = (args: Record<string, unknown>) => Promise<unknown>;\nconst WORKFLOW_TOOL_NAME_SET = new Set<string>(WORKFLOW_TOOL_NAMES);\nconst QUERY_FIELDS = {\n all: [\"state\", \"project\", \"requirements\", \"milestones\"],\n state: [\"state\"],\n status: [\"state\"],\n project: [\"project\"],\n requirements: [\"requirements\"],\n milestones: [\"milestones\"],\n} as const;\n\ntype QueryCategory = keyof typeof QUERY_FIELDS;\ntype ProjectStateField = (typeof QUERY_FIELDS)[QueryCategory][number];\n\nexport class LocalToolExecutor {\n private readonly workflowHandlers = new Map<string, ToolHandler>();\n\n constructor(\n private readonly sessionManager: SessionManager,\n private readonly scanProjects: () => Promise<ProjectInfo[]>,\n ) {\n registerWorkflowTools({\n tool: (name: string, _description: string, _params: Record<string, unknown>, handler: ToolHandler) => {\n if (!WORKFLOW_TOOL_NAME_SET.has(name)) return;\n this.workflowHandlers.set(name, handler);\n },\n });\n }\n\n async execute(toolName: string, rawArgs: Record<string, unknown>, projectAlias?: string): Promise<unknown> {\n const args = { ...rawArgs };\n if (projectAlias) {\n args.projectDir = await this.resolveProjectPath(projectAlias);\n }\n\n const workflowResult = this.executeWorkflowTool(toolName, args);\n if (workflowResult) return workflowResult;\n\n switch (toolName) {\n case \"gsd_execute\": {\n const projectDir = await this.requiredProjectDir(args);\n const sessionId = await this.sessionManager.startSession({\n projectDir,\n command: typeof args.command === \"string\" ? args.command : undefined,\n model: typeof args.model === \"string\" ? args.model : undefined,\n bare: typeof args.bare === \"boolean\" ? args.bare : undefined,\n });\n return { content: [{ type: \"text\", text: JSON.stringify({ sessionId, status: \"started\" }, null, 2) }] };\n }\n case \"gsd_status\": {\n const session = this.sessionManager.getSession(String(args.sessionId ?? \"\"));\n if (!session) throw new Error(`Session not found: ${String(args.sessionId ?? \"\")}`);\n const toolCallCount = session.events.filter((event) => {\n const type = (event as Record<string, unknown>).type;\n return type === \"tool_use\" || type === \"tool_execution_start\";\n }).length;\n return { content: [{ type: \"text\", text: JSON.stringify({\n status: session.status,\n progress: {\n eventCount: session.events.length,\n toolCalls: toolCallCount,\n },\n recentEvents: session.events.slice(-10),\n pendingBlocker: session.pendingBlocker\n ? {\n id: session.pendingBlocker.id,\n method: session.pendingBlocker.method,\n message: session.pendingBlocker.message,\n }\n : null,\n cost: session.cost,\n durationMs: Date.now() - session.startTime,\n }, null, 2) }] };\n }\n case \"gsd_result\":\n return { content: [{ type: \"text\", text: JSON.stringify(this.sessionManager.getResult(String(args.sessionId ?? \"\")), null, 2) }] };\n case \"gsd_cancel\":\n if (typeof args.sessionId === \"string\") await this.sessionManager.cancelSession(args.sessionId);\n else await this.sessionManager.cancelSessionByDir(await this.requiredProjectDir(args));\n return { content: [{ type: \"text\", text: JSON.stringify({ cancelled: true }, null, 2) }] };\n case \"gsd_resolve_blocker\": {\n const sessionId = String(args.sessionId ?? \"\");\n const response = String(args.response ?? \"\");\n await this.sessionManager.resolveBlocker(sessionId, response);\n return { content: [{ type: \"text\", text: JSON.stringify({ resolved: true }, null, 2) }] };\n }\n case \"gsd_query\": {\n const projectDir = await this.requiredProjectDir(args);\n const query = typeof args.query === \"string\" ? args.query : undefined;\n return { content: [{ type: \"text\", text: JSON.stringify(await readProjectState(projectDir, query), null, 2) }] };\n }\n case \"gsd_progress\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readProgress(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_roadmap\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readRoadmap(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_history\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readHistory(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_doctor\":\n return { content: [{ type: \"text\", text: JSON.stringify(await runDoctorLite(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_captures\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readCaptures(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_knowledge\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readKnowledge(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_graph\":\n return { content: [{ type: \"text\", text: JSON.stringify(await this.executeGraph(args), null, 2) }] };\n default:\n throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n }\n }\n\n async advertisedProjects(): Promise<Array<{\n alias: string;\n path: string;\n repoIdentity: string;\n remoteLabel?: string;\n markers: string[];\n }>> {\n const projects = await this.scanProjects();\n return projects.map((project) => {\n const remoteLabel = gitRemote(project.path);\n return {\n alias: project.name,\n path: project.path,\n repoIdentity: identityFor(project.path, remoteLabel),\n ...(remoteLabel ? { remoteLabel } : {}),\n markers: project.markers,\n };\n });\n }\n\n private async requiredProjectDir(args: Record<string, unknown>): Promise<string> {\n const value = args.projectDir;\n if (typeof value === \"string\" && value.trim()) return this.resolveProjectPath(value);\n throw new Error(\"projectDir or projectAlias is required\");\n }\n\n private async resolveProjectPath(aliasOrPath: string): Promise<string> {\n const projects = await this.scanProjects();\n const match = projects.find((project) => project.name === aliasOrPath || project.path === aliasOrPath);\n if (!match) throw new Error(`Project is not advertised by the Local GSD Runtime: ${aliasOrPath}`);\n return match.path;\n }\n\n private executeWorkflowTool(toolName: string, args: Record<string, unknown>): Promise<unknown> | undefined {\n switch (toolName) {\n case \"gsd_decision_save\": return this.invokeRegisteredWorkflowTool(\"gsd_decision_save\", args);\n case \"gsd_save_decision\": return this.invokeRegisteredWorkflowTool(\"gsd_save_decision\", args);\n case \"gsd_requirement_update\": return this.invokeRegisteredWorkflowTool(\"gsd_requirement_update\", args);\n case \"gsd_update_requirement\": return this.invokeRegisteredWorkflowTool(\"gsd_update_requirement\", args);\n case \"gsd_requirement_save\": return this.invokeRegisteredWorkflowTool(\"gsd_requirement_save\", args);\n case \"gsd_save_requirement\": return this.invokeRegisteredWorkflowTool(\"gsd_save_requirement\", args);\n case \"gsd_milestone_generate_id\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_generate_id\", args);\n case \"gsd_generate_milestone_id\": return this.invokeRegisteredWorkflowTool(\"gsd_generate_milestone_id\", args);\n case \"gsd_plan_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_milestone\", args);\n case \"gsd_plan_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_slice\", args);\n case \"gsd_plan_task\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_task\", args);\n case \"gsd_task_plan\": return this.invokeRegisteredWorkflowTool(\"gsd_task_plan\", args);\n case \"gsd_replan_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_replan_slice\", args);\n case \"gsd_slice_replan\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_replan\", args);\n case \"gsd_slice_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_complete\", args);\n case \"gsd_complete_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_slice\", args);\n case \"gsd_skip_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_skip_slice\", args);\n case \"gsd_complete_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_milestone\", args);\n case \"gsd_milestone_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_complete\", args);\n case \"gsd_validate_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_validate_milestone\", args);\n case \"gsd_milestone_validate\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_validate\", args);\n case \"gsd_reassess_roadmap\": return this.invokeRegisteredWorkflowTool(\"gsd_reassess_roadmap\", args);\n case \"gsd_roadmap_reassess\": return this.invokeRegisteredWorkflowTool(\"gsd_roadmap_reassess\", args);\n case \"gsd_save_gate_result\": return this.invokeRegisteredWorkflowTool(\"gsd_save_gate_result\", args);\n case \"gsd_summary_save\": return this.invokeRegisteredWorkflowTool(\"gsd_summary_save\", args);\n case \"gsd_task_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_task_complete\", args);\n case \"gsd_complete_task\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_task\", args);\n case \"gsd_task_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_task_reopen\", args);\n case \"gsd_reopen_task\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_task\", args);\n case \"gsd_slice_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_reopen\", args);\n case \"gsd_reopen_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_slice\", args);\n case \"gsd_milestone_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_reopen\", args);\n case \"gsd_reopen_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_milestone\", args);\n case \"gsd_milestone_status\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_status\", args);\n case \"gsd_journal_query\": return this.invokeRegisteredWorkflowTool(\"gsd_journal_query\", args);\n case \"gsd_exec\": return this.invokeRegisteredWorkflowTool(\"gsd_exec\", args);\n case \"gsd_exec_search\": return this.invokeRegisteredWorkflowTool(\"gsd_exec_search\", args);\n case \"gsd_resume\": return this.invokeRegisteredWorkflowTool(\"gsd_resume\", args);\n case \"gsd_capture_thought\": return this.invokeRegisteredWorkflowTool(\"gsd_capture_thought\", args);\n case \"gsd_memory_query\": return this.invokeRegisteredWorkflowTool(\"gsd_memory_query\", args);\n case \"gsd_memory_graph\": return this.invokeRegisteredWorkflowTool(\"gsd_memory_graph\", args);\n default:\n if (WORKFLOW_TOOL_NAME_SET.has(toolName)) {\n throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n }\n return undefined;\n }\n }\n\n private invokeRegisteredWorkflowTool(toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const workflow = this.workflowHandlers.get(toolName);\n if (!workflow) throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n return workflow(args);\n }\n\n private async executeGraph(args: Record<string, unknown>): Promise<unknown> {\n const projectDir = await this.requiredProjectDir(args);\n const mode = args.mode;\n switch (mode) {\n case \"build\": {\n const gsdRoot = resolveGsdRoot(projectDir);\n if (args.snapshot === true) {\n await writeSnapshot(gsdRoot).catch(() => { /* best-effort */ });\n }\n const graph = await buildGraph(projectDir);\n await writeGraph(gsdRoot, graph);\n return {\n built: true,\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n builtAt: graph.builtAt,\n };\n }\n case \"query\":\n return graphQuery(\n projectDir,\n typeof args.term === \"string\" ? args.term : \"\",\n typeof args.budget === \"number\" ? args.budget : undefined,\n );\n case \"status\":\n return graphStatus(projectDir);\n case \"diff\":\n return graphDiff(projectDir);\n default:\n throw new Error(\"gsd_graph mode must be one of: build, query, status, diff\");\n }\n }\n}\n\nasync function readProjectState(projectDir: string, query: string | undefined): Promise<Record<string, unknown>> {\n const resolvedProjectDir = resolve(projectDir);\n const gsdDir = join(resolvedProjectDir, \".gsd\");\n const category = normalizeQuery(query);\n const wanted = new Set<ProjectStateField>(QUERY_FIELDS[category]);\n\n const result: Record<string, unknown> = {\n projectDir: resolvedProjectDir,\n query: category,\n };\n\n if (wanted.has(\"state\")) {\n result.state = await readTextOrNull(join(gsdDir, \"STATE.md\"));\n }\n if (wanted.has(\"project\")) {\n result.project = await readTextOrNull(join(gsdDir, \"PROJECT.md\"));\n }\n if (wanted.has(\"requirements\")) {\n result.requirements = await readTextOrNull(join(gsdDir, \"REQUIREMENTS.md\"));\n }\n if (wanted.has(\"milestones\")) {\n result.milestones = await readMilestones(gsdDir);\n }\n\n return result;\n}\n\nfunction normalizeQuery(query: string | undefined): QueryCategory {\n const key = (query ?? \"all\").trim().toLowerCase();\n return Object.hasOwn(QUERY_FIELDS, key) ? key as QueryCategory : \"all\";\n}\n\nasync function readTextOrNull(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function readMilestones(gsdDir: string): Promise<Array<{ id: string; hasRoadmap: boolean; hasSummary: boolean }>> {\n try {\n const entries = await readdir(join(gsdDir, \"milestones\"), { withFileTypes: true });\n const milestones: Array<{ id: string; hasRoadmap: boolean; hasSummary: boolean }> = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n milestones.push({\n id: entry.name,\n hasRoadmap: await milestoneFileExists(gsdDir, entry.name, \"ROADMAP\"),\n hasSummary: await milestoneFileExists(gsdDir, entry.name, \"SUMMARY\"),\n });\n }\n return milestones;\n } catch {\n return [];\n }\n}\n\nasync function milestoneFileExists(gsdDir: string, milestoneId: string, suffix: string): Promise<boolean> {\n const milestoneDir = join(gsdDir, \"milestones\", milestoneId);\n return fileExists(join(milestoneDir, `${milestoneId}-${suffix}.md`))\n || fileExists(join(milestoneDir, `${basename(milestoneDir)}-${suffix}.md`))\n || fileExists(join(milestoneDir, `${suffix}.md`));\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await readFile(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction gitRemote(projectPath: string): string | undefined {\n try {\n return execFileSync(\"git\", [\"remote\", \"get-url\", \"origin\"], {\n cwd: projectPath,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction identityFor(projectPath: string, remote?: string): string {\n return createHash(\"sha256\").update(remote || `${basename(projectPath)}:${projectPath}`).digest(\"hex\").slice(0, 12);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"local-tool-executor.js","sourceRoot":"","sources":["../src/local-tool-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,UAAU,EACV,aAAa,EACb,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAK7B,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAS,mBAAmB,CAAC,CAAC;AACpE,MAAM,YAAY,GAAG;IACnB,GAAG,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,CAAC;IACvD,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,OAAO,EAAE,CAAC,SAAS,CAAC;IACpB,YAAY,EAAE,CAAC,cAAc,CAAC;IAC9B,UAAU,EAAE,CAAC,YAAY,CAAC;CAClB,CAAC;AAKX,MAAM,OAAO,iBAAiB;IAIT;IACA;IAJF,gBAAgB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEnE,YACmB,cAA8B,EAC9B,YAA0C;QAD1C,mBAAc,GAAd,cAAc,CAAgB;QAC9B,iBAAY,GAAZ,YAAY,CAA8B;QAE3D,qBAAqB,CAAC;YACpB,IAAI,EAAE,CAAC,IAAY,EAAE,YAAoB,EAAE,OAAgC,EAAE,OAAoB,EAAE,EAAE;gBACnG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAC9C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,OAAgC,EAAE,YAAqB;QACrF,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;QAC5B,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChE,IAAI,cAAc;YAAE,OAAO,cAAc,CAAC;QAE1C,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACvD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC;oBACvD,UAAU;oBACV,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;oBACpE,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;oBAC9D,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;iBAC7D,CAAC,CAAC;gBACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1G,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC7E,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpD,MAAM,IAAI,GAAI,KAAiC,CAAC,IAAI,CAAC;oBACrD,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,sBAAsB,CAAC;gBAChE,CAAC,CAAC,CAAC,MAAM,CAAC;gBACV,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACtD,MAAM,EAAE,OAAO,CAAC,MAAM;gCACtB,QAAQ,EAAE;oCACR,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM;oCACjC,SAAS,EAAE,aAAa;iCACzB;gCACD,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gCACvC,cAAc,EAAE,OAAO,CAAC,cAAc;oCACpC,CAAC,CAAC;wCACE,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE;wCAC7B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,MAAM;wCACrC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO;qCACxC;oCACH,CAAC,CAAC,IAAI;gCACR,IAAI,EAAE,OAAO,CAAC,IAAI;gCAClB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS;6BAC3C,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACnB,CAAC;YACD,KAAK,YAAY;gBACf,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACrI,KAAK,YAAY;gBACf,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;oBAAE,MAAM,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;;oBAC3F,MAAM,IAAI,CAAC,cAAc,CAAC,kBAAkB,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7F,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;gBAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;gBAC7C,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBAC9D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5F,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACvD,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;gBACtE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACnH,CAAC;YACD,KAAK,cAAc;gBACjB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACjI,KAAK,aAAa;gBAChB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAChI,KAAK,aAAa;gBAChB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAChI,KAAK,YAAY;gBACf,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,aAAa,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAClI,KAAK,cAAc;gBACjB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACjI,KAAK,eAAe;gBAClB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,aAAa,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAClI,KAAK,WAAW;gBACd,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACvG;gBACE,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB;QAOtB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9B,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO;gBACL,KAAK,EAAE,OAAO,CAAC,IAAI;gBACnB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC;gBACpD,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvC,OAAO,EAAE,OAAO,CAAC,OAAO;aACzB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,IAA6B;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACrF,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,WAAmB;QAClD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QACvG,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,WAAW,EAAE,CAAC,CAAC;QAClG,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAEO,mBAAmB,CAAC,QAAgB,EAAE,IAA6B;QACzE,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,mBAAmB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;YAC9F,KAAK,mBAAmB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;YAC9F,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,2BAA2B,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;YAC9G,KAAK,2BAA2B,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;YAC9G,KAAK,oBAAoB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;YAChG,KAAK,gBAAgB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YACxF,KAAK,eAAe,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YACtF,KAAK,eAAe,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YACtF,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,iBAAiB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC1F,KAAK,uBAAuB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;YACtG,KAAK,oBAAoB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;YAChG,KAAK,oBAAoB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;YAChG,KAAK,gBAAgB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YACxF,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,wBAAwB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;YACxG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,mBAAmB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;YAC9F,KAAK,mBAAmB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;YAC9F,KAAK,iBAAiB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC1F,KAAK,iBAAiB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC1F,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,sBAAsB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACpG,KAAK,mBAAmB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;YAC9F,KAAK,UAAU,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC5E,KAAK,iBAAiB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC1F,KAAK,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAChF,KAAK,qBAAqB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;YAClG,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F,KAAK,kBAAkB,CAAC,CAAC,OAAO,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC5F;gBACE,IAAI,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACzC,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;gBACrE,CAAC;gBACD,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC;IAEO,4BAA4B,CAAC,QAAgB,EAAE,IAA6B;QAClF,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;QAClF,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAA6B;QACtD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;gBAC3C,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC3B,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC,CAAC;gBAClE,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;gBAC3C,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACjC,OAAO;oBACL,KAAK,EAAE,IAAI;oBACX,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;oBAC7B,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;oBAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;iBACvB,CAAC;YACJ,CAAC;YACD,KAAK,OAAO;gBACV,OAAO,UAAU,CACf,UAAU,EACV,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAC9C,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAC1D,CAAC;YACJ,KAAK,QAAQ;gBACX,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC;YACjC,KAAK,MAAM;gBACT,OAAO,SAAS,CAAC,UAAU,CAAC,CAAC;YAC/B;gBACE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;CACF;AAED,KAAK,UAAU,gBAAgB,CAAC,UAAkB,EAAE,KAAyB;IAC3E,MAAM,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAoB,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;IAElE,MAAM,MAAM,GAA4B;QACtC,UAAU,EAAE,kBAAkB;QAC9B,KAAK,EAAE,QAAQ;KAChB,CAAC;IAEF,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,YAAY,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,UAAU,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClD,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAoB,CAAC,CAAC,CAAC,KAAK,CAAC;AACzE,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAc;IAC1C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,MAAM,UAAU,GAAoE,EAAE,CAAC;QACvF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YACnC,UAAU,CAAC,IAAI,CAAC;gBACd,EAAE,EAAE,KAAK,CAAC,IAAI;gBACd,UAAU,EAAE,MAAM,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;gBACpE,UAAU,EAAE,MAAM,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;aACrE,CAAC,CAAC;QACL,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,WAAmB,EAAE,MAAc;IACpF,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAC7D,OAAO,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,WAAW,IAAI,MAAM,KAAK,CAAC,CAAC;WAC/D,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC;WACxE,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,WAAmB;IACpC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;YAC1D,GAAG,EAAE,WAAW;YAChB,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,WAAmB,EAAE,MAAe;IACvD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrH,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { execFileSync } from \"node:child_process\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { basename, join, resolve } from \"node:path\";\nimport {\n readCaptures,\n readHistory,\n readKnowledge,\n readProgress,\n readRoadmap,\n buildGraph,\n graphDiff,\n graphQuery,\n graphStatus,\n registerWorkflowTools,\n resolveGsdRoot,\n runDoctorLite,\n writeGraph,\n writeSnapshot,\n WORKFLOW_TOOL_NAMES,\n} from \"@opengsd/mcp-server\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { ProjectInfo } from \"./types.js\";\n\ntype ToolHandler = (args: Record<string, unknown>) => Promise<unknown>;\nconst WORKFLOW_TOOL_NAME_SET = new Set<string>(WORKFLOW_TOOL_NAMES);\nconst QUERY_FIELDS = {\n all: [\"state\", \"project\", \"requirements\", \"milestones\"],\n state: [\"state\"],\n status: [\"state\"],\n project: [\"project\"],\n requirements: [\"requirements\"],\n milestones: [\"milestones\"],\n} as const;\n\ntype QueryCategory = keyof typeof QUERY_FIELDS;\ntype ProjectStateField = (typeof QUERY_FIELDS)[QueryCategory][number];\n\nexport class LocalToolExecutor {\n private readonly workflowHandlers = new Map<string, ToolHandler>();\n\n constructor(\n private readonly sessionManager: SessionManager,\n private readonly scanProjects: () => Promise<ProjectInfo[]>,\n ) {\n registerWorkflowTools({\n tool: (name: string, _description: string, _params: Record<string, unknown>, handler: ToolHandler) => {\n if (!WORKFLOW_TOOL_NAME_SET.has(name)) return;\n this.workflowHandlers.set(name, handler);\n },\n });\n }\n\n async execute(toolName: string, rawArgs: Record<string, unknown>, projectAlias?: string): Promise<unknown> {\n const args = { ...rawArgs };\n if (projectAlias) {\n args.projectDir = await this.resolveProjectPath(projectAlias);\n }\n\n const workflowResult = this.executeWorkflowTool(toolName, args);\n if (workflowResult) return workflowResult;\n\n switch (toolName) {\n case \"gsd_execute\": {\n const projectDir = await this.requiredProjectDir(args);\n const sessionId = await this.sessionManager.startSession({\n projectDir,\n command: typeof args.command === \"string\" ? args.command : undefined,\n model: typeof args.model === \"string\" ? args.model : undefined,\n bare: typeof args.bare === \"boolean\" ? args.bare : undefined,\n });\n return { content: [{ type: \"text\", text: JSON.stringify({ sessionId, status: \"started\" }, null, 2) }] };\n }\n case \"gsd_status\": {\n const session = this.sessionManager.getSession(String(args.sessionId ?? \"\"));\n if (!session) throw new Error(`Session not found: ${String(args.sessionId ?? \"\")}`);\n const toolCallCount = session.events.filter((event) => {\n const type = (event as Record<string, unknown>).type;\n return type === \"tool_use\" || type === \"tool_execution_start\";\n }).length;\n return { content: [{ type: \"text\", text: JSON.stringify({\n status: session.status,\n progress: {\n eventCount: session.events.length,\n toolCalls: toolCallCount,\n },\n recentEvents: session.events.slice(-10),\n pendingBlocker: session.pendingBlocker\n ? {\n id: session.pendingBlocker.id,\n method: session.pendingBlocker.method,\n message: session.pendingBlocker.message,\n }\n : null,\n cost: session.cost,\n durationMs: Date.now() - session.startTime,\n }, null, 2) }] };\n }\n case \"gsd_result\":\n return { content: [{ type: \"text\", text: JSON.stringify(this.sessionManager.getResult(String(args.sessionId ?? \"\")), null, 2) }] };\n case \"gsd_cancel\":\n if (typeof args.sessionId === \"string\") await this.sessionManager.cancelSession(args.sessionId);\n else await this.sessionManager.cancelSessionByDir(await this.requiredProjectDir(args));\n return { content: [{ type: \"text\", text: JSON.stringify({ cancelled: true }, null, 2) }] };\n case \"gsd_resolve_blocker\": {\n const sessionId = String(args.sessionId ?? \"\");\n const response = String(args.response ?? \"\");\n await this.sessionManager.resolveBlocker(sessionId, response);\n return { content: [{ type: \"text\", text: JSON.stringify({ resolved: true }, null, 2) }] };\n }\n case \"gsd_query\": {\n const projectDir = await this.requiredProjectDir(args);\n const query = typeof args.query === \"string\" ? args.query : undefined;\n return { content: [{ type: \"text\", text: JSON.stringify(await readProjectState(projectDir, query), null, 2) }] };\n }\n case \"gsd_progress\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readProgress(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_roadmap\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readRoadmap(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_history\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readHistory(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_doctor\":\n return { content: [{ type: \"text\", text: JSON.stringify(await runDoctorLite(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_captures\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readCaptures(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_knowledge\":\n return { content: [{ type: \"text\", text: JSON.stringify(await readKnowledge(await this.requiredProjectDir(args)), null, 2) }] };\n case \"gsd_graph\":\n return { content: [{ type: \"text\", text: JSON.stringify(await this.executeGraph(args), null, 2) }] };\n default:\n throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n }\n }\n\n async advertisedProjects(): Promise<Array<{\n alias: string;\n path: string;\n repoIdentity: string;\n remoteLabel?: string;\n markers: string[];\n }>> {\n const projects = await this.scanProjects();\n return projects.map((project) => {\n const remoteLabel = gitRemote(project.path);\n return {\n alias: project.name,\n path: project.path,\n repoIdentity: identityFor(project.path, remoteLabel),\n ...(remoteLabel ? { remoteLabel } : {}),\n markers: project.markers,\n };\n });\n }\n\n private async requiredProjectDir(args: Record<string, unknown>): Promise<string> {\n const value = args.projectDir;\n if (typeof value === \"string\" && value.trim()) return this.resolveProjectPath(value);\n throw new Error(\"projectDir or projectAlias is required\");\n }\n\n private async resolveProjectPath(aliasOrPath: string): Promise<string> {\n const projects = await this.scanProjects();\n const match = projects.find((project) => project.name === aliasOrPath || project.path === aliasOrPath);\n if (!match) throw new Error(`Project is not advertised by the Local GSD Runtime: ${aliasOrPath}`);\n return match.path;\n }\n\n private executeWorkflowTool(toolName: string, args: Record<string, unknown>): Promise<unknown> | undefined {\n switch (toolName) {\n case \"gsd_decision_save\": return this.invokeRegisteredWorkflowTool(\"gsd_decision_save\", args);\n case \"gsd_save_decision\": return this.invokeRegisteredWorkflowTool(\"gsd_save_decision\", args);\n case \"gsd_requirement_update\": return this.invokeRegisteredWorkflowTool(\"gsd_requirement_update\", args);\n case \"gsd_update_requirement\": return this.invokeRegisteredWorkflowTool(\"gsd_update_requirement\", args);\n case \"gsd_requirement_save\": return this.invokeRegisteredWorkflowTool(\"gsd_requirement_save\", args);\n case \"gsd_save_requirement\": return this.invokeRegisteredWorkflowTool(\"gsd_save_requirement\", args);\n case \"gsd_milestone_generate_id\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_generate_id\", args);\n case \"gsd_generate_milestone_id\": return this.invokeRegisteredWorkflowTool(\"gsd_generate_milestone_id\", args);\n case \"gsd_plan_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_milestone\", args);\n case \"gsd_plan_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_slice\", args);\n case \"gsd_plan_task\": return this.invokeRegisteredWorkflowTool(\"gsd_plan_task\", args);\n case \"gsd_task_plan\": return this.invokeRegisteredWorkflowTool(\"gsd_task_plan\", args);\n case \"gsd_replan_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_replan_slice\", args);\n case \"gsd_slice_replan\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_replan\", args);\n case \"gsd_replan_task\": return this.invokeRegisteredWorkflowTool(\"gsd_replan_task\", args);\n case \"gsd_rework_brief_save\": return this.invokeRegisteredWorkflowTool(\"gsd_rework_brief_save\", args);\n case \"gsd_slice_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_complete\", args);\n case \"gsd_complete_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_slice\", args);\n case \"gsd_skip_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_skip_slice\", args);\n case \"gsd_complete_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_milestone\", args);\n case \"gsd_milestone_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_complete\", args);\n case \"gsd_validate_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_validate_milestone\", args);\n case \"gsd_milestone_validate\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_validate\", args);\n case \"gsd_reassess_roadmap\": return this.invokeRegisteredWorkflowTool(\"gsd_reassess_roadmap\", args);\n case \"gsd_roadmap_reassess\": return this.invokeRegisteredWorkflowTool(\"gsd_roadmap_reassess\", args);\n case \"gsd_save_gate_result\": return this.invokeRegisteredWorkflowTool(\"gsd_save_gate_result\", args);\n case \"gsd_summary_save\": return this.invokeRegisteredWorkflowTool(\"gsd_summary_save\", args);\n case \"gsd_task_complete\": return this.invokeRegisteredWorkflowTool(\"gsd_task_complete\", args);\n case \"gsd_complete_task\": return this.invokeRegisteredWorkflowTool(\"gsd_complete_task\", args);\n case \"gsd_task_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_task_reopen\", args);\n case \"gsd_reopen_task\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_task\", args);\n case \"gsd_slice_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_slice_reopen\", args);\n case \"gsd_reopen_slice\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_slice\", args);\n case \"gsd_milestone_reopen\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_reopen\", args);\n case \"gsd_reopen_milestone\": return this.invokeRegisteredWorkflowTool(\"gsd_reopen_milestone\", args);\n case \"gsd_milestone_status\": return this.invokeRegisteredWorkflowTool(\"gsd_milestone_status\", args);\n case \"gsd_journal_query\": return this.invokeRegisteredWorkflowTool(\"gsd_journal_query\", args);\n case \"gsd_exec\": return this.invokeRegisteredWorkflowTool(\"gsd_exec\", args);\n case \"gsd_exec_search\": return this.invokeRegisteredWorkflowTool(\"gsd_exec_search\", args);\n case \"gsd_resume\": return this.invokeRegisteredWorkflowTool(\"gsd_resume\", args);\n case \"gsd_capture_thought\": return this.invokeRegisteredWorkflowTool(\"gsd_capture_thought\", args);\n case \"gsd_memory_query\": return this.invokeRegisteredWorkflowTool(\"gsd_memory_query\", args);\n case \"gsd_memory_graph\": return this.invokeRegisteredWorkflowTool(\"gsd_memory_graph\", args);\n default:\n if (WORKFLOW_TOOL_NAME_SET.has(toolName)) {\n throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n }\n return undefined;\n }\n }\n\n private invokeRegisteredWorkflowTool(toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const workflow = this.workflowHandlers.get(toolName);\n if (!workflow) throw new Error(`Unsupported forwarded GSD MCP tool: ${toolName}`);\n return workflow(args);\n }\n\n private async executeGraph(args: Record<string, unknown>): Promise<unknown> {\n const projectDir = await this.requiredProjectDir(args);\n const mode = args.mode;\n switch (mode) {\n case \"build\": {\n const gsdRoot = resolveGsdRoot(projectDir);\n if (args.snapshot === true) {\n await writeSnapshot(gsdRoot).catch(() => { /* best-effort */ });\n }\n const graph = await buildGraph(projectDir);\n await writeGraph(gsdRoot, graph);\n return {\n built: true,\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n builtAt: graph.builtAt,\n };\n }\n case \"query\":\n return graphQuery(\n projectDir,\n typeof args.term === \"string\" ? args.term : \"\",\n typeof args.budget === \"number\" ? args.budget : undefined,\n );\n case \"status\":\n return graphStatus(projectDir);\n case \"diff\":\n return graphDiff(projectDir);\n default:\n throw new Error(\"gsd_graph mode must be one of: build, query, status, diff\");\n }\n }\n}\n\nasync function readProjectState(projectDir: string, query: string | undefined): Promise<Record<string, unknown>> {\n const resolvedProjectDir = resolve(projectDir);\n const gsdDir = join(resolvedProjectDir, \".gsd\");\n const category = normalizeQuery(query);\n const wanted = new Set<ProjectStateField>(QUERY_FIELDS[category]);\n\n const result: Record<string, unknown> = {\n projectDir: resolvedProjectDir,\n query: category,\n };\n\n if (wanted.has(\"state\")) {\n result.state = await readTextOrNull(join(gsdDir, \"STATE.md\"));\n }\n if (wanted.has(\"project\")) {\n result.project = await readTextOrNull(join(gsdDir, \"PROJECT.md\"));\n }\n if (wanted.has(\"requirements\")) {\n result.requirements = await readTextOrNull(join(gsdDir, \"REQUIREMENTS.md\"));\n }\n if (wanted.has(\"milestones\")) {\n result.milestones = await readMilestones(gsdDir);\n }\n\n return result;\n}\n\nfunction normalizeQuery(query: string | undefined): QueryCategory {\n const key = (query ?? \"all\").trim().toLowerCase();\n return Object.hasOwn(QUERY_FIELDS, key) ? key as QueryCategory : \"all\";\n}\n\nasync function readTextOrNull(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function readMilestones(gsdDir: string): Promise<Array<{ id: string; hasRoadmap: boolean; hasSummary: boolean }>> {\n try {\n const entries = await readdir(join(gsdDir, \"milestones\"), { withFileTypes: true });\n const milestones: Array<{ id: string; hasRoadmap: boolean; hasSummary: boolean }> = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n milestones.push({\n id: entry.name,\n hasRoadmap: await milestoneFileExists(gsdDir, entry.name, \"ROADMAP\"),\n hasSummary: await milestoneFileExists(gsdDir, entry.name, \"SUMMARY\"),\n });\n }\n return milestones;\n } catch {\n return [];\n }\n}\n\nasync function milestoneFileExists(gsdDir: string, milestoneId: string, suffix: string): Promise<boolean> {\n const milestoneDir = join(gsdDir, \"milestones\", milestoneId);\n return fileExists(join(milestoneDir, `${milestoneId}-${suffix}.md`))\n || fileExists(join(milestoneDir, `${basename(milestoneDir)}-${suffix}.md`))\n || fileExists(join(milestoneDir, `${suffix}.md`));\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await readFile(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction gitRemote(projectPath: string): string | undefined {\n try {\n return execFileSync(\"git\", [\"remote\", \"get-url\", \"origin\"], {\n cwd: projectPath,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction identityFor(projectPath: string, remote?: string): string {\n return createHash(\"sha256\").update(remote || `${basename(projectPath)}:${projectPath}`).digest(\"hex\").slice(0, 12);\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/daemon",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1-dev.897b3c90",
|
|
4
4
|
"description": "GSD daemon — background process for project monitoring and Discord integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build": "node ../../scripts/clean-package-dist.cjs && tsc",
|
|
30
|
-
"test": "node --test dist/daemon.test.js dist/cloud-config.test.js dist/cloud-runtime.test.js dist/device-flow.test.js dist/local-tool-executor.test.js dist/mcp-cli.test.js dist/message-batcher.test.js"
|
|
30
|
+
"test": "pnpm run build && node --test dist/daemon.test.js dist/cloud-config.test.js dist/cloud-runtime.test.js dist/device-flow.test.js dist/local-tool-executor.test.js dist/mcp-cli.test.js dist/message-batcher.test.js"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@anthropic-ai/sdk": "^0.
|
|
34
|
-
"@opengsd/contracts": "^1.
|
|
35
|
-
"@opengsd/mcp-server": "^1.
|
|
36
|
-
"@opengsd/rpc-client": "^1.
|
|
33
|
+
"@anthropic-ai/sdk": "^0.91.1",
|
|
34
|
+
"@opengsd/contracts": "^1.8.1-dev.897b3c90",
|
|
35
|
+
"@opengsd/mcp-server": "^1.8.1-dev.897b3c90",
|
|
36
|
+
"@opengsd/rpc-client": "^1.8.1-dev.897b3c90",
|
|
37
37
|
"discord.js": "^14.25.1",
|
|
38
38
|
"ws": "^8.20.0",
|
|
39
39
|
"yaml": "^2.8.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/agent-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1-dev.897b3c90",
|
|
4
4
|
"description": "GSD session orchestration layer on top of @gsd/pi-coding-agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"test": "node --import ../../src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/*.test.ts src/**/*.test.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@gsd/native": "^1.
|
|
29
|
-
"@gsd/pi-agent-core": "^1.
|
|
30
|
-
"@gsd/pi-ai": "^1.
|
|
31
|
-
"@gsd/pi-coding-agent": "^1.
|
|
28
|
+
"@gsd/native": "^1.8.1-dev.897b3c90",
|
|
29
|
+
"@gsd/pi-agent-core": "^1.8.1-dev.897b3c90",
|
|
30
|
+
"@gsd/pi-ai": "^1.8.1-dev.897b3c90",
|
|
31
|
+
"@gsd/pi-coding-agent": "^1.8.1-dev.897b3c90"
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/agent-modes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1-dev.897b3c90",
|
|
4
4
|
"description": "GSD run modes and CLI layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"test": "node --import ../../src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/**/*.test.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@gsd/agent-core": "^1.
|
|
29
|
-
"@gsd/pi-agent-core": "^1.
|
|
30
|
-
"@gsd/pi-ai": "^1.
|
|
31
|
-
"@gsd/pi-coding-agent": "^1.
|
|
32
|
-
"@gsd/pi-tui": "^1.
|
|
33
|
-
"@opengsd/contracts": "^1.
|
|
28
|
+
"@gsd/agent-core": "^1.8.1-dev.897b3c90",
|
|
29
|
+
"@gsd/pi-agent-core": "^1.8.1-dev.897b3c90",
|
|
30
|
+
"@gsd/pi-ai": "^1.8.1-dev.897b3c90",
|
|
31
|
+
"@gsd/pi-coding-agent": "^1.8.1-dev.897b3c90",
|
|
32
|
+
"@gsd/pi-tui": "^1.8.1-dev.897b3c90",
|
|
33
|
+
"@opengsd/contracts": "^1.8.1-dev.897b3c90",
|
|
34
34
|
"chalk": "^5.5.0"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
Connect a local GSD runtime to [GSD Cloud](https://cloud.opengsd.net) so you can
|
|
4
4
|
monitor and control your GSD projects from any browser.
|
|
5
5
|
|
|
6
|
-
This is a
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
This is a **self-contained** agent. It depends only on `ws` and `yaml` — no
|
|
7
|
+
`@opengsd/daemon`, no `@opengsd/mcp-server`, no `@opengsd/gsd-pi`. It runs the
|
|
8
|
+
RFC 8628 device-flow login, opens a persistent WebSocket to the cloud gateway,
|
|
9
|
+
and forwards each requested GSD workflow tool to your locally-installed `gsd`
|
|
10
|
+
CLI (via `gsd --mode mcp`). The gateway default of `https://cloud.opengsd.net`
|
|
11
|
+
is injected for `login`/`pair` so you never have to type `--gateway`.
|
|
12
|
+
|
|
13
|
+
Requires the `gsd` CLI (from `@opengsd/gsd-pi`) to be installed and on your
|
|
14
|
+
`PATH` (or set `GSD_CLI_PATH`).
|
|
10
15
|
|
|
11
16
|
## Usage
|
|
12
17
|
|
|
@@ -29,6 +34,15 @@ npx @opengsd/gsd-cloud disconnect
|
|
|
29
34
|
different gateway, pass `--gateway <url>` explicitly — the explicit flag always
|
|
30
35
|
wins. The `status`, `connect`, and `disconnect` commands do not use a gateway.
|
|
31
36
|
|
|
37
|
+
## Environment
|
|
38
|
+
|
|
39
|
+
- `GSD_CLOUD_PROJECTS` — path-delimiter separated list of project directories to
|
|
40
|
+
advertise to the cloud (default: the current working directory).
|
|
41
|
+
- `GSD_CLI_PATH` — path to the `gsd` binary (default: `gsd` on `PATH`).
|
|
42
|
+
- `GSD_CLOUD_EXECUTOR` — backend adapter: `gsd-pi` (default). `codex` and
|
|
43
|
+
`claude` adapters are stubbed for future use.
|
|
44
|
+
|
|
32
45
|
## Requirements
|
|
33
46
|
|
|
34
47
|
- Node.js >= 22
|
|
48
|
+
- The `gsd` CLI (`@opengsd/gsd-pi`) installed locally
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Project/App: Open GSD
|
|
3
|
-
// File Purpose: gsd-cloud CLI entry — inject the default gateway then
|
|
3
|
+
// File Purpose: gsd-cloud CLI entry — inject the default gateway, then run the
|
|
4
|
+
// standalone cloud command handler. No @opengsd/daemon dependency.
|
|
4
5
|
import { existsSync } from 'node:fs';
|
|
5
6
|
import { dirname, join } from 'node:path';
|
|
6
7
|
import { fileURLToPath } from 'node:url';
|
|
7
8
|
|
|
8
9
|
const binDir = dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const
|
|
10
|
+
const distDir = join(binDir, '..', 'dist');
|
|
10
11
|
|
|
11
|
-
if (!existsSync(
|
|
12
|
+
if (!existsSync(join(distDir, 'cli.js'))) {
|
|
12
13
|
process.stderr.write('gsd-cloud: build output missing. Run `pnpm --filter @opengsd/gsd-cloud run build`.\n');
|
|
13
14
|
process.exit(1);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const { injectDefaultGateway } = await import('../dist/inject-gateway.js');
|
|
17
|
-
const {
|
|
18
|
+
const { handleCloudCommand } = await import('../dist/cli.js');
|
|
18
19
|
|
|
19
20
|
const argv = injectDefaultGateway(process.argv.slice(2));
|
|
20
21
|
|
|
21
22
|
try {
|
|
22
|
-
await
|
|
23
|
+
await handleCloudCommand(argv, { binaryName: 'gsd-cloud' });
|
|
23
24
|
} catch (err) {
|
|
24
25
|
const msg = err instanceof Error ? err.message : String(err);
|
|
25
26
|
process.stderr.write(`gsd-cloud: fatal: ${msg}\n`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAqBA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE;IAC7D,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FhB;AAkCD,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA8BtD"}
|