@opengsd/gsd-pi 1.2.0-dev.d6c5343c → 1.2.0-dev.ddc97c10
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/dist/mcp-server.js +2 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +28 -10
- package/dist/resources/extensions/gsd/auto/phases.js +47 -4
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +3 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +18 -6
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto.js +37 -1
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/consent-question.js +16 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -3
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -1
- package/dist/resources/extensions/gsd/guided-flow.js +6 -3
- package/dist/resources/extensions/gsd/milestone-closeout.js +73 -2
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +21 -2
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- 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/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +10 -5
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +99 -38
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.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/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +28 -10
- package/src/resources/extensions/gsd/auto/phases.ts +63 -24
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +10 -16
- package/src/resources/extensions/gsd/auto-dispatch.ts +11 -10
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +21 -6
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto.ts +44 -1
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/consent-question.ts +15 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +21 -26
- package/src/resources/extensions/gsd/milestone-closeout.ts +97 -2
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/shared/gsd-browser-cli.ts +23 -2
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- /package/dist/web/standalone/.next/static/{jmTLg6xZmAuq_LIqKOxrH → McokybTayhff1xEVc-d3T}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{jmTLg6xZmAuq_LIqKOxrH → McokybTayhff1xEVc-d3T}/_ssgManifest.js +0 -0
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
reopenMilestoneCascade,
|
|
16
16
|
} from "../gsd-db.js";
|
|
17
17
|
import { invalidateStateCache } from "../state.js";
|
|
18
|
-
import {
|
|
18
|
+
import { flushWorkflowProjections } from "../projection-flush.js";
|
|
19
19
|
import { writeManifest } from "../workflow-manifest.js";
|
|
20
20
|
import { appendEvent } from "../workflow-events.js";
|
|
21
21
|
import { logWarning } from "../workflow-logger.js";
|
|
@@ -98,7 +98,7 @@ export async function handleReopenMilestone(
|
|
|
98
98
|
|
|
99
99
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
100
100
|
try {
|
|
101
|
-
await
|
|
101
|
+
await flushWorkflowProjections(basePath, { milestoneId: params.milestoneId });
|
|
102
102
|
writeManifest(basePath);
|
|
103
103
|
appendEvent(basePath, {
|
|
104
104
|
cmd: "reopen-milestone",
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
reopenSliceCascade,
|
|
17
17
|
} from "../gsd-db.js";
|
|
18
18
|
import { invalidateStateCache } from "../state.js";
|
|
19
|
-
import {
|
|
19
|
+
import { flushWorkflowProjections } from "../projection-flush.js";
|
|
20
20
|
import { writeManifest } from "../workflow-manifest.js";
|
|
21
21
|
import { appendEvent } from "../workflow-events.js";
|
|
22
22
|
import { logWarning } from "../workflow-logger.js";
|
|
@@ -97,7 +97,7 @@ export async function handleReopenSlice(
|
|
|
97
97
|
|
|
98
98
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
99
99
|
try {
|
|
100
|
-
await
|
|
100
|
+
await flushWorkflowProjections(basePath, { milestoneId: params.milestoneId });
|
|
101
101
|
writeManifest(basePath);
|
|
102
102
|
appendEvent(basePath, {
|
|
103
103
|
cmd: "reopen-slice",
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "../gsd-db.js";
|
|
20
20
|
import { invalidateStateCache } from "../state.js";
|
|
21
21
|
import { isClosedStatus } from "../status-guards.js";
|
|
22
|
-
import {
|
|
22
|
+
import { flushWorkflowProjections } from "../projection-flush.js";
|
|
23
23
|
import { writeManifest } from "../workflow-manifest.js";
|
|
24
24
|
import { appendEvent } from "../workflow-events.js";
|
|
25
25
|
import { logWarning } from "../workflow-logger.js";
|
|
@@ -119,7 +119,7 @@ export async function handleReopenTask(
|
|
|
119
119
|
|
|
120
120
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
121
121
|
try {
|
|
122
|
-
await
|
|
122
|
+
await flushWorkflowProjections(basePath, { milestoneId: params.milestoneId });
|
|
123
123
|
writeManifest(basePath);
|
|
124
124
|
appendEvent(basePath, {
|
|
125
125
|
cmd: "reopen-task",
|
|
@@ -13,7 +13,7 @@ import { invalidateStateCache } from "../state.js";
|
|
|
13
13
|
import { isClosedStatus } from "../status-guards.js";
|
|
14
14
|
import { isNonEmptyString } from "../validation.js";
|
|
15
15
|
import { renderPlanFromDb, renderReplanFromDb } from "../markdown-renderer.js";
|
|
16
|
-
import {
|
|
16
|
+
import { flushWorkflowProjections } from "../projection-flush.js";
|
|
17
17
|
import { writeManifest } from "../workflow-manifest.js";
|
|
18
18
|
import { appendEvent } from "../workflow-events.js";
|
|
19
19
|
import { logWarning } from "../workflow-logger.js";
|
|
@@ -216,7 +216,7 @@ export async function handleReplanSlice(
|
|
|
216
216
|
|
|
217
217
|
// ── Post-mutation hook: projections, manifest, event log ─────
|
|
218
218
|
try {
|
|
219
|
-
await
|
|
219
|
+
await flushWorkflowProjections(basePath, { milestoneId: params.milestoneId });
|
|
220
220
|
writeManifest(basePath);
|
|
221
221
|
appendEvent(basePath, {
|
|
222
222
|
cmd: "replan-slice",
|
|
@@ -19,9 +19,10 @@ import {
|
|
|
19
19
|
} from "../gsd-db.js";
|
|
20
20
|
import { GATE_REGISTRY } from "../gate-registry.js";
|
|
21
21
|
import { generateRequirementsMd, saveArtifactToDb } from "../db-writer.js";
|
|
22
|
-
import { clearPathCache, relSliceFile, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
|
|
22
|
+
import { clearPathCache, normalizeRealPath, relSliceFile, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
|
|
23
23
|
import { saveFile, clearParseCache } from "../files.js";
|
|
24
24
|
import { unlinkSync } from "node:fs";
|
|
25
|
+
import { hostname } from "node:os";
|
|
25
26
|
import { join } from "node:path";
|
|
26
27
|
import type { CompleteMilestoneParams } from "./complete-milestone.js";
|
|
27
28
|
import { handleCompleteMilestone } from "./complete-milestone.js";
|
|
@@ -48,13 +49,21 @@ import { logError, logWarning } from "../workflow-logger.js";
|
|
|
48
49
|
import { invalidateStateCache } from "../state.js";
|
|
49
50
|
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
50
51
|
import { parseProject } from "../schemas/parsers.js";
|
|
51
|
-
import { getAutoRuntimeSnapshot } from "../auto-runtime-state.js";
|
|
52
|
+
import { autoSession, getAutoRuntimeSnapshot, isAutoActive } from "../auto-runtime-state.js";
|
|
52
53
|
import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
53
54
|
import {
|
|
54
55
|
prepareUatRun,
|
|
55
56
|
saveUatAttemptArtifact,
|
|
56
57
|
type UatResultSaveParams,
|
|
57
58
|
} from "../uat-run.js";
|
|
59
|
+
import { registerAutoWorker, markWorkerStopping, getAutoWorker } from "../db/auto-workers.js";
|
|
60
|
+
import {
|
|
61
|
+
claimMilestoneLease,
|
|
62
|
+
releaseMilestoneLease,
|
|
63
|
+
getMilestoneLease,
|
|
64
|
+
refreshMilestoneLease,
|
|
65
|
+
milestoneLeaseTtlSeconds,
|
|
66
|
+
} from "../db/milestone-leases.js";
|
|
58
67
|
export type {
|
|
59
68
|
UatCheckResultInput,
|
|
60
69
|
UatEvidenceRef,
|
|
@@ -105,6 +114,24 @@ function blockIfWrongAutoUnit(requiredUnitType: string, operation: string): Tool
|
|
|
105
114
|
};
|
|
106
115
|
}
|
|
107
116
|
|
|
117
|
+
function milestoneLeaseConflictResult(
|
|
118
|
+
milestoneId: string,
|
|
119
|
+
byWorker: string,
|
|
120
|
+
expiresAt: string,
|
|
121
|
+
): ToolExecutionResult {
|
|
122
|
+
return {
|
|
123
|
+
content: [{ type: "text", text: `Milestone ${milestoneId} is currently leased by ${byWorker}. Retry after ${expiresAt}.` }],
|
|
124
|
+
details: {
|
|
125
|
+
operation: "plan_milestone",
|
|
126
|
+
error: "milestone_lease_conflict",
|
|
127
|
+
milestoneId,
|
|
128
|
+
byWorker,
|
|
129
|
+
expiresAt,
|
|
130
|
+
},
|
|
131
|
+
isError: true,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
108
135
|
export interface SummarySaveParams {
|
|
109
136
|
milestone_id?: string;
|
|
110
137
|
slice_id?: string;
|
|
@@ -1244,7 +1271,48 @@ export async function executePlanMilestone(
|
|
|
1244
1271
|
isError: true,
|
|
1245
1272
|
};
|
|
1246
1273
|
}
|
|
1274
|
+
let workerId: string | null = null;
|
|
1275
|
+
let acquiredToken: number | null = null;
|
|
1276
|
+
let leaseRefreshTimer: ReturnType<typeof setInterval> | undefined;
|
|
1247
1277
|
try {
|
|
1278
|
+
// Re-read at the gate so a peer-created milestone is not treated as fresh.
|
|
1279
|
+
const milestoneExists = getMilestone(params.milestoneId) !== null;
|
|
1280
|
+
if (milestoneExists) {
|
|
1281
|
+
const heldLease = getMilestoneLease(params.milestoneId);
|
|
1282
|
+
if (heldLease?.status === "held" && Date.parse(heldLease.expires_at) > Date.now()) {
|
|
1283
|
+
const holder = getAutoWorker(heldLease.worker_id);
|
|
1284
|
+
// Let the one-shot claim path recover stale same-process worker rows.
|
|
1285
|
+
const projectRoot = normalizeRealPath(basePath);
|
|
1286
|
+
const isOurAutoLease = isAutoActive() && heldLease.worker_id === autoSession.workerId;
|
|
1287
|
+
const holderIsOneShotReentrantPeer = !isAutoActive()
|
|
1288
|
+
&& !!holder
|
|
1289
|
+
&& holder.host === hostname()
|
|
1290
|
+
&& holder.pid === process.pid
|
|
1291
|
+
&& holder.project_root_realpath === projectRoot;
|
|
1292
|
+
if (holder?.status === "active" && !isOurAutoLease && !holderIsOneShotReentrantPeer) {
|
|
1293
|
+
return milestoneLeaseConflictResult(params.milestoneId, heldLease.worker_id, heldLease.expires_at);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// Fresh creation cannot claim a lease because the FK row does not exist.
|
|
1299
|
+
// In-process auto already owns its lease; re-claiming would bump its token.
|
|
1300
|
+
if (!isAutoActive() && milestoneExists) {
|
|
1301
|
+
workerId = registerAutoWorker({ projectRootRealpath: normalizeRealPath(basePath) });
|
|
1302
|
+
const lease = claimMilestoneLease(workerId, params.milestoneId);
|
|
1303
|
+
if (!lease.ok) {
|
|
1304
|
+
return milestoneLeaseConflictResult(params.milestoneId, lease.byWorker, lease.expiresAt);
|
|
1305
|
+
}
|
|
1306
|
+
acquiredToken = lease.token;
|
|
1307
|
+
|
|
1308
|
+
const leaseRefreshMs = (milestoneLeaseTtlSeconds() / 2) * 1000;
|
|
1309
|
+
leaseRefreshTimer = setInterval(() => {
|
|
1310
|
+
if (acquiredToken !== null && workerId !== null) {
|
|
1311
|
+
refreshMilestoneLease(workerId, params.milestoneId, acquiredToken);
|
|
1312
|
+
}
|
|
1313
|
+
}, leaseRefreshMs);
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1248
1316
|
const result = await handlePlanMilestone(params, basePath);
|
|
1249
1317
|
if ("error" in result) {
|
|
1250
1318
|
return {
|
|
@@ -1270,6 +1338,17 @@ export async function executePlanMilestone(
|
|
|
1270
1338
|
isError: true,
|
|
1271
1339
|
};
|
|
1272
1340
|
}
|
|
1341
|
+
finally {
|
|
1342
|
+
if (leaseRefreshTimer !== undefined) {
|
|
1343
|
+
clearInterval(leaseRefreshTimer);
|
|
1344
|
+
}
|
|
1345
|
+
if (workerId !== null && acquiredToken !== null) {
|
|
1346
|
+
releaseMilestoneLease(workerId, params.milestoneId, acquiredToken);
|
|
1347
|
+
}
|
|
1348
|
+
if (workerId !== null) {
|
|
1349
|
+
markWorkerStopping(workerId);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1273
1352
|
}
|
|
1274
1353
|
|
|
1275
1354
|
export async function executePlanSlice(
|
|
@@ -15,6 +15,9 @@ export interface VerificationVerdict {
|
|
|
15
15
|
failureContext: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export const NO_HOST_CHECKS_FAILURE_CONTEXT =
|
|
19
|
+
"No runnable host-owned verification command was discovered. Add project verification_commands in .gsd/PREFERENCES.md or a runnable task-plan Verify command, then resume with /gsd next.";
|
|
20
|
+
|
|
18
21
|
export function decideVerificationVerdict(
|
|
19
22
|
unitType: string,
|
|
20
23
|
result: VerificationGateResult,
|
|
@@ -33,8 +36,7 @@ export function decideVerificationVerdict(
|
|
|
33
36
|
passed: false,
|
|
34
37
|
reason: "no-host-checks",
|
|
35
38
|
retryable: false,
|
|
36
|
-
failureContext:
|
|
37
|
-
"No runnable host-owned verification command was discovered. Add project verification_commands or a runnable task-plan Verify command before completing this execute-task.",
|
|
39
|
+
failureContext: NO_HOST_CHECKS_FAILURE_CONTEXT,
|
|
38
40
|
};
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -55,6 +55,24 @@ function parseGsdBrowserVersion(output: string): string | null {
|
|
|
55
55
|
return output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function splitCommandLine(commandLine: string): string[] {
|
|
59
|
+
const parts = commandLine.match(/(?:"[^"]*"|'[^']*'|[^\s"']+)/g) ?? [];
|
|
60
|
+
return parts.map((part) => {
|
|
61
|
+
const quote = part[0];
|
|
62
|
+
if ((quote === '"' || quote === "'") && part.endsWith(quote)) {
|
|
63
|
+
return part.slice(1, -1);
|
|
64
|
+
}
|
|
65
|
+
return part;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function buildPathGsdBrowserVersionInvocation(platform: NodeJS.Platform): { command: string; args: string[] } {
|
|
70
|
+
if (platform === "win32") {
|
|
71
|
+
return { command: "cmd", args: ["/d", "/s", "/c", "gsd-browser", "--version"] };
|
|
72
|
+
}
|
|
73
|
+
return { command: "gsd-browser", args: ["--version"] };
|
|
74
|
+
}
|
|
75
|
+
|
|
58
76
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
59
77
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
60
78
|
}
|
|
@@ -86,7 +104,8 @@ function resolvePathGsdBrowserVersion(env: NodeJS.ProcessEnv): string | null {
|
|
|
86
104
|
if (cachedPathProbeVersion !== undefined) return cachedPathProbeVersion;
|
|
87
105
|
|
|
88
106
|
try {
|
|
89
|
-
|
|
107
|
+
const invocation = buildPathGsdBrowserVersionInvocation(process.platform);
|
|
108
|
+
cachedPathProbeVersion = parseGsdBrowserVersion(execFileSync(invocation.command, invocation.args, {
|
|
90
109
|
encoding: "utf-8",
|
|
91
110
|
env,
|
|
92
111
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -216,7 +235,8 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
216
235
|
const serverName = env.GSD_BROWSER_MCP_NAME?.trim() || GSD_BROWSER_MCP_SERVER_NAME;
|
|
217
236
|
const explicitArgs = parseJsonEnv<unknown>(env, "GSD_BROWSER_MCP_ARGS");
|
|
218
237
|
const explicitEnv = parseJsonEnv<Record<string, string>>(env, "GSD_BROWSER_MCP_ENV");
|
|
219
|
-
const
|
|
238
|
+
const explicitCommandLine = env.GSD_BROWSER_MCP_COMMAND?.trim();
|
|
239
|
+
const [explicitCommand, ...explicitCommandArgs] = explicitCommandLine ? splitCommandLine(explicitCommandLine) : [];
|
|
220
240
|
const explicitCliPath = resolveExplicitGsdBrowserCliPath(env);
|
|
221
241
|
const preferPathCli = !explicitCommand && !explicitCliPath && shouldPreferPathGsdBrowser(env);
|
|
222
242
|
const bundledCliPath = !explicitCommand && !explicitCliPath && !preferPathCli
|
|
@@ -241,6 +261,7 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
241
261
|
const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
|
|
242
262
|
? explicitArgs.map(String)
|
|
243
263
|
: [
|
|
264
|
+
...explicitCommandArgs,
|
|
244
265
|
...(bundledCliPath ? [bundledCliPath] : []),
|
|
245
266
|
"mcp",
|
|
246
267
|
"--session",
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, readlinkSync, realpathSync } from 'node:fs'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
4
|
+
import { dirname, isAbsolute, join, delimiter as pathDelimiter, resolve as resolvePath } from 'node:path'
|
|
5
|
+
import { isPnpmInstall, pathStartsWith } from './package-manager-detection.js'
|
|
6
|
+
|
|
7
|
+
export interface GsdBrowserPathReconcileResult {
|
|
8
|
+
action: 'none' | 'synced' | 'shadowed'
|
|
9
|
+
pathCli?: string
|
|
10
|
+
installedCli?: string
|
|
11
|
+
syncTarget?: string
|
|
12
|
+
message?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isBunGlobalInstall(argv1: string | undefined, env: NodeJS.ProcessEnv): boolean {
|
|
16
|
+
if ('bun' in process.versions) return true
|
|
17
|
+
if (!argv1) return false
|
|
18
|
+
|
|
19
|
+
const bunBinDirs: string[] = []
|
|
20
|
+
if (env.BUN_INSTALL) bunBinDirs.push(join(env.BUN_INSTALL, 'bin'))
|
|
21
|
+
bunBinDirs.push(join(homedir(), '.bun', 'bin'))
|
|
22
|
+
|
|
23
|
+
return bunBinDirs.some((dir) => pathStartsWith(argv1, dir))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function gsdBrowserBinaryName(platform: NodeJS.Platform): string {
|
|
27
|
+
return platform === 'win32' ? 'gsd-browser.cmd' : 'gsd-browser'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function tryResolveFromBinDir(binDir: string, platform: NodeJS.Platform): string | null {
|
|
31
|
+
const primary = join(binDir, gsdBrowserBinaryName(platform))
|
|
32
|
+
if (existsSync(primary)) return primary
|
|
33
|
+
|
|
34
|
+
if (platform === 'win32') {
|
|
35
|
+
const fallback = join(binDir, 'gsd-browser')
|
|
36
|
+
if (existsSync(fallback)) return fallback
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function tryResolveFromPackageRoot(
|
|
43
|
+
rootDir: string,
|
|
44
|
+
platform: NodeJS.Platform,
|
|
45
|
+
): string | null {
|
|
46
|
+
const candidate = join(rootDir, '@opengsd', 'gsd-browser', 'bin', gsdBrowserBinaryName(platform))
|
|
47
|
+
if (existsSync(candidate)) return candidate
|
|
48
|
+
|
|
49
|
+
if (platform === 'win32') {
|
|
50
|
+
const fallback = join(rootDir, '@opengsd', 'gsd-browser', 'bin', 'gsd-browser')
|
|
51
|
+
if (existsSync(fallback)) return fallback
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function tryExecLookup(
|
|
58
|
+
command: string,
|
|
59
|
+
args: string[],
|
|
60
|
+
env: NodeJS.ProcessEnv,
|
|
61
|
+
platform: NodeJS.Platform,
|
|
62
|
+
resolve: (dir: string, platform: NodeJS.Platform) => string | null,
|
|
63
|
+
): string | null {
|
|
64
|
+
try {
|
|
65
|
+
const dir = execFileSync(command, args, {
|
|
66
|
+
encoding: 'utf-8',
|
|
67
|
+
env,
|
|
68
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
69
|
+
timeout: 5000,
|
|
70
|
+
}).trim()
|
|
71
|
+
return resolve(dir, platform)
|
|
72
|
+
} catch {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function resolvePathBinary(env: NodeJS.ProcessEnv, platform: NodeJS.Platform): string | null {
|
|
78
|
+
if (platform === 'win32') {
|
|
79
|
+
try {
|
|
80
|
+
const out = execFileSync('where', ['gsd-browser'], {
|
|
81
|
+
encoding: 'utf-8',
|
|
82
|
+
env,
|
|
83
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
84
|
+
timeout: 5000,
|
|
85
|
+
}).trim()
|
|
86
|
+
const first = out.split(/\r?\n/).map((line) => line.trim()).find(Boolean)
|
|
87
|
+
return first && existsSync(first) ? first : null
|
|
88
|
+
} catch {
|
|
89
|
+
return null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const entry of (env.PATH ?? '').split(pathDelimiter)) {
|
|
94
|
+
if (!entry) continue
|
|
95
|
+
const candidate = join(entry, 'gsd-browser')
|
|
96
|
+
if (existsSync(candidate)) return candidate
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveRealPath(pathValue: string): string {
|
|
103
|
+
try {
|
|
104
|
+
return realpathSync(pathValue)
|
|
105
|
+
} catch {
|
|
106
|
+
return resolvePath(pathValue)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function resolveSymlinkTarget(pathCli: string): string {
|
|
111
|
+
try {
|
|
112
|
+
const stat = lstatSync(pathCli)
|
|
113
|
+
if (!stat.isSymbolicLink()) return pathCli
|
|
114
|
+
|
|
115
|
+
const target = readlinkSync(pathCli)
|
|
116
|
+
return isAbsolute(target) ? target : resolvePath(dirname(pathCli), target)
|
|
117
|
+
} catch {
|
|
118
|
+
// PATH entry vanished or is inaccessible between resolution and sync.
|
|
119
|
+
// Fall back to the original path; subsequent sync will surface a useful
|
|
120
|
+
// error rather than escaping as an unhandled throw.
|
|
121
|
+
return pathCli
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function resolveHomeDir(env: NodeJS.ProcessEnv): string {
|
|
126
|
+
const fromEnv = env.HOME?.trim() || env.USERPROFILE?.trim()
|
|
127
|
+
return resolvePath(fromEnv || homedir())
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function canAutoSyncTarget(targetPath: string, env: NodeJS.ProcessEnv): boolean {
|
|
131
|
+
const home = resolveHomeDir(env)
|
|
132
|
+
const resolved = resolvePath(targetPath)
|
|
133
|
+
return pathStartsWith(resolved, home)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function syncBinary(installedCli: string, targetPath: string, platform: NodeJS.Platform): void {
|
|
137
|
+
const source = resolveRealPath(installedCli)
|
|
138
|
+
copyFileSync(source, targetPath)
|
|
139
|
+
if (platform !== 'win32') {
|
|
140
|
+
chmodSync(targetPath, 0o755)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Resolve the gsd-browser binary installed by the active global package manager.
|
|
146
|
+
*/
|
|
147
|
+
export function resolveGlobalGsdBrowserCliPath(
|
|
148
|
+
options: { env?: NodeJS.ProcessEnv; argv1?: string; platform?: NodeJS.Platform } = {},
|
|
149
|
+
): string | null {
|
|
150
|
+
const env = options.env ?? process.env
|
|
151
|
+
const argv1 = options.argv1 ?? process.argv[1]
|
|
152
|
+
const platform = options.platform ?? process.platform
|
|
153
|
+
|
|
154
|
+
if (isBunGlobalInstall(argv1, env)) {
|
|
155
|
+
return (
|
|
156
|
+
tryExecLookup('bun', ['pm', 'bin', '-g'], env, platform, tryResolveFromBinDir)
|
|
157
|
+
?? (env.BUN_INSTALL ? tryResolveFromBinDir(join(env.BUN_INSTALL, 'bin'), platform) : null)
|
|
158
|
+
?? tryResolveFromBinDir(join(homedir(), '.bun', 'bin'), platform)
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (isPnpmInstall(argv1, env)) {
|
|
163
|
+
return (
|
|
164
|
+
tryExecLookup('pnpm', ['bin', '-g'], env, platform, tryResolveFromBinDir)
|
|
165
|
+
?? tryExecLookup('pnpm', ['root', '-g'], env, platform, tryResolveFromPackageRoot)
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
tryExecLookup('npm', ['bin', '-g'], env, platform, tryResolveFromBinDir)
|
|
171
|
+
?? tryExecLookup('npm', ['root', '-g'], env, platform, tryResolveFromPackageRoot)
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the gsd-browser binary that wins on PATH (`command -v` / `where`).
|
|
177
|
+
*/
|
|
178
|
+
export function resolveGsdBrowserOnPath(
|
|
179
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
180
|
+
platform: NodeJS.Platform = process.platform,
|
|
181
|
+
): string | null {
|
|
182
|
+
return resolvePathBinary(env, platform)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* After a global gsd-browser install, ensure the PATH-resolved binary matches
|
|
187
|
+
* the freshly installed global binary when an older copy is shadowing it.
|
|
188
|
+
*/
|
|
189
|
+
export function reconcileGsdBrowserPathAfterInstall(
|
|
190
|
+
options: {
|
|
191
|
+
latestVersion: string
|
|
192
|
+
compareSemver: (a: string, b: string) => number
|
|
193
|
+
resolvePathVersion: (env: NodeJS.ProcessEnv) => string | null
|
|
194
|
+
env?: NodeJS.ProcessEnv
|
|
195
|
+
argv1?: string
|
|
196
|
+
platform?: NodeJS.Platform
|
|
197
|
+
},
|
|
198
|
+
): GsdBrowserPathReconcileResult {
|
|
199
|
+
const env = options.env ?? process.env
|
|
200
|
+
const argv1 = options.argv1 ?? process.argv[1]
|
|
201
|
+
const platform = options.platform ?? process.platform
|
|
202
|
+
|
|
203
|
+
const installedCli = resolveGlobalGsdBrowserCliPath({ env, argv1, platform })
|
|
204
|
+
if (!installedCli) {
|
|
205
|
+
return { action: 'none' }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const pathCli = resolveGsdBrowserOnPath(env, platform)
|
|
209
|
+
const installedReal = resolveRealPath(installedCli)
|
|
210
|
+
if (pathCli && resolveRealPath(pathCli) === installedReal) {
|
|
211
|
+
return { action: 'none', pathCli, installedCli }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const pathVersion = options.resolvePathVersion(env)
|
|
215
|
+
if (pathVersion && options.compareSemver(pathVersion, options.latestVersion) >= 0) {
|
|
216
|
+
return { action: 'none', pathCli: pathCli ?? undefined, installedCli }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!pathCli) {
|
|
220
|
+
return {
|
|
221
|
+
action: 'shadowed',
|
|
222
|
+
installedCli,
|
|
223
|
+
message:
|
|
224
|
+
'Installed gsd-browser globally, but no gsd-browser was found on PATH. Add your package manager global bin directory to PATH.',
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const syncTarget = resolveSymlinkTarget(pathCli)
|
|
229
|
+
if (!canAutoSyncTarget(syncTarget, env)) {
|
|
230
|
+
return {
|
|
231
|
+
action: 'shadowed',
|
|
232
|
+
pathCli,
|
|
233
|
+
installedCli,
|
|
234
|
+
syncTarget,
|
|
235
|
+
message:
|
|
236
|
+
`PATH resolves gsd-browser to ${pathCli}, but the updated global install is at ${installedCli}. ` +
|
|
237
|
+
'Move your package manager global bin directory ahead of the stale location on PATH, or update the stale binary manually.',
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let syncSucceeded = false
|
|
242
|
+
try {
|
|
243
|
+
syncBinary(installedCli, syncTarget, platform)
|
|
244
|
+
syncSucceeded = true
|
|
245
|
+
} catch {
|
|
246
|
+
// Fall through to shadowed guidance.
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (syncSucceeded) {
|
|
250
|
+
const refreshedVersion = options.resolvePathVersion(env)
|
|
251
|
+
const verified = refreshedVersion !== null
|
|
252
|
+
&& options.compareSemver(refreshedVersion, options.latestVersion) >= 0
|
|
253
|
+
return {
|
|
254
|
+
action: 'synced',
|
|
255
|
+
pathCli,
|
|
256
|
+
installedCli,
|
|
257
|
+
syncTarget,
|
|
258
|
+
message: verified
|
|
259
|
+
? `Synced PATH-resolved gsd-browser at ${syncTarget} to the updated global install.`
|
|
260
|
+
: `Synced PATH-resolved gsd-browser at ${syncTarget} to the updated global install. Could not verify the new version on PATH; restart your shell or rerun if it still reports the old version.`,
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
action: 'shadowed',
|
|
266
|
+
pathCli,
|
|
267
|
+
installedCli,
|
|
268
|
+
syncTarget,
|
|
269
|
+
message:
|
|
270
|
+
`PATH resolves gsd-browser to ${pathCli}, but the updated global install is at ${installedCli}. ` +
|
|
271
|
+
'Move your package manager global bin directory ahead of the stale location on PATH, or update the stale binary manually.',
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -12,7 +12,7 @@ function hasPnpmPath(value: string | undefined): boolean {
|
|
|
12
12
|
)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function pathStartsWith(pathValue: string | undefined, dir: string): boolean {
|
|
15
|
+
export function pathStartsWith(pathValue: string | undefined, dir: string): boolean {
|
|
16
16
|
if (!pathValue) return false
|
|
17
17
|
const resolvedPath = resolvePath(pathValue)
|
|
18
18
|
const resolvedDir = resolvePath(dir)
|
|
File without changes
|
|
File without changes
|