gsd-pi 2.51.0-dev.7d435fe → 2.51.0-dev.859cedb

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.
Files changed (53) hide show
  1. package/dist/resources/extensions/async-jobs/job-manager.js +4 -1
  2. package/dist/resources/extensions/gsd/auto/phases.js +6 -0
  3. package/dist/resources/extensions/gsd/auto.js +4 -2
  4. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +11 -2
  5. package/dist/web/standalone/.next/BUILD_ID +1 -1
  6. package/dist/web/standalone/.next/app-path-routes-manifest.json +23 -23
  7. package/dist/web/standalone/.next/build-manifest.json +2 -2
  8. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  9. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  10. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  11. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  18. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/index.html +1 -1
  26. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app-paths-manifest.json +23 -23
  33. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  34. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  35. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  36. package/package.json +1 -1
  37. package/packages/mcp-server/README.md +202 -0
  38. package/packages/mcp-server/package.json +36 -0
  39. package/packages/mcp-server/src/cli.ts +68 -0
  40. package/packages/mcp-server/src/index.ts +14 -0
  41. package/packages/mcp-server/src/mcp-server.test.ts +628 -0
  42. package/packages/mcp-server/src/server.ts +278 -0
  43. package/packages/mcp-server/src/session-manager.ts +328 -0
  44. package/packages/mcp-server/src/types.ts +107 -0
  45. package/packages/mcp-server/tsconfig.json +24 -0
  46. package/packages/rpc-client/package.json +20 -0
  47. package/src/resources/extensions/async-jobs/job-manager.ts +4 -1
  48. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  49. package/src/resources/extensions/gsd/auto.ts +5 -2
  50. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +11 -2
  51. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +1 -1
  52. /package/dist/web/standalone/.next/static/{RqOU-jOv9uZ1Q03P6L6nn → hFpSn70hOfLw7RhKUl_eK}/_buildManifest.js +0 -0
  53. /package/dist/web/standalone/.next/static/{RqOU-jOv9uZ1Q03P6L6nn → hFpSn70hOfLw7RhKUl_eK}/_ssgManifest.js +0 -0
