gsd-pi 2.50.0-dev.d210a87 → 2.51.0-dev.7d435fe
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 +4 -4
- package/dist/headless-events.d.ts +18 -0
- package/dist/headless-events.js +36 -0
- package/dist/headless-types.d.ts +28 -0
- package/dist/headless-types.js +7 -0
- package/dist/headless.d.ts +8 -3
- package/dist/headless.js +47 -16
- package/dist/help-text.js +16 -5
- package/dist/onboarding.js +5 -4
- package/dist/remote-questions-config.js +1 -1
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +29 -17
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +18 -19
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -0
- package/dist/resources/extensions/gsd/auto-start.js +2 -0
- package/dist/resources/extensions/gsd/auto-timers.js +24 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +25 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +21 -0
- package/dist/resources/extensions/gsd/auto.js +4 -2
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +95 -69
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +12 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +1 -1
- package/dist/resources/extensions/gsd/claude-import.js +60 -9
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +69 -6
- package/dist/resources/extensions/gsd/commands-config.js +10 -5
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/detection.js +6 -6
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/dist/resources/extensions/gsd/error-classifier.js +105 -0
- package/dist/resources/extensions/gsd/gitignore.js +7 -7
- package/dist/resources/extensions/gsd/gsd-db.js +298 -45
- package/dist/resources/extensions/gsd/init-wizard.js +2 -2
- package/dist/resources/extensions/gsd/key-manager.js +7 -16
- package/dist/resources/extensions/gsd/memory-store.js +28 -13
- package/dist/resources/extensions/gsd/milestone-actions.js +19 -0
- package/dist/resources/extensions/gsd/preferences-models.js +1 -13
- package/dist/resources/extensions/gsd/preferences.js +13 -13
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-error-pause.js +0 -44
- package/dist/resources/extensions/gsd/rule-registry.js +1 -1
- package/dist/resources/extensions/gsd/service-tier.js +13 -2
- package/dist/resources/extensions/gsd/state.js +21 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -10
- package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -17
- package/dist/resources/extensions/gsd/tools/complete-task.js +7 -18
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +26 -17
- package/dist/resources/extensions/gsd/tools/plan-slice.js +25 -14
- package/dist/resources/extensions/gsd/tools/plan-task.js +21 -11
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +47 -37
- package/dist/resources/extensions/gsd/tools/replan-slice.js +49 -38
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +23 -16
- package/dist/resources/extensions/gsd/workflow-logger.js +0 -1
- package/dist/resources/extensions/remote-questions/config.js +1 -1
- package/dist/resources/extensions/remote-questions/remote-command.js +1 -1
- package/dist/resources/extensions/search-the-web/native-search.js +1 -1
- package/dist/resources/extensions/search-the-web/provider.js +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +21 -21
- 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/react-loadable-manifest.json +1 -1
- 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 +2 -2
- 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_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 +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +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 +21 -21
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.21054f459af5cc78.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-cfc9a116e6450a6b.js → webpack-024d82be84800e52.js} +1 -1
- package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +1 -0
- package/dist/wizard.js +4 -1
- package/package.json +2 -2
- package/packages/pi-ai/dist/models.d.ts +14 -3
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.js +53 -10
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +102 -1
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +30 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/models.test.ts +114 -1
- package/packages/pi-ai/src/models.ts +70 -13
- package/packages/pi-ai/src/types.ts +31 -0
- package/packages/pi-coding-agent/dist/cli/args.d.ts +2 -0
- package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/cli/args.js +3 -0
- package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.js +5 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +9 -4
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +83 -0
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +5 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +5 -3
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +0 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +28 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +49 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +114 -6
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.js +831 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-protocol-v2.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +66 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +0 -1
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/cli/args.ts +4 -0
- package/packages/pi-coding-agent/src/core/bash-executor.ts +5 -1
- package/packages/pi-coding-agent/src/core/model-registry.ts +10 -3
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +101 -0
- package/packages/pi-coding-agent/src/core/tools/bash.ts +5 -1
- package/packages/pi-coding-agent/src/index.ts +3 -0
- package/packages/pi-coding-agent/src/main.ts +5 -3
- package/packages/pi-coding-agent/src/modes/index.ts +8 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +0 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +54 -1
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +124 -6
- package/packages/pi-coding-agent/src/modes/rpc/rpc-protocol-v2.test.ts +971 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +61 -4
- package/packages/pi-coding-agent/src/utils/shell.ts +0 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +22 -11
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +19 -20
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +21 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +19 -0
- package/src/resources/extensions/gsd/auto-start.ts +2 -0
- package/src/resources/extensions/gsd/auto-timers.ts +25 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +30 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -0
- package/src/resources/extensions/gsd/auto.ts +5 -2
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +115 -72
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +11 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +1 -1
- package/src/resources/extensions/gsd/claude-import.ts +58 -9
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +73 -6
- package/src/resources/extensions/gsd/commands-config.ts +11 -5
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/detection.ts +6 -6
- package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/src/resources/extensions/gsd/error-classifier.ts +139 -0
- package/src/resources/extensions/gsd/gitignore.ts +7 -7
- package/src/resources/extensions/gsd/gsd-db.ts +355 -63
- package/src/resources/extensions/gsd/init-wizard.ts +2 -2
- package/src/resources/extensions/gsd/key-manager.ts +7 -16
- package/src/resources/extensions/gsd/memory-store.ts +29 -18
- package/src/resources/extensions/gsd/milestone-actions.ts +17 -0
- package/src/resources/extensions/gsd/preferences-models.ts +1 -13
- package/src/resources/extensions/gsd/preferences.ts +12 -13
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-error-pause.ts +0 -57
- package/src/resources/extensions/gsd/rule-registry.ts +1 -1
- package/src/resources/extensions/gsd/service-tier.ts +14 -2
- package/src/resources/extensions/gsd/state.ts +22 -2
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/claude-import-marketplace-discovery.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +35 -7
- package/src/resources/extensions/gsd/tests/detection.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +77 -70
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +42 -31
- package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/vacuous-truth-slices.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +81 -1
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +130 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -14
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -21
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -22
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +28 -18
- package/src/resources/extensions/gsd/tools/plan-slice.ts +28 -16
- package/src/resources/extensions/gsd/tools/plan-task.ts +24 -12
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +54 -42
- package/src/resources/extensions/gsd/tools/replan-slice.ts +53 -40
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +26 -20
- package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
- package/src/resources/extensions/remote-questions/config.ts +1 -1
- package/src/resources/extensions/remote-questions/remote-command.ts +1 -1
- package/src/resources/extensions/search-the-web/native-search.ts +1 -1
- package/src/resources/extensions/search-the-web/provider.ts +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.9ad5def014d90ce4.js +0 -9
- package/dist/web/standalone/.next/static/css/de141508b083f922.css +0 -1
- /package/dist/resources/extensions/gsd/templates/{preferences.md → PREFERENCES.md} +0 -0
- /package/dist/web/standalone/.next/static/{yJIyd5cXPNpmXTv18ZlyC → RqOU-jOv9uZ1Q03P6L6nn}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{yJIyd5cXPNpmXTv18ZlyC → RqOU-jOv9uZ1Q03P6L6nn}/_ssgManifest.js +0 -0
- /package/src/resources/extensions/gsd/templates/{preferences.md → PREFERENCES.md} +0 -0
|
@@ -4,6 +4,7 @@ import { enableDebug } from "../../debug-logger.js";
|
|
|
4
4
|
import { isAutoActive, isAutoPaused, pauseAuto, startAuto, stopAuto, stopAutoRemote } from "../../auto.js";
|
|
5
5
|
import { handleRate } from "../../commands-rate.js";
|
|
6
6
|
import { guardRemoteSession, projectRoot } from "../context.js";
|
|
7
|
+
import { findMilestoneIds } from "../../milestone-id-utils.js";
|
|
7
8
|
/**
|
|
8
9
|
* Parse --yolo flag and optional file path from the auto command string.
|
|
9
10
|
* Supports: `/gsd auto --yolo path/to/file.md` or `/gsd auto -y path/to/file.md`
|
|
@@ -22,6 +23,40 @@ function parseYoloFlag(trimmed) {
|
|
|
22
23
|
const rest = trimmed.replace(match[0], "").replace(/\s+/g, " ").trim();
|
|
23
24
|
return { yoloSeedFile: filePath, rest };
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract a milestone ID (e.g. M016 or M001-a3b4c5) from the command string.
|
|
28
|
+
* Returns the matched ID and the remaining string with the ID removed.
|
|
29
|
+
* The milestone ID pattern matches the format used by findMilestoneIds: M\d+ with
|
|
30
|
+
* an optional -[a-z0-9]{6} suffix for unique milestone IDs.
|
|
31
|
+
*/
|
|
32
|
+
export function parseMilestoneTarget(input) {
|
|
33
|
+
const match = input.match(/\b(M\d+(?:-[a-z0-9]{6})?)\b/);
|
|
34
|
+
if (!match)
|
|
35
|
+
return { milestoneId: null, rest: input };
|
|
36
|
+
const rest = input.replace(match[0], "").replace(/\s+/g, " ").trim();
|
|
37
|
+
return { milestoneId: match[1], rest };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Set GSD_MILESTONE_LOCK to target a specific milestone, then run `fn`.
|
|
41
|
+
* Clears the env var when `fn` resolves or rejects, so the lock does not
|
|
42
|
+
* leak into subsequent commands in the same process.
|
|
43
|
+
*/
|
|
44
|
+
async function withMilestoneLock(milestoneId, fn) {
|
|
45
|
+
const previous = process.env.GSD_MILESTONE_LOCK;
|
|
46
|
+
process.env.GSD_MILESTONE_LOCK = milestoneId;
|
|
47
|
+
try {
|
|
48
|
+
await fn();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
// Restore previous value (undefined → delete, else restore).
|
|
52
|
+
if (previous === undefined) {
|
|
53
|
+
delete process.env.GSD_MILESTONE_LOCK;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
process.env.GSD_MILESTONE_LOCK = previous;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
25
60
|
export async function handleAutoCommand(trimmed, ctx, pi) {
|
|
26
61
|
if (trimmed === "next" || trimmed.startsWith("next ")) {
|
|
27
62
|
if (trimmed.includes("--dry-run")) {
|
|
@@ -29,23 +64,46 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
|
|
|
29
64
|
await handleDryRun(ctx, projectRoot());
|
|
30
65
|
return true;
|
|
31
66
|
}
|
|
32
|
-
const
|
|
33
|
-
const
|
|
67
|
+
const { milestoneId, rest: afterMilestone } = parseMilestoneTarget(trimmed);
|
|
68
|
+
const verboseMode = afterMilestone.includes("--verbose");
|
|
69
|
+
const debugMode = afterMilestone.includes("--debug");
|
|
34
70
|
if (debugMode)
|
|
35
71
|
enableDebug(projectRoot());
|
|
36
72
|
if (!(await guardRemoteSession(ctx, pi)))
|
|
37
73
|
return true;
|
|
38
|
-
|
|
74
|
+
// Validate the milestone target exists and is not already complete.
|
|
75
|
+
if (milestoneId) {
|
|
76
|
+
const allIds = findMilestoneIds(projectRoot());
|
|
77
|
+
if (!allIds.includes(milestoneId)) {
|
|
78
|
+
ctx.ui.notify(`Milestone ${milestoneId} does not exist. Available: ${allIds.join(", ") || "(none)"}`, "error");
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (milestoneId) {
|
|
83
|
+
await withMilestoneLock(milestoneId, () => startAuto(ctx, pi, projectRoot(), verboseMode, { step: true }));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
await startAuto(ctx, pi, projectRoot(), verboseMode, { step: true });
|
|
87
|
+
}
|
|
39
88
|
return true;
|
|
40
89
|
}
|
|
41
90
|
if (trimmed === "auto" || trimmed.startsWith("auto ")) {
|
|
42
|
-
const { yoloSeedFile, rest } = parseYoloFlag(trimmed);
|
|
43
|
-
const
|
|
44
|
-
const
|
|
91
|
+
const { yoloSeedFile, rest: afterYolo } = parseYoloFlag(trimmed);
|
|
92
|
+
const { milestoneId, rest: afterMilestone } = parseMilestoneTarget(afterYolo);
|
|
93
|
+
const verboseMode = afterMilestone.includes("--verbose");
|
|
94
|
+
const debugMode = afterMilestone.includes("--debug");
|
|
45
95
|
if (debugMode)
|
|
46
96
|
enableDebug(projectRoot());
|
|
47
97
|
if (!(await guardRemoteSession(ctx, pi)))
|
|
48
98
|
return true;
|
|
99
|
+
// Validate the milestone target exists and is not already complete.
|
|
100
|
+
if (milestoneId) {
|
|
101
|
+
const allIds = findMilestoneIds(projectRoot());
|
|
102
|
+
if (!allIds.includes(milestoneId)) {
|
|
103
|
+
ctx.ui.notify(`Milestone ${milestoneId} does not exist. Available: ${allIds.join(", ") || "(none)"}`, "error");
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
49
107
|
if (yoloSeedFile) {
|
|
50
108
|
const resolved = resolve(projectRoot(), yoloSeedFile);
|
|
51
109
|
if (!existsSync(resolved)) {
|
|
@@ -63,6 +121,11 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
|
|
|
63
121
|
const { showHeadlessMilestoneCreation } = await import("../../guided-flow.js");
|
|
64
122
|
await showHeadlessMilestoneCreation(ctx, pi, projectRoot(), seedContent);
|
|
65
123
|
}
|
|
124
|
+
else if (milestoneId) {
|
|
125
|
+
// Target a specific milestone — use GSD_MILESTONE_LOCK so state
|
|
126
|
+
// derivation only sees this milestone (#2521).
|
|
127
|
+
await withMilestoneLock(milestoneId, () => startAuto(ctx, pi, projectRoot(), verboseMode));
|
|
128
|
+
}
|
|
66
129
|
else {
|
|
67
130
|
await startAuto(ctx, pi, projectRoot(), verboseMode);
|
|
68
131
|
}
|
|
@@ -18,6 +18,11 @@ export const TOOL_KEYS = [
|
|
|
18
18
|
{ id: "jina", env: "JINA_API_KEY", label: "Jina Page Extract", hint: "jina.ai/api" },
|
|
19
19
|
{ id: "groq", env: "GROQ_API_KEY", label: "Groq Voice", hint: "console.groq.com" },
|
|
20
20
|
];
|
|
21
|
+
function getStoredToolKey(auth, providerId) {
|
|
22
|
+
const creds = auth.getCredentialsForProvider(providerId);
|
|
23
|
+
const cred = creds.find((c) => c.type === "api_key" && c.key);
|
|
24
|
+
return cred?.type === "api_key" ? cred.key : undefined;
|
|
25
|
+
}
|
|
21
26
|
/**
|
|
22
27
|
* Load tool API keys from auth.json into environment variables.
|
|
23
28
|
* Called at session startup to ensure tools have access to their credentials.
|
|
@@ -29,9 +34,9 @@ export function loadToolApiKeys() {
|
|
|
29
34
|
return;
|
|
30
35
|
const auth = AuthStorage.create(authPath);
|
|
31
36
|
for (const tool of TOOL_KEYS) {
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
process.env[tool.env] =
|
|
37
|
+
const key = getStoredToolKey(auth, tool.id);
|
|
38
|
+
if (key && !process.env[tool.env]) {
|
|
39
|
+
process.env[tool.env] = key;
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
}
|
|
@@ -49,13 +54,13 @@ export async function handleConfig(ctx) {
|
|
|
49
54
|
// Show current status
|
|
50
55
|
const statusLines = ["GSD Tool Configuration\n"];
|
|
51
56
|
for (const tool of TOOL_KEYS) {
|
|
52
|
-
const hasKey = !!process.env[tool.env] || !!auth
|
|
57
|
+
const hasKey = !!process.env[tool.env] || !!getStoredToolKey(auth, tool.id);
|
|
53
58
|
statusLines.push(` ${hasKey ? "\u2713" : "\u2717"} ${tool.label}${hasKey ? "" : ` \u2014 get key at ${tool.hint}`}`);
|
|
54
59
|
}
|
|
55
60
|
ctx.ui.notify(statusLines.join("\n"), "info");
|
|
56
61
|
// Ask which tools to configure
|
|
57
62
|
const options = TOOL_KEYS.map(t => {
|
|
58
|
-
const hasKey = !!process.env[t.env] || !!auth
|
|
63
|
+
const hasKey = !!process.env[t.env] || !!getStoredToolKey(auth, t.id);
|
|
59
64
|
return `${t.label} ${hasKey ? "(configured \u2713)" : "(not set)"}`;
|
|
60
65
|
});
|
|
61
66
|
options.push("(done)");
|
|
@@ -650,7 +650,7 @@ export function serializePreferencesToFrontmatter(prefs) {
|
|
|
650
650
|
}
|
|
651
651
|
export async function ensurePreferencesFile(path, ctx, scope) {
|
|
652
652
|
if (!existsSync(path)) {
|
|
653
|
-
const template = await loadFile(join(dirname(fileURLToPath(import.meta.url)), "templates", "
|
|
653
|
+
const template = await loadFile(join(dirname(fileURLToPath(import.meta.url)), "templates", "PREFERENCES.md"));
|
|
654
654
|
if (!template) {
|
|
655
655
|
ctx.ui.notify("Could not load GSD preferences template.", "error");
|
|
656
656
|
return;
|
|
@@ -277,8 +277,8 @@ function detectV2Gsd(basePath) {
|
|
|
277
277
|
const gsdPath = gsdRoot(basePath);
|
|
278
278
|
if (!existsSync(gsdPath))
|
|
279
279
|
return null;
|
|
280
|
-
const hasPreferences = existsSync(join(gsdPath, "
|
|
281
|
-
existsSync(join(gsdPath, "
|
|
280
|
+
const hasPreferences = existsSync(join(gsdPath, "PREFERENCES.md")) ||
|
|
281
|
+
existsSync(join(gsdPath, "preferences.md"));
|
|
282
282
|
const hasContext = existsSync(join(gsdPath, "CONTEXT.md"));
|
|
283
283
|
let milestoneCount = 0;
|
|
284
284
|
const milestonesPath = join(gsdPath, "milestones");
|
|
@@ -596,8 +596,8 @@ function detectVerificationCommands(basePath, detectedFiles, packageManager) {
|
|
|
596
596
|
* Check if global GSD setup exists (has ~/.gsd/ with preferences).
|
|
597
597
|
*/
|
|
598
598
|
export function hasGlobalSetup() {
|
|
599
|
-
return (existsSync(join(gsdHome, "
|
|
600
|
-
existsSync(join(gsdHome, "
|
|
599
|
+
return (existsSync(join(gsdHome, "PREFERENCES.md")) ||
|
|
600
|
+
existsSync(join(gsdHome, "preferences.md")));
|
|
601
601
|
}
|
|
602
602
|
/**
|
|
603
603
|
* Check if this is the very first time GSD has been used on this machine.
|
|
@@ -607,8 +607,8 @@ export function isFirstEverLaunch() {
|
|
|
607
607
|
if (!existsSync(gsdHome))
|
|
608
608
|
return true;
|
|
609
609
|
// If we have preferences, not first launch
|
|
610
|
-
if (existsSync(join(gsdHome, "
|
|
611
|
-
existsSync(join(gsdHome, "
|
|
610
|
+
if (existsSync(join(gsdHome, "PREFERENCES.md")) ||
|
|
611
|
+
existsSync(join(gsdHome, "preferences.md"))) {
|
|
612
612
|
return false;
|
|
613
613
|
}
|
|
614
614
|
// If we have auth.json, not first launch (onboarding.ts already ran)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GSD Preferences Reference
|
|
2
2
|
|
|
3
|
-
Full documentation for `~/.gsd/
|
|
3
|
+
Full documentation for `~/.gsd/PREFERENCES.md` (global) and `.gsd/PREFERENCES.md` (project).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -51,8 +51,8 @@ skill_rules: []
|
|
|
51
51
|
|
|
52
52
|
Preferences are loaded from two locations and merged:
|
|
53
53
|
|
|
54
|
-
1. **Global:** `~/.gsd/
|
|
55
|
-
2. **Project:** `.gsd/
|
|
54
|
+
1. **Global:** `~/.gsd/PREFERENCES.md` — applies to all projects
|
|
55
|
+
2. **Project:** `.gsd/PREFERENCES.md` — applies to the current project only
|
|
56
56
|
|
|
57
57
|
**Merge behavior** (see `mergePreferences()` in `preferences.ts`):
|
|
58
58
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified error classifier for provider/network/server errors.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates patterns from:
|
|
5
|
+
* - isTransientNetworkError() in preferences-models.ts
|
|
6
|
+
* - classifyProviderError() in provider-error-pause.ts
|
|
7
|
+
*
|
|
8
|
+
* Single entry point: classifyError(errorMsg, retryAfterMs?)
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/gsd-build/gsd/issues/2577
|
|
11
|
+
*/
|
|
12
|
+
export function createRetryState() {
|
|
13
|
+
return { networkRetryCount: 0, consecutiveTransientCount: 0, currentRetryModelId: undefined };
|
|
14
|
+
}
|
|
15
|
+
export function resetRetryState(state) {
|
|
16
|
+
state.networkRetryCount = 0;
|
|
17
|
+
state.consecutiveTransientCount = 0;
|
|
18
|
+
state.currentRetryModelId = undefined;
|
|
19
|
+
}
|
|
20
|
+
// ── Classification ──────────────────────────────────────────────────────────
|
|
21
|
+
const PERMANENT_RE = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i;
|
|
22
|
+
const RATE_LIMIT_RE = /rate.?limit|too many requests|429/i;
|
|
23
|
+
const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|fetch failed|connection.*reset|dns/i;
|
|
24
|
+
const SERVER_RE = /internal server error|500|502|503|overloaded|server_error|api_error|service.?unavailable/i;
|
|
25
|
+
// ECONNRESET/ECONNREFUSED are in NETWORK_RE (same-model retry first).
|
|
26
|
+
const CONNECTION_RE = /terminated|connection.?refused|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
|
|
27
|
+
const STREAM_RE = /Unexpected end of JSON|Unexpected token.*JSON|Expected double-quoted property name|SyntaxError.*JSON/i;
|
|
28
|
+
const RESET_DELAY_RE = /reset in (\d+)s/i;
|
|
29
|
+
/**
|
|
30
|
+
* Classify an error message into one of the ErrorClass kinds.
|
|
31
|
+
*
|
|
32
|
+
* Classification order:
|
|
33
|
+
* 1. Permanent (auth/billing/quota) — unless also rate-limited
|
|
34
|
+
* 2. Rate limit (429, rate.?limit, too many requests)
|
|
35
|
+
* 3. Network (ECONNRESET, ETIMEDOUT, socket hang up, fetch failed, dns)
|
|
36
|
+
* 4. Server (500/502/503, overloaded, server_error)
|
|
37
|
+
* 5. Connection (terminated, ECONNREFUSED, EPIPE, other side closed)
|
|
38
|
+
* 6. Stream truncation (malformed JSON from mid-stream cut)
|
|
39
|
+
* 7. Unknown
|
|
40
|
+
*/
|
|
41
|
+
export function classifyError(errorMsg, retryAfterMs) {
|
|
42
|
+
const isPermanent = PERMANENT_RE.test(errorMsg);
|
|
43
|
+
const isRateLimit = RATE_LIMIT_RE.test(errorMsg);
|
|
44
|
+
// 1. Permanent — but rate limit takes precedence
|
|
45
|
+
if (isPermanent && !isRateLimit) {
|
|
46
|
+
return { kind: "permanent" };
|
|
47
|
+
}
|
|
48
|
+
// 2. Rate limit
|
|
49
|
+
if (isRateLimit) {
|
|
50
|
+
if (retryAfterMs != null && retryAfterMs > 0) {
|
|
51
|
+
return { kind: "rate-limit", retryAfterMs };
|
|
52
|
+
}
|
|
53
|
+
const resetMatch = errorMsg.match(RESET_DELAY_RE);
|
|
54
|
+
const delayMs = resetMatch ? Number(resetMatch[1]) * 1000 : 60_000;
|
|
55
|
+
return { kind: "rate-limit", retryAfterMs: delayMs };
|
|
56
|
+
}
|
|
57
|
+
// 3. Network errors — same-model retry candidate
|
|
58
|
+
if (NETWORK_RE.test(errorMsg)) {
|
|
59
|
+
// Exclude if also matches permanent signals (already handled above for
|
|
60
|
+
// rate-limit, but double-check for non-rate-limit permanent overlap like
|
|
61
|
+
// "billing" appearing alongside "network").
|
|
62
|
+
return { kind: "network", retryAfterMs: retryAfterMs ?? 3_000 };
|
|
63
|
+
}
|
|
64
|
+
// 4. Server errors — try fallback model
|
|
65
|
+
if (SERVER_RE.test(errorMsg)) {
|
|
66
|
+
return { kind: "server", retryAfterMs: retryAfterMs ?? 30_000 };
|
|
67
|
+
}
|
|
68
|
+
// 5. Connection errors — try fallback model
|
|
69
|
+
if (CONNECTION_RE.test(errorMsg)) {
|
|
70
|
+
return { kind: "connection", retryAfterMs: retryAfterMs ?? 15_000 };
|
|
71
|
+
}
|
|
72
|
+
// 6. Stream truncation — downstream symptom of connection drop
|
|
73
|
+
if (STREAM_RE.test(errorMsg)) {
|
|
74
|
+
return { kind: "stream", retryAfterMs: retryAfterMs ?? 15_000 };
|
|
75
|
+
}
|
|
76
|
+
// 7. Unknown
|
|
77
|
+
return { kind: "unknown" };
|
|
78
|
+
}
|
|
79
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
80
|
+
/** Returns true for all transient (auto-resumable) error kinds. */
|
|
81
|
+
export function isTransient(cls) {
|
|
82
|
+
switch (cls.kind) {
|
|
83
|
+
case "network":
|
|
84
|
+
case "rate-limit":
|
|
85
|
+
case "server":
|
|
86
|
+
case "stream":
|
|
87
|
+
case "connection":
|
|
88
|
+
return true;
|
|
89
|
+
default:
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Backward-compatible thin wrapper.
|
|
95
|
+
*
|
|
96
|
+
* Returns true when the error is a transient *network* error specifically
|
|
97
|
+
* (worth retrying the same model). Permanent signals (auth, billing, quota)
|
|
98
|
+
* cause this to return false even if a network keyword is present.
|
|
99
|
+
*/
|
|
100
|
+
export function isTransientNetworkError(errorMsg) {
|
|
101
|
+
if (!errorMsg)
|
|
102
|
+
return false;
|
|
103
|
+
const cls = classifyError(errorMsg);
|
|
104
|
+
return cls.kind === "network";
|
|
105
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GSD bootstrappers for .gitignore and
|
|
2
|
+
* GSD bootstrappers for .gitignore and PREFERENCES.md
|
|
3
3
|
*
|
|
4
4
|
* Ensures baseline .gitignore exists with universally-correct patterns.
|
|
5
|
-
* Creates an empty
|
|
5
|
+
* Creates an empty PREFERENCES.md template if it doesn't exist.
|
|
6
6
|
* Both idempotent — non-destructive if already present.
|
|
7
7
|
*/
|
|
8
8
|
import { join } from "node:path";
|
|
@@ -190,16 +190,16 @@ export function untrackRuntimeFiles(basePath) {
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
* Ensure basePath/.gsd/
|
|
193
|
+
* Ensure basePath/.gsd/PREFERENCES.md exists as an empty template.
|
|
194
194
|
* Creates the file with frontmatter only if it doesn't exist.
|
|
195
195
|
* Returns true if created, false if already exists.
|
|
196
196
|
*
|
|
197
|
-
* Checks both
|
|
198
|
-
* creating a duplicate when
|
|
197
|
+
* Checks both uppercase (canonical) and lowercase (legacy) to avoid
|
|
198
|
+
* creating a duplicate when a lowercase file already exists.
|
|
199
199
|
*/
|
|
200
200
|
export function ensurePreferences(basePath) {
|
|
201
|
-
const preferencesPath = join(gsdRoot(basePath), "
|
|
202
|
-
const legacyPath = join(gsdRoot(basePath), "
|
|
201
|
+
const preferencesPath = join(gsdRoot(basePath), "PREFERENCES.md");
|
|
202
|
+
const legacyPath = join(gsdRoot(basePath), "preferences.md");
|
|
203
203
|
if (existsSync(preferencesPath) || existsSync(legacyPath)) {
|
|
204
204
|
return false;
|
|
205
205
|
}
|