gsd-pi 2.71.0-dev.977c553 → 2.71.0-dev.e17e0ce
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/cli.js +12 -3
- package/dist/headless-events.d.ts +2 -0
- package/dist/headless-events.js +7 -0
- package/dist/headless.js +16 -3
- package/dist/mcp-server.js +6 -6
- package/dist/provider-migrations.d.ts +10 -0
- package/dist/provider-migrations.js +12 -0
- package/dist/resource-loader.js +139 -13
- package/dist/resources/GSD-WORKFLOW.md +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +10 -4
- package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +1 -1
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
- package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
- package/dist/resources/extensions/gsd/auto-start.js +13 -6
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +52 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +66 -51
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
- package/dist/resources/extensions/gsd/commands/context.js +15 -6
- package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
- package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
- package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +19 -6
- package/dist/resources/extensions/gsd/guided-flow.js +5 -10
- package/dist/resources/extensions/gsd/metrics.js +1 -0
- package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
- package/dist/resources/extensions/gsd/notification-overlay.js +20 -5
- package/dist/resources/extensions/gsd/notification-store.js +51 -1
- package/dist/resources/extensions/gsd/notification-widget.js +5 -13
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +20 -19
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -1
- package/dist/resources/extensions/gsd/session-model-override.js +25 -0
- package/dist/resources/extensions/gsd/shortcut-defs.js +34 -0
- package/dist/resources/skills/create-skill/SKILL.md +2 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- 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 +13 -13
- 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/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +21 -11
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
- package/packages/mcp-server/src/workflow-tools.ts +31 -11
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +7 -4
- package/packages/pi-ai/dist/providers/anthropic.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 +11 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
- package/packages/pi-ai/src/providers/anthropic.ts +8 -4
- package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
- 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 +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.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 +7 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
- package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
- package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
- package/src/resources/GSD-WORKFLOW.md +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +13 -5
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +56 -4
- package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +45 -1
- package/src/resources/extensions/gsd/auto/phases.ts +2 -0
- package/src/resources/extensions/gsd/auto/session.ts +11 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
- package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
- package/src/resources/extensions/gsd/auto-start.ts +13 -6
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +68 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +82 -60
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -5
- package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
- package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +23 -7
- package/src/resources/extensions/gsd/guided-flow.ts +5 -10
- package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
- package/src/resources/extensions/gsd/metrics.ts +12 -1
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
- package/src/resources/extensions/gsd/notification-overlay.ts +24 -7
- package/src/resources/extensions/gsd/notification-store.ts +49 -1
- package/src/resources/extensions/gsd/notification-widget.ts +5 -14
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +20 -19
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +3 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -1
- package/src/resources/extensions/gsd/session-model-override.ts +36 -0
- package/src/resources/extensions/gsd/shortcut-defs.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +62 -5
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
- package/src/resources/skills/create-skill/SKILL.md +2 -0
- /package/dist/web/standalone/.next/static/{4xyaXTn7-shVHaGMcl75o → cYPZv_bAhZk2ms-Pz6vsY}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{4xyaXTn7-shVHaGMcl75o → cYPZv_bAhZk2ms-Pz6vsY}/_ssgManifest.js +0 -0
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
runFinalize,
|
|
28
28
|
} from "./phases.js";
|
|
29
29
|
import { debugLog } from "../debug-logger.js";
|
|
30
|
-
import { isInfrastructureError } from "./infra-errors.js";
|
|
30
|
+
import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
|
|
31
31
|
import { resolveEngine } from "../engine-resolver.js";
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -48,6 +48,7 @@ export async function autoLoop(
|
|
|
48
48
|
let iteration = 0;
|
|
49
49
|
const loopState: LoopState = { recentUnits: [], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
|
|
50
50
|
let consecutiveErrors = 0;
|
|
51
|
+
let consecutiveCooldowns = 0;
|
|
51
52
|
const recentErrorMessages: string[] = [];
|
|
52
53
|
|
|
53
54
|
while (s.active) {
|
|
@@ -203,6 +204,7 @@ export async function autoLoop(
|
|
|
203
204
|
|
|
204
205
|
deps.clearUnitTimeout();
|
|
205
206
|
consecutiveErrors = 0;
|
|
207
|
+
consecutiveCooldowns = 0;
|
|
206
208
|
recentErrorMessages.length = 0;
|
|
207
209
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
208
210
|
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
@@ -265,6 +267,7 @@ export async function autoLoop(
|
|
|
265
267
|
if (finalizeResult.action === "continue") continue;
|
|
266
268
|
|
|
267
269
|
consecutiveErrors = 0; // Iteration completed successfully
|
|
270
|
+
consecutiveCooldowns = 0;
|
|
268
271
|
recentErrorMessages.length = 0;
|
|
269
272
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
270
273
|
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
@@ -300,6 +303,47 @@ export async function autoLoop(
|
|
|
300
303
|
break;
|
|
301
304
|
}
|
|
302
305
|
|
|
306
|
+
// ── Credential cooldown: wait and retry with bounded budget ──
|
|
307
|
+
// A 429 triggers a 30s credential backoff in AuthStorage. If the SDK's
|
|
308
|
+
// getApiKey() retries couldn't outlast the window, the error surfaces
|
|
309
|
+
// here. Wait for the cooldown to clear rather than counting it as a
|
|
310
|
+
// consecutive failure — but cap retries so we don't spin for hours
|
|
311
|
+
// on persistent quota exhaustion.
|
|
312
|
+
if (isTransientCooldownError(loopErr)) {
|
|
313
|
+
consecutiveCooldowns++;
|
|
314
|
+
const retryAfterMs = getCooldownRetryAfterMs(loopErr);
|
|
315
|
+
debugLog("autoLoop", {
|
|
316
|
+
phase: "cooldown-wait",
|
|
317
|
+
iteration,
|
|
318
|
+
consecutiveCooldowns,
|
|
319
|
+
retryAfterMs,
|
|
320
|
+
error: msg,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
if (consecutiveCooldowns > MAX_COOLDOWN_RETRIES) {
|
|
324
|
+
ctx.ui.notify(
|
|
325
|
+
`Auto-mode stopped: ${consecutiveCooldowns} consecutive credential cooldowns — rate limit or quota may be persistently exhausted.`,
|
|
326
|
+
"error",
|
|
327
|
+
);
|
|
328
|
+
await deps.stopAuto(
|
|
329
|
+
ctx,
|
|
330
|
+
pi,
|
|
331
|
+
`${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`,
|
|
332
|
+
);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const waitMs = (retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= 60_000)
|
|
337
|
+
? retryAfterMs + 500 // Use structured hint + small buffer
|
|
338
|
+
: COOLDOWN_FALLBACK_WAIT_MS;
|
|
339
|
+
ctx.ui.notify(
|
|
340
|
+
`Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`,
|
|
341
|
+
"warning",
|
|
342
|
+
);
|
|
343
|
+
await new Promise(resolve => setTimeout(resolve, waitMs));
|
|
344
|
+
continue; // Retry iteration without incrementing consecutiveErrors
|
|
345
|
+
}
|
|
346
|
+
|
|
303
347
|
consecutiveErrors++;
|
|
304
348
|
recentErrorMessages.push(msg.length > 120 ? msg.slice(0, 120) + "..." : msg);
|
|
305
349
|
debugLog("autoLoop", {
|
|
@@ -1183,6 +1183,8 @@ export async function runUnitPhase(
|
|
|
1183
1183
|
s.verbose,
|
|
1184
1184
|
s.autoModeStartModel,
|
|
1185
1185
|
sidecarItem ? undefined : { isRetry, previousTier },
|
|
1186
|
+
undefined,
|
|
1187
|
+
s.manualSessionModelOverride,
|
|
1186
1188
|
);
|
|
1187
1189
|
s.currentUnitRouting =
|
|
1188
1190
|
modelResult.routing as AutoSession["currentUnitRouting"];
|
|
@@ -87,6 +87,10 @@ export class AutoSession {
|
|
|
87
87
|
previousProjectRootEnv: string | null = null;
|
|
88
88
|
hadProjectRootEnv = false;
|
|
89
89
|
projectRootEnvCaptured = false;
|
|
90
|
+
previousMilestoneLockEnv: string | null = null;
|
|
91
|
+
hadMilestoneLockEnv = false;
|
|
92
|
+
milestoneLockEnvCaptured = false;
|
|
93
|
+
sessionMilestoneLock: string | null = null;
|
|
90
94
|
gitService: GitServiceImpl | null = null;
|
|
91
95
|
|
|
92
96
|
// ── Dispatch counters ────────────────────────────────────────────────────
|
|
@@ -107,6 +111,8 @@ export class AutoSession {
|
|
|
107
111
|
|
|
108
112
|
// ── Model state ──────────────────────────────────────────────────────────
|
|
109
113
|
autoModeStartModel: StartModel | null = null;
|
|
114
|
+
/** Explicit /gsd model pin captured at bootstrap (session-scoped policy override). */
|
|
115
|
+
manualSessionModelOverride: StartModel | null = null;
|
|
110
116
|
currentUnitModel: Model<Api> | null = null;
|
|
111
117
|
/** Fully-qualified model ID (provider/id) set after selectAndApplyModel + hook overrides (#2899). */
|
|
112
118
|
currentDispatchedModelId: string | null = null;
|
|
@@ -200,6 +206,10 @@ export class AutoSession {
|
|
|
200
206
|
this.previousProjectRootEnv = null;
|
|
201
207
|
this.hadProjectRootEnv = false;
|
|
202
208
|
this.projectRootEnvCaptured = false;
|
|
209
|
+
this.previousMilestoneLockEnv = null;
|
|
210
|
+
this.hadMilestoneLockEnv = false;
|
|
211
|
+
this.milestoneLockEnvCaptured = false;
|
|
212
|
+
this.sessionMilestoneLock = null;
|
|
203
213
|
this.gitService = null;
|
|
204
214
|
|
|
205
215
|
// Dispatch
|
|
@@ -214,6 +224,7 @@ export class AutoSession {
|
|
|
214
224
|
|
|
215
225
|
// Model
|
|
216
226
|
this.autoModeStartModel = null;
|
|
227
|
+
this.manualSessionModelOverride = null;
|
|
217
228
|
this.currentUnitModel = null;
|
|
218
229
|
this.currentDispatchedModelId = null;
|
|
219
230
|
this.originalModelId = null;
|
|
@@ -6,7 +6,13 @@
|
|
|
6
6
|
* or AutoContext dependency. State accessors are passed as callbacks.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
ExtensionContext,
|
|
11
|
+
ExtensionCommandContext,
|
|
12
|
+
SessionMessageEntry,
|
|
13
|
+
ReadonlyFooterDataProvider,
|
|
14
|
+
Theme,
|
|
15
|
+
} from "@gsd/pi-coding-agent";
|
|
10
16
|
import type { GSDState } from "./types.js";
|
|
11
17
|
import { getCurrentBranch } from "./worktree.js";
|
|
12
18
|
import { getActiveHook } from "./post-unit-hooks.js";
|
|
@@ -17,7 +23,6 @@ import {
|
|
|
17
23
|
resolveSliceFile,
|
|
18
24
|
} from "./paths.js";
|
|
19
25
|
import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
20
|
-
import { formatShortcut } from "./files.js";
|
|
21
26
|
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
22
27
|
import { execFileSync } from "node:child_process";
|
|
23
28
|
import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
|
|
@@ -38,6 +43,7 @@ import {
|
|
|
38
43
|
type RtkSessionSavings,
|
|
39
44
|
} from "../shared/rtk-session-stats.js";
|
|
40
45
|
import { logWarning } from "./workflow-logger.js";
|
|
46
|
+
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
41
47
|
|
|
42
48
|
// ─── UAT Slice Extraction ─────────────────────────────────────────────────────
|
|
43
49
|
|
|
@@ -358,12 +364,23 @@ function getLastCommit(basePath: string): { timeAgo: string; message: string } |
|
|
|
358
364
|
// ─── Footer Factory ───────────────────────────────────────────────────────────
|
|
359
365
|
|
|
360
366
|
/**
|
|
361
|
-
* Footer factory
|
|
362
|
-
*
|
|
363
|
-
* progress widget instead, so there's no gap or redundancy.
|
|
367
|
+
* Footer factory used by auto-mode.
|
|
368
|
+
* Keep footer minimal but preserve extension status context from setStatus().
|
|
364
369
|
*/
|
|
365
|
-
|
|
366
|
-
|
|
370
|
+
function sanitizeFooterStatus(text: string): string {
|
|
371
|
+
return text.replace(/\s+/g, " ").trim();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export const hideFooter = (_tui: unknown, theme: Theme, footerData: ReadonlyFooterDataProvider) => ({
|
|
375
|
+
render(width: number): string[] {
|
|
376
|
+
const extensionStatuses = footerData.getExtensionStatuses();
|
|
377
|
+
if (extensionStatuses.size === 0) return [];
|
|
378
|
+
const statusLine = Array.from(extensionStatuses.entries())
|
|
379
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
380
|
+
.map(([, text]) => sanitizeFooterStatus(text))
|
|
381
|
+
.join(" ");
|
|
382
|
+
return [truncateToWidth(theme.fg("dim", statusLine), width, theme.fg("dim", "..."))];
|
|
383
|
+
},
|
|
367
384
|
invalidate() {},
|
|
368
385
|
dispose() {},
|
|
369
386
|
});
|
|
@@ -646,14 +663,6 @@ export function updateProgressWidget(
|
|
|
646
663
|
: "";
|
|
647
664
|
lines.push(rightAlign(headerLeft, headerRight, width));
|
|
648
665
|
|
|
649
|
-
// Worktree/branch right-aligned below header
|
|
650
|
-
const branchLabel = worktreeName && cachedBranch
|
|
651
|
-
? `${worktreeName} (${cachedBranch})`
|
|
652
|
-
: cachedBranch ?? "";
|
|
653
|
-
if (branchLabel) {
|
|
654
|
-
lines.push(rightAlign("", theme.fg("dim", branchLabel), width));
|
|
655
|
-
}
|
|
656
|
-
|
|
657
666
|
// Show health signal details when degraded (yellow/red)
|
|
658
667
|
if (score.level !== "green" && score.signals.length > 0 && widgetMode !== "min") {
|
|
659
668
|
// Show up to 3 most relevant signals in compact form
|
|
@@ -917,15 +926,17 @@ export function updateProgressWidget(
|
|
|
917
926
|
// Hints line
|
|
918
927
|
const hintParts: string[] = [];
|
|
919
928
|
hintParts.push("esc pause");
|
|
920
|
-
hintParts.push(`${
|
|
929
|
+
hintParts.push(`${formattedShortcutPair("dashboard")} dashboard`);
|
|
930
|
+
hintParts.push(`${formattedShortcutPair("parallel")} parallel`);
|
|
921
931
|
const hintStr = theme.fg("dim", hintParts.join(" | "));
|
|
922
932
|
const commitStr = lastCommit
|
|
923
933
|
? theme.fg("dim", `${lastCommit.timeAgo} ago: ${commitMsg}`)
|
|
924
934
|
: "";
|
|
935
|
+
const locationStr = theme.fg("dim", widgetPwd);
|
|
925
936
|
if (commitStr) {
|
|
926
|
-
lines.push(rightAlign(`${pad}${commitStr}`, hintStr, width));
|
|
937
|
+
lines.push(rightAlign(`${pad}${locationStr} · ${commitStr}`, hintStr, width));
|
|
927
938
|
} else {
|
|
928
|
-
lines.push(rightAlign(
|
|
939
|
+
lines.push(rightAlign(`${pad}${locationStr}`, hintStr, width));
|
|
929
940
|
}
|
|
930
941
|
|
|
931
942
|
lines.push(...ui.bar());
|
|
@@ -14,6 +14,7 @@ import { classifyUnitComplexity, tierLabel } from "./complexity-classifier.js";
|
|
|
14
14
|
import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet, filterToolsForProvider } from "./model-router.js";
|
|
15
15
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
16
16
|
import { unitPhaseLabel } from "./auto-dashboard.js";
|
|
17
|
+
import { getSessionModelOverride } from "./session-model-override.js";
|
|
17
18
|
|
|
18
19
|
export interface ModelSelectionResult {
|
|
19
20
|
/** Routing metadata for metrics recording */
|
|
@@ -72,8 +73,15 @@ export async function selectAndApplyModel(
|
|
|
72
73
|
/** When false (interactive/guided-flow), skip dynamic routing and use the session model.
|
|
73
74
|
* Dynamic routing only applies in auto-mode where cost optimization is expected. (#3962) */
|
|
74
75
|
isAutoMode = true,
|
|
76
|
+
/** Explicit /gsd model pin captured at bootstrap for long-running auto loops. */
|
|
77
|
+
sessionModelOverride?: { provider: string; id: string } | null,
|
|
75
78
|
): Promise<ModelSelectionResult> {
|
|
76
|
-
const
|
|
79
|
+
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
80
|
+
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
81
|
+
: (sessionModelOverride ?? undefined);
|
|
82
|
+
const modelConfig = effectiveSessionModelOverride
|
|
83
|
+
? undefined
|
|
84
|
+
: resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode);
|
|
77
85
|
let routing: { tier: string; modelDowngraded: boolean } | null = null;
|
|
78
86
|
let appliedModel: Model<Api> | null = null;
|
|
79
87
|
|
|
@@ -85,6 +85,7 @@ import { sep as pathSep } from "node:path";
|
|
|
85
85
|
import { resolveProjectRootDbPath } from "./bootstrap/dynamic-tools.js";
|
|
86
86
|
import { resolveDefaultSessionModel, resolveDynamicRoutingConfig } from "./preferences-models.js";
|
|
87
87
|
import type { WorktreeResolver } from "./worktree-resolver.js";
|
|
88
|
+
import { getSessionModelOverride } from "./session-model-override.js";
|
|
88
89
|
|
|
89
90
|
export interface BootstrapDeps {
|
|
90
91
|
shouldUseWorktreeIsolation: () => boolean;
|
|
@@ -266,12 +267,17 @@ export async function bootstrapAutoSession(
|
|
|
266
267
|
// Capture the user's session model before guided-flow dispatch can apply a
|
|
267
268
|
// phase-specific planning model for a discuss turn (#2829).
|
|
268
269
|
//
|
|
269
|
-
//
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
270
|
+
// Precedence:
|
|
271
|
+
// 1) Explicit session override via /gsd model (this session)
|
|
272
|
+
// 2) GSD model preferences from PREFERENCES.md
|
|
273
|
+
// 3) Current session model from settings/session restore
|
|
274
|
+
//
|
|
275
|
+
// This preserves #3517 defaults while honoring explicit runtime model
|
|
276
|
+
// selection for subsequent /gsd runs in the same session.
|
|
277
|
+
const manualSessionOverride = getSessionModelOverride(ctx.sessionManager.getSessionId());
|
|
273
278
|
const preferredModel = resolveDefaultSessionModel(ctx.model?.provider);
|
|
274
|
-
const startModelSnapshot =
|
|
279
|
+
const startModelSnapshot = manualSessionOverride
|
|
280
|
+
?? preferredModel
|
|
275
281
|
?? (ctx.model
|
|
276
282
|
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
277
283
|
: null);
|
|
@@ -678,7 +684,7 @@ export async function bootstrapAutoSession(
|
|
|
678
684
|
}
|
|
679
685
|
|
|
680
686
|
// ── DB lifecycle ──
|
|
681
|
-
const gsdDbPath =
|
|
687
|
+
const gsdDbPath = resolveProjectRootDbPath(s.basePath);
|
|
682
688
|
const gsdDirPath = join(s.basePath, ".gsd");
|
|
683
689
|
if (existsSync(gsdDirPath) && !existsSync(gsdDbPath)) {
|
|
684
690
|
const hasDecisions = existsSync(join(gsdDirPath, "DECISIONS.md"));
|
|
@@ -731,6 +737,7 @@ export async function bootstrapAutoSession(
|
|
|
731
737
|
id: startModelSnapshot.id,
|
|
732
738
|
};
|
|
733
739
|
}
|
|
740
|
+
s.manualSessionModelOverride = manualSessionOverride ?? null;
|
|
734
741
|
|
|
735
742
|
// Apply worker model override from parallel orchestrator (#worker-model).
|
|
736
743
|
// GSD_WORKER_MODEL is injected by the coordinator when parallel.worker_model
|
|
@@ -92,7 +92,7 @@ export function clearInFlightTools(): void {
|
|
|
92
92
|
* handler. When these errors occur, retrying the same unit will produce the same
|
|
93
93
|
* failure, so the retry loop must be broken.
|
|
94
94
|
*/
|
|
95
|
-
const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Expected ',' or '\}' in JSON
|
|
95
|
+
const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON/i;
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
98
|
* Returns true if the error message indicates a tool invocation failure due to
|
|
@@ -2043,7 +2043,7 @@ export function mergeMilestoneToMain(
|
|
|
2043
2043
|
// 12. Remove worktree directory first (must happen before branch deletion)
|
|
2044
2044
|
try {
|
|
2045
2045
|
removeWorktree(originalBasePath_, milestoneId, {
|
|
2046
|
-
branch:
|
|
2046
|
+
branch: milestoneBranch,
|
|
2047
2047
|
deleteBranch: false,
|
|
2048
2048
|
});
|
|
2049
2049
|
} catch (err) {
|
|
@@ -165,6 +165,7 @@ import {
|
|
|
165
165
|
reconcileMergeState,
|
|
166
166
|
} from "./auto-recovery.js";
|
|
167
167
|
import { resolveDispatch, DISPATCH_RULES } from "./auto-dispatch.js";
|
|
168
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
168
169
|
import { initRegistry, convertDispatchRules } from "./rule-registry.js";
|
|
169
170
|
import { emitJournalEvent as _emitJournalEvent, type JournalEntry } from "./journal.js";
|
|
170
171
|
import {
|
|
@@ -272,6 +273,53 @@ function restoreProjectRootEnv(): void {
|
|
|
272
273
|
s.projectRootEnvCaptured = false;
|
|
273
274
|
}
|
|
274
275
|
|
|
276
|
+
function captureMilestoneLockEnv(milestoneId: string | null): void {
|
|
277
|
+
if (!s.milestoneLockEnvCaptured) {
|
|
278
|
+
s.hadMilestoneLockEnv = Object.prototype.hasOwnProperty.call(process.env, "GSD_MILESTONE_LOCK");
|
|
279
|
+
s.previousMilestoneLockEnv = process.env.GSD_MILESTONE_LOCK ?? null;
|
|
280
|
+
s.milestoneLockEnvCaptured = true;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (milestoneId) {
|
|
284
|
+
process.env.GSD_MILESTONE_LOCK = milestoneId;
|
|
285
|
+
} else {
|
|
286
|
+
delete process.env.GSD_MILESTONE_LOCK;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function restoreMilestoneLockEnv(): void {
|
|
291
|
+
if (!s.milestoneLockEnvCaptured) return;
|
|
292
|
+
|
|
293
|
+
if (s.hadMilestoneLockEnv && s.previousMilestoneLockEnv !== null) {
|
|
294
|
+
process.env.GSD_MILESTONE_LOCK = s.previousMilestoneLockEnv;
|
|
295
|
+
} else {
|
|
296
|
+
delete process.env.GSD_MILESTONE_LOCK;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
s.previousMilestoneLockEnv = null;
|
|
300
|
+
s.hadMilestoneLockEnv = false;
|
|
301
|
+
s.milestoneLockEnvCaptured = false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function startAutoDetached(
|
|
305
|
+
ctx: ExtensionCommandContext,
|
|
306
|
+
pi: ExtensionAPI,
|
|
307
|
+
base: string,
|
|
308
|
+
verboseMode: boolean,
|
|
309
|
+
options?: {
|
|
310
|
+
step?: boolean;
|
|
311
|
+
interrupted?: InterruptedSessionAssessment;
|
|
312
|
+
milestoneLock?: string | null;
|
|
313
|
+
},
|
|
314
|
+
): void {
|
|
315
|
+
void startAuto(ctx, pi, base, verboseMode, options).catch((err) => {
|
|
316
|
+
const message = getErrorMessage(err);
|
|
317
|
+
ctx.ui.notify(`Auto-start failed: ${message}`, "error");
|
|
318
|
+
logWarning("engine", `auto start error: ${message}`, { file: "auto.ts" });
|
|
319
|
+
debugLog("auto-start-failed", { error: message });
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
275
323
|
export function shouldUseWorktreeIsolation(): boolean {
|
|
276
324
|
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
277
325
|
if (prefs?.isolation === "worktree") return true;
|
|
@@ -549,11 +597,13 @@ function buildSnapshotOpts(
|
|
|
549
597
|
_unitType: string,
|
|
550
598
|
_unitId: string,
|
|
551
599
|
): {
|
|
600
|
+
autoSessionKey?: string;
|
|
552
601
|
continueHereFired?: boolean;
|
|
553
602
|
promptCharCount?: number;
|
|
554
603
|
baselineCharCount?: number;
|
|
555
604
|
} & Record<string, unknown> {
|
|
556
605
|
return {
|
|
606
|
+
...(s.autoStartTime > 0 ? { autoSessionKey: String(s.autoStartTime) } : {}),
|
|
557
607
|
promptCharCount: s.lastPromptCharCount,
|
|
558
608
|
baselineCharCount: s.lastBaselineCharCount,
|
|
559
609
|
...(s.currentUnitRouting ?? {}),
|
|
@@ -574,6 +624,7 @@ function handleLostSessionLock(
|
|
|
574
624
|
s.paused = false;
|
|
575
625
|
clearUnitTimeout();
|
|
576
626
|
restoreProjectRootEnv();
|
|
627
|
+
restoreMilestoneLockEnv();
|
|
577
628
|
deregisterSigtermHandler();
|
|
578
629
|
clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
|
|
579
630
|
const base = lockBase();
|
|
@@ -610,6 +661,7 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
|
|
|
610
661
|
s.active = false;
|
|
611
662
|
clearUnitTimeout();
|
|
612
663
|
restoreProjectRootEnv();
|
|
664
|
+
restoreMilestoneLockEnv();
|
|
613
665
|
|
|
614
666
|
// Clear crash lock and release session lock so the next `/gsd next` does
|
|
615
667
|
// not see a stale lock with the current PID and treat it as a "remote"
|
|
@@ -880,6 +932,7 @@ export async function stopAuto(
|
|
|
880
932
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
881
933
|
ctx?.ui.setFooter(undefined);
|
|
882
934
|
restoreProjectRootEnv();
|
|
935
|
+
restoreMilestoneLockEnv();
|
|
883
936
|
|
|
884
937
|
// Reset all session state in one call
|
|
885
938
|
s.reset();
|
|
@@ -933,6 +986,7 @@ export async function pauseAuto(
|
|
|
933
986
|
activeEngineId: s.activeEngineId,
|
|
934
987
|
activeRunDir: s.activeRunDir,
|
|
935
988
|
autoStartTime: s.autoStartTime,
|
|
989
|
+
milestoneLock: s.sessionMilestoneLock ?? undefined,
|
|
936
990
|
};
|
|
937
991
|
const runtimeDir = join(gsdRoot(s.originalBasePath || s.basePath), "runtime");
|
|
938
992
|
mkdirSync(runtimeDir, { recursive: true });
|
|
@@ -971,6 +1025,7 @@ export async function pauseAuto(
|
|
|
971
1025
|
s.active = false;
|
|
972
1026
|
s.paused = true;
|
|
973
1027
|
restoreProjectRootEnv();
|
|
1028
|
+
restoreMilestoneLockEnv();
|
|
974
1029
|
s.pendingVerificationRetry = null;
|
|
975
1030
|
s.verificationRetryCount.clear();
|
|
976
1031
|
ctx?.ui.setStatus("gsd-auto", "paused");
|
|
@@ -1154,6 +1209,7 @@ export async function startAuto(
|
|
|
1154
1209
|
options?: {
|
|
1155
1210
|
step?: boolean;
|
|
1156
1211
|
interrupted?: InterruptedSessionAssessment;
|
|
1212
|
+
milestoneLock?: string | null;
|
|
1157
1213
|
},
|
|
1158
1214
|
): Promise<void> {
|
|
1159
1215
|
if (s.active) {
|
|
@@ -1163,6 +1219,12 @@ export async function startAuto(
|
|
|
1163
1219
|
|
|
1164
1220
|
const requestedStepMode = options?.step ?? false;
|
|
1165
1221
|
const interruptedAssessment = options?.interrupted ?? null;
|
|
1222
|
+
if (options?.milestoneLock !== undefined) {
|
|
1223
|
+
s.sessionMilestoneLock = options.milestoneLock ?? null;
|
|
1224
|
+
}
|
|
1225
|
+
if (s.sessionMilestoneLock) {
|
|
1226
|
+
captureMilestoneLockEnv(s.sessionMilestoneLock);
|
|
1227
|
+
}
|
|
1166
1228
|
|
|
1167
1229
|
// Escape stale worktree cwd from a previous milestone (#608).
|
|
1168
1230
|
base = escapeStaleWorktree(base);
|
|
@@ -1194,6 +1256,7 @@ export async function startAuto(
|
|
|
1194
1256
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1195
1257
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1196
1258
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1259
|
+
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1197
1260
|
s.paused = true;
|
|
1198
1261
|
try { unlinkSync(pausedPath); } catch (e) { logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" }); }
|
|
1199
1262
|
ctx.ui.notify(
|
|
@@ -1228,6 +1291,7 @@ export async function startAuto(
|
|
|
1228
1291
|
s.pausedUnitType = meta.unitType ?? null;
|
|
1229
1292
|
s.pausedUnitId = meta.unitId ?? null;
|
|
1230
1293
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1294
|
+
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1231
1295
|
s.paused = true;
|
|
1232
1296
|
try { unlinkSync(pausedPath); } catch (e) { logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" }); }
|
|
1233
1297
|
ctx.ui.notify(
|
|
@@ -1247,6 +1311,10 @@ export async function startAuto(
|
|
|
1247
1311
|
if (!s.autoStartTime || s.autoStartTime <= 0) s.autoStartTime = Date.now();
|
|
1248
1312
|
}
|
|
1249
1313
|
|
|
1314
|
+
if (s.sessionMilestoneLock) {
|
|
1315
|
+
captureMilestoneLockEnv(s.sessionMilestoneLock);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1250
1318
|
if (!s.paused) {
|
|
1251
1319
|
s.stepMode = requestedStepMode;
|
|
1252
1320
|
}
|
|
@@ -121,6 +121,8 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
121
121
|
return { cancel: true };
|
|
122
122
|
}
|
|
123
123
|
const basePath = process.cwd();
|
|
124
|
+
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
125
|
+
await ensureDbOpen();
|
|
124
126
|
const state = await deriveState(basePath);
|
|
125
127
|
if (!state.activeMilestone || !state.activeSlice || !state.activeTask) return;
|
|
126
128
|
if (state.phase !== "executing") return;
|
|
@@ -1,79 +1,101 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
4
|
+
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
5
5
|
import { Key } from "@gsd/pi-tui";
|
|
6
6
|
|
|
7
7
|
import { GSDDashboardOverlay } from "../dashboard-overlay.js";
|
|
8
8
|
import { GSDNotificationOverlay } from "../notification-overlay.js";
|
|
9
9
|
import { ParallelMonitorOverlay } from "../parallel-monitor-overlay.js";
|
|
10
|
+
import { GSD_SHORTCUTS } from "../shortcut-defs.js";
|
|
10
11
|
import { projectRoot } from "../commands/context.js";
|
|
11
12
|
import { shortcutDesc } from "../../shared/mod.js";
|
|
12
13
|
|
|
13
14
|
export function registerShortcuts(pi: ExtensionAPI): void {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
15
|
+
const overlayOptions = {
|
|
16
|
+
width: "90%",
|
|
17
|
+
minWidth: 80,
|
|
18
|
+
maxHeight: "92%",
|
|
19
|
+
anchor: "center",
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
const openDashboardOverlay = async (ctx: ExtensionContext) => {
|
|
23
|
+
const basePath = projectRoot();
|
|
24
|
+
if (!existsSync(join(basePath, ".gsd"))) {
|
|
25
|
+
ctx.ui.notify("No .gsd/ directory found. Run /gsd to start.", "info");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await ctx.ui.custom<boolean>(
|
|
29
|
+
(tui, theme, _kb, done) => new GSDDashboardOverlay(tui, theme, () => done(true)),
|
|
30
|
+
{
|
|
31
|
+
overlay: true,
|
|
32
|
+
overlayOptions,
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const openNotificationsOverlay = async (ctx: ExtensionContext) => {
|
|
38
|
+
await ctx.ui.custom<boolean>(
|
|
39
|
+
(tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)),
|
|
40
|
+
{
|
|
41
|
+
overlay: true,
|
|
42
|
+
overlayOptions: {
|
|
43
|
+
width: "80%",
|
|
44
|
+
minWidth: 60,
|
|
45
|
+
maxHeight: "88%",
|
|
46
|
+
anchor: "center",
|
|
47
|
+
backdrop: true,
|
|
32
48
|
},
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const openParallelOverlay = async (ctx: ExtensionContext) => {
|
|
54
|
+
const basePath = projectRoot();
|
|
55
|
+
const parallelDir = join(basePath, ".gsd", "parallel");
|
|
56
|
+
if (!existsSync(parallelDir)) {
|
|
57
|
+
ctx.ui.notify("No parallel workers found. Run /gsd parallel start first.", "info");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await ctx.ui.custom<boolean>(
|
|
61
|
+
(tui, theme, _kb, done) => new ParallelMonitorOverlay(tui, theme, () => done(true), basePath),
|
|
62
|
+
{
|
|
63
|
+
overlay: true,
|
|
64
|
+
overlayOptions,
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.dashboard.key), {
|
|
70
|
+
description: shortcutDesc(GSD_SHORTCUTS.dashboard.action, GSD_SHORTCUTS.dashboard.command),
|
|
71
|
+
handler: openDashboardOverlay,
|
|
35
72
|
});
|
|
36
73
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
(tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)),
|
|
42
|
-
{
|
|
43
|
-
overlay: true,
|
|
44
|
-
overlayOptions: {
|
|
45
|
-
width: "80%",
|
|
46
|
-
minWidth: 60,
|
|
47
|
-
maxHeight: "88%",
|
|
48
|
-
anchor: "center",
|
|
49
|
-
backdrop: true,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
);
|
|
53
|
-
},
|
|
74
|
+
// Fallback for terminals where Ctrl+Alt letter chords are not forwarded reliably.
|
|
75
|
+
pi.registerShortcut(Key.ctrlShift(GSD_SHORTCUTS.dashboard.key), {
|
|
76
|
+
description: shortcutDesc(`${GSD_SHORTCUTS.dashboard.action} (fallback)`, GSD_SHORTCUTS.dashboard.command),
|
|
77
|
+
handler: openDashboardOverlay,
|
|
54
78
|
});
|
|
55
79
|
|
|
56
|
-
pi.registerShortcut(Key.ctrlAlt(
|
|
57
|
-
description: shortcutDesc(
|
|
58
|
-
handler:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
);
|
|
77
|
-
},
|
|
80
|
+
pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.notifications.key), {
|
|
81
|
+
description: shortcutDesc(GSD_SHORTCUTS.notifications.action, GSD_SHORTCUTS.notifications.command),
|
|
82
|
+
handler: openNotificationsOverlay,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Fallback for terminals where Ctrl+Alt letter chords are not forwarded reliably.
|
|
86
|
+
pi.registerShortcut(Key.ctrlShift(GSD_SHORTCUTS.notifications.key), {
|
|
87
|
+
description: shortcutDesc(`${GSD_SHORTCUTS.notifications.action} (fallback)`, GSD_SHORTCUTS.notifications.command),
|
|
88
|
+
handler: openNotificationsOverlay,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
pi.registerShortcut(Key.ctrlAlt(GSD_SHORTCUTS.parallel.key), {
|
|
92
|
+
description: shortcutDesc(GSD_SHORTCUTS.parallel.action, GSD_SHORTCUTS.parallel.command),
|
|
93
|
+
handler: openParallelOverlay,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Fallback for terminals where Ctrl+Alt letter chords are not forwarded reliably.
|
|
97
|
+
pi.registerShortcut(Key.ctrlShift(GSD_SHORTCUTS.parallel.key), {
|
|
98
|
+
description: shortcutDesc(`${GSD_SHORTCUTS.parallel.action} (fallback)`, GSD_SHORTCUTS.parallel.command),
|
|
99
|
+
handler: openParallelOverlay,
|
|
78
100
|
});
|
|
79
101
|
}
|