@@ -0,0 +1,107 @@
1
+ /**
2
+ * MCP Server types — session lifecycle and orchestration.
3
+ */
4
+
5
+ import type { RpcClient, SdkAgentEvent, RpcCostUpdateEvent, RpcExtensionUIRequest } from '@gsd/rpc-client';
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Session Status
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export type SessionStatus = 'starting' | 'running' | 'blocked' | 'completed' | 'error' | 'cancelled';
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Managed Session
15
+ // ---------------------------------------------------------------------------
16
+
17
+ export interface ManagedSession {
18
+ /** Unique session ID returned from RpcClient.init() */
19
+ sessionId: string;
20
+
21
+ /** Absolute path to the project directory */
22
+ projectDir: string;
23
+
24
+ /** Current lifecycle status */
25
+ status: SessionStatus;
26
+
27
+ /** The RpcClient instance managing the agent process */
28
+ client: RpcClient;
29
+
30
+ /** Ring buffer of recent events (capped at MAX_EVENTS) */
31
+ events: SdkAgentEvent[];
32
+
33
+ /** Pending blocker requiring user response, if any */
34
+ pendingBlocker: PendingBlocker | null;
35
+
36
+ /** Cumulative cost tracking (max pattern per K004) */
37
+ cost: CostAccumulator;
38
+
39
+ /** Session start timestamp */
40
+ startTime: number;
41
+
42
+ /** Error message if status is 'error' */
43
+ error?: string;
44
+
45
+ /** Cleanup function to unsubscribe from events */
46
+ unsubscribe?: () => void;
47
+ }
48
+
49
+ // ---------------------------------------------------------------------------
50
+ // Pending Blocker
51
+ // ---------------------------------------------------------------------------
52
+
53
+ export interface PendingBlocker {
54
+ /** The extension_ui_request id */
55
+ id: string;
56
+
57
+ /** The request method (e.g. 'select', 'confirm', 'input') */
58
+ method: string;
59
+
60
+ /** Human-readable message or title */
61
+ message: string;
62
+
63
+ /** Full event payload for inspection */
64
+ event: RpcExtensionUIRequest;
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Cost Accumulator (K004 — cumulative-max)
69
+ // ---------------------------------------------------------------------------
70
+
71
+ export interface CostAccumulator {
72
+ totalCost: number;
73
+ tokens: {
74
+ input: number;
75
+ output: number;
76
+ cacheRead: number;
77
+ cacheWrite: number;
78
+ };
79
+ }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Execute Options
83
+ // ---------------------------------------------------------------------------
84
+
85
+ export interface ExecuteOptions {
86
+ /** Command to send after '/gsd auto' (default: none) */
87
+ command?: string;
88
+
89
+ /** Model ID override */
90
+ model?: string;
91
+
92
+ /** Run in bare mode (skip user config) */
93
+ bare?: boolean;
94
+
95
+ /** Path to CLI binary (overrides GSD_CLI_PATH and which resolution) */
96
+ cliPath?: string;
97
+ }
98
+
99
+ // ---------------------------------------------------------------------------
100
+ // Constants
101
+ // ---------------------------------------------------------------------------
102
+
103
+ /** Maximum number of events kept in the ring buffer */
104
+ export const MAX_EVENTS = 50;
105
+
106
+ /** Timeout for RpcClient initialization (ms) */
107
+ export const INIT_TIMEOUT_MS = 30_000;
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2024",
4
+ "module": "Node16",
5
+ "lib": ["ES2024"],
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "declaration": true,
11
+ "declarationMap": true,
12
+ "sourceMap": true,
13
+ "inlineSources": true,
14
+ "inlineSourceMap": false,
15
+ "moduleResolution": "Node16",
16
+ "resolveJsonModule": true,
17
+ "allowImportingTsExtensions": false,
18
+ "types": ["node"],
19
+ "outDir": "./dist",
20
+ "rootDir": "./src"
21
+ },
22
+ "include": ["src/**/*.ts"],
23
+ "exclude": ["node_modules", "dist", "**/*.d.ts", "src/**/*.d.ts"]
24
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@gsd/rpc-client",
3
+ "version": "2.51.0",
4
+ "description": "Standalone RPC client SDK for GSD — zero internal dependencies",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "engines": {
18
+ "node": ">=22.0.0"
19
+ }
20
+ }
@@ -172,7 +172,10 @@ export class AsyncJobManager {
172
172
 
173
173
  private deliverResult(job: Job): void {
174
174
  if (!this.onJobComplete) return;
175
- this.onJobComplete(job);
175
+ // Defer delivery by one microtask so await_job's .then() chain runs first
176
+ // and can set job.awaited = true before onJobComplete checks it (#2762).
177
+ const cb = this.onJobComplete;
178
+ queueMicrotask(() => cb(job));
176
179
  }
177
180
 
178
181
  private scheduleEviction(id: string): void {
@@ -1069,6 +1069,12 @@ export async function runUnitPhase(
1069
1069
  }
1070
1070
 
1071
1071
  if (unitResult.status === "cancelled") {
1072
+ // Provider-error pause: pauseAuto already handled cleanup and scheduled
1073
+ // recovery. Don't hard-stop — just break out of the loop (#2762).
1074
+ if (unitResult.errorContext?.category === "provider") {
1075
+ debugLog("autoLoop", { phase: "exit", reason: "provider-pause", isTransient: unitResult.errorContext.isTransient });
1076
+ return { action: "break", reason: "provider-pause" };
1077
+ }
1072
1078
  ctx.ui.notify(
1073
1079
  `Session creation timed out or was cancelled for ${unitType} ${unitId}. Will retry.`,
1074
1080
  "warning",
@@ -186,7 +186,7 @@ import {
186
186
  postUnitPostVerification,
187
187
  } from "./auto-post-unit.js";
188
188
  import { bootstrapAutoSession, type BootstrapDeps } from "./auto-start.js";
189
- import { autoLoop, resolveAgentEnd, resolveAgentEndCancelled, _resetPendingResolve, isSessionSwitchInFlight, type LoopDeps } from "./auto-loop.js";
189
+ import { autoLoop, resolveAgentEnd, resolveAgentEndCancelled, _resetPendingResolve, isSessionSwitchInFlight, type LoopDeps, type ErrorContext } from "./auto-loop.js";
190
190
  import {
191
191
  WorktreeResolver,
192
192
  type WorktreeResolverDeps,
@@ -800,11 +800,14 @@ export async function stopAuto(
800
800
  export async function pauseAuto(
801
801
  ctx?: ExtensionContext,
802
802
  _pi?: ExtensionAPI,
803
+ _errorContext?: ErrorContext,
803
804
  ): Promise<void> {
804
805
  if (!s.active) return;
805
806
  clearUnitTimeout();
806
807
  // Unblock any pending unit promise so the auto-loop is not orphaned.
807
- resolveAgentEndCancelled();
808
+ // Pass errorContext so runUnitPhase can distinguish user-initiated pause
809
+ // from provider-error pause and avoid hard-stopping (#2762).
810
+ resolveAgentEndCancelled(_errorContext);
808
811
 
809
812
  s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
810
813
 
@@ -33,7 +33,12 @@ async function pauseTransientWithBackoff(
33
33
  if (!allowAutoResume) {
34
34
  ctx.ui.notify(`Transient provider errors persisted after ${MAX_TRANSIENT_AUTO_RESUMES} auto-resume attempts. Pausing for manual review.`, "warning");
35
35
  }
36
- await pauseAutoForProviderError(ctx.ui, errorDetail, () => pauseAuto(ctx, pi), {
36
+ await pauseAutoForProviderError(ctx.ui, errorDetail, () => pauseAuto(ctx, pi, {
37
+ message: `Provider error: ${errorDetail}`,
38
+ category: "provider",
39
+ isTransient: allowAutoResume,
40
+ retryAfterMs,
41
+ }), {
37
42
  isRateLimit,
38
43
  isTransient: allowAutoResume,
39
44
  retryAfterMs,
@@ -161,7 +166,11 @@ export async function handleAgentEnd(
161
166
  }
162
167
 
163
168
  // --- Permanent / unknown: pause indefinitely ---
164
- await pauseAutoForProviderError(ctx.ui, errorDetail, () => pauseAuto(ctx, pi), {
169
+ await pauseAutoForProviderError(ctx.ui, errorDetail, () => pauseAuto(ctx, pi, {
170
+ message: `Provider error: ${errorDetail}`,
171
+ category: "provider",
172
+ isTransient: false,
173
+ }), {
165
174
  isRateLimit: false,
166
175
  isTransient: false,
167
176
  retryAfterMs: 0,
@@ -102,7 +102,7 @@ test("pauseAuto calls resolveAgentEndCancelled to unblock the loop", () => {
102
102
  const fnBlock = source.slice(fnIdx, source.indexOf("\n/**\n * Build", fnIdx + 100));
103
103
 
104
104
  assert.ok(
105
- fnBlock.includes("resolveAgentEndCancelled()"),
105
+ fnBlock.includes("resolveAgentEndCancelled("),
106
106
  "pauseAuto must call resolveAgentEndCancelled to unblock the auto-loop promise",
107
107
  );
108
108
  });