gsd-pi 2.69.0 → 2.70.0-dev.8f4d92b
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/loader.js +4 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +150 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +7 -3
- package/dist/resources/extensions/gsd/auto.js +12 -8
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -2
- package/dist/resources/extensions/gsd/commands-cmux.js +30 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +22 -8
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +12 -0
- package/dist/resources/extensions/gsd/doctor-format.js +2 -0
- package/dist/resources/extensions/gsd/guided-flow.js +19 -9
- package/dist/resources/extensions/gsd/pre-execution-checks.js +2 -2
- package/dist/resources/extensions/gsd/workflow-mcp.js +64 -6
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +30 -27
- package/dist/update-cmd.js +3 -11
- 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 +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/daemon/src/orchestrator.ts +9 -84
- package/packages/mcp-server/README.md +25 -3
- package/packages/mcp-server/dist/cli.d.ts +0 -1
- package/packages/mcp-server/dist/cli.d.ts.map +1 -1
- package/packages/mcp-server/dist/cli.js +4 -2
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts +32 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +118 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/tool-credentials.d.ts +6 -0
- package/packages/mcp-server/dist/tool-credentials.d.ts.map +1 -0
- package/packages/mcp-server/dist/tool-credentials.js +90 -0
- package/packages/mcp-server/dist/tool-credentials.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts +3 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +308 -4
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/cli.ts +5 -3
- package/packages/mcp-server/src/import-candidates.test.ts +48 -0
- package/packages/mcp-server/src/mcp-server.test.ts +85 -1
- package/packages/mcp-server/src/server.ts +188 -1
- package/packages/mcp-server/src/tool-credentials.test.ts +95 -0
- package/packages/mcp-server/src/tool-credentials.ts +97 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +32 -25
- package/packages/mcp-server/src/workflow-tools.ts +398 -2
- package/packages/pi-agent-core/dist/agent.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +3 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/src/agent.test.ts +82 -0
- package/packages/pi-agent-core/src/agent.ts +12 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +1 -23
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/index.d.ts +3 -2
- package/packages/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/index.js +3 -5
- package/packages/pi-ai/dist/utils/oauth/index.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic.ts +1 -31
- package/packages/pi-ai/src/utils/oauth/index.ts +3 -5
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +10 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +8 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +227 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +172 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +7 -3
- package/src/resources/extensions/gsd/auto.ts +12 -8
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +9 -5
- package/src/resources/extensions/gsd/commands-cmux.ts +32 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +22 -7
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +14 -0
- package/src/resources/extensions/gsd/doctor-format.ts +1 -0
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/guided-flow.ts +23 -8
- package/src/resources/extensions/gsd/pre-execution-checks.ts +2 -2
- package/src/resources/extensions/gsd/tests/cmux.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +87 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +48 -7
- package/src/resources/extensions/gsd/workflow-mcp.ts +74 -5
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/packages/pi-ai/dist/utils/oauth/anthropic.d.ts +0 -17
- package/packages/pi-ai/dist/utils/oauth/anthropic.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/anthropic.js +0 -106
- package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/anthropic.ts +0 -140
- /package/dist/web/standalone/.next/static/{DrWdzskk28E5Qz-Wjw1mj → j_Ae_qOKzzIlA6oFOxVx4}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{DrWdzskk28E5Qz-Wjw1mj → j_Ae_qOKzzIlA6oFOxVx4}/_ssgManifest.js +0 -0
|
@@ -9,10 +9,11 @@ import { deriveState, isValidationTerminal } from "../state.ts";
|
|
|
9
9
|
import { resolveExpectedArtifactPath, diagnoseExpectedArtifact } from "../auto-artifact-paths.ts";
|
|
10
10
|
import { verifyExpectedArtifact, buildLoopRemediationSteps } from "../auto-recovery.ts";
|
|
11
11
|
import { resolveDispatch, type DispatchContext } from "../auto-dispatch.ts";
|
|
12
|
-
import { buildValidateMilestonePrompt } from "../auto-prompts.ts";
|
|
12
|
+
import { buildCompleteMilestonePrompt, buildValidateMilestonePrompt } from "../auto-prompts.ts";
|
|
13
13
|
import type { GSDState } from "../types.ts";
|
|
14
14
|
import { clearPathCache } from "../paths.ts";
|
|
15
15
|
import { clearParseCache } from "../files.ts";
|
|
16
|
+
import { closeDatabase, insertMilestone, insertSlice, openDatabase } from "../gsd-db.ts";
|
|
16
17
|
|
|
17
18
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -25,9 +26,15 @@ function makeTmpBase(): string {
|
|
|
25
26
|
function cleanup(base: string): void {
|
|
26
27
|
clearPathCache();
|
|
27
28
|
clearParseCache();
|
|
29
|
+
closeDatabase();
|
|
28
30
|
try { rmSync(base, { recursive: true, force: true }); } catch { /* */ }
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
function openTestDb(base: string): void {
|
|
34
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
35
|
+
assert.equal(openDatabase(dbPath), true, "test DB should open");
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
function writeRoadmap(base: string, mid: string, content: string): void {
|
|
32
39
|
const dir = join(base, ".gsd", "milestones", mid);
|
|
33
40
|
mkdirSync(dir, { recursive: true });
|
|
@@ -218,6 +225,85 @@ test("buildValidateMilestonePrompt inlines ASSESSMENT evidence instead of UAT sp
|
|
|
218
225
|
}
|
|
219
226
|
});
|
|
220
227
|
|
|
228
|
+
test("buildCompleteMilestonePrompt skips skipped slices from DB-backed summary inlining", async () => {
|
|
229
|
+
const base = makeTmpBase();
|
|
230
|
+
try {
|
|
231
|
+
writeRoadmap(base, "M001", `# M001: Test Milestone
|
|
232
|
+
|
|
233
|
+
## Vision
|
|
234
|
+
Test
|
|
235
|
+
|
|
236
|
+
## Success Criteria
|
|
237
|
+
- It works
|
|
238
|
+
|
|
239
|
+
## Slices
|
|
240
|
+
|
|
241
|
+
- [x] **S01: First slice** \`risk:low\` \`depends:[]\`
|
|
242
|
+
> Done
|
|
243
|
+
- [ ] **S02: Skipped slice** \`risk:low\` \`depends:[]\`
|
|
244
|
+
> Intentionally skipped
|
|
245
|
+
|
|
246
|
+
## Boundary Map
|
|
247
|
+
|
|
248
|
+
| From | To | Produces | Consumes |
|
|
249
|
+
|------|-----|----------|----------|
|
|
250
|
+
| S01 | terminal | output | nothing |
|
|
251
|
+
`);
|
|
252
|
+
openTestDb(base);
|
|
253
|
+
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
254
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [], sequence: 1 });
|
|
255
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [], sequence: 2 });
|
|
256
|
+
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
257
|
+
|
|
258
|
+
const prompt = await buildCompleteMilestonePrompt("M001", "Test Milestone", base);
|
|
259
|
+
assert.match(prompt, /S01 Summary/i, "prompt should inline non-skipped slice summaries");
|
|
260
|
+
assert.doesNotMatch(prompt, /### S02 Summary/i, "prompt should not inline skipped slice summaries");
|
|
261
|
+
assert.doesNotMatch(prompt, /not found — file does not exist yet/i, "prompt should not emit skipped-slice missing-file placeholders");
|
|
262
|
+
} finally {
|
|
263
|
+
cleanup(base);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("buildValidateMilestonePrompt skips skipped slices from DB-backed summary inlining", async () => {
|
|
268
|
+
const base = makeTmpBase();
|
|
269
|
+
try {
|
|
270
|
+
writeRoadmap(base, "M001", `# M001: Test Milestone
|
|
271
|
+
|
|
272
|
+
## Vision
|
|
273
|
+
Test
|
|
274
|
+
|
|
275
|
+
## Success Criteria
|
|
276
|
+
- It works
|
|
277
|
+
|
|
278
|
+
## Slices
|
|
279
|
+
|
|
280
|
+
- [x] **S01: First slice** \`risk:low\` \`depends:[]\`
|
|
281
|
+
> Done
|
|
282
|
+
- [ ] **S02: Skipped slice** \`risk:low\` \`depends:[]\`
|
|
283
|
+
> Intentionally skipped
|
|
284
|
+
|
|
285
|
+
## Boundary Map
|
|
286
|
+
|
|
287
|
+
| From | To | Produces | Consumes |
|
|
288
|
+
|------|-----|----------|----------|
|
|
289
|
+
| S01 | terminal | output | nothing |
|
|
290
|
+
`);
|
|
291
|
+
openTestDb(base);
|
|
292
|
+
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
293
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [], sequence: 1 });
|
|
294
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [], sequence: 2 });
|
|
295
|
+
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
296
|
+
writeSliceAssessment(base, "M001", "S01", "---\nverdict: PASS\n---\n# Assessment\nEvidence captured.");
|
|
297
|
+
|
|
298
|
+
const prompt = await buildValidateMilestonePrompt("M001", "Test Milestone", base);
|
|
299
|
+
assert.match(prompt, /S01 Summary/i, "prompt should inline non-skipped slice summaries");
|
|
300
|
+
assert.doesNotMatch(prompt, /### S02 Summary/i, "prompt should not inline skipped slice summaries");
|
|
301
|
+
assert.doesNotMatch(prompt, /not found — file does not exist yet/i, "prompt should not emit skipped-slice missing-file placeholders");
|
|
302
|
+
} finally {
|
|
303
|
+
cleanup(base);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
221
307
|
// ─── Dispatch rule ────────────────────────────────────────────────────────
|
|
222
308
|
|
|
223
309
|
test("dispatch rule matches validating-milestone phase", async () => {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getWorkflowTransportSupportError,
|
|
14
14
|
getRequiredWorkflowToolsForAutoUnit,
|
|
15
15
|
getRequiredWorkflowToolsForGuidedUnit,
|
|
16
|
+
supportsStructuredQuestions,
|
|
16
17
|
usesWorkflowMcpTransport,
|
|
17
18
|
} from "../workflow-mcp.ts";
|
|
18
19
|
|
|
@@ -141,7 +142,11 @@ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the
|
|
|
141
142
|
assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
|
|
142
143
|
assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
|
|
143
144
|
assert.equal(typeof launch?.args?.[0], "string");
|
|
144
|
-
assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\]dist[\/\\]cli\.js$/);
|
|
145
|
+
assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\](dist[\/\\]cli\.js|src[\/\\]cli\.ts)$/);
|
|
146
|
+
if ((launch?.args?.[0] ?? "").endsWith(".ts")) {
|
|
147
|
+
assert.match(launch?.env?.NODE_OPTIONS ?? "", /--experimental-strip-types/);
|
|
148
|
+
assert.match(launch?.env?.NODE_OPTIONS ?? "", /resolve-ts\.mjs/);
|
|
149
|
+
}
|
|
145
150
|
});
|
|
146
151
|
|
|
147
152
|
test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the package without env hints", () => {
|
|
@@ -154,7 +159,11 @@ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the
|
|
|
154
159
|
assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
|
|
155
160
|
assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
|
|
156
161
|
assert.equal(typeof launch?.args?.[0], "string");
|
|
157
|
-
assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\]dist[\/\\]cli\.js$/);
|
|
162
|
+
assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\](dist[\/\\]cli\.js|src[\/\\]cli\.ts)$/);
|
|
163
|
+
if ((launch?.args?.[0] ?? "").endsWith(".ts")) {
|
|
164
|
+
assert.match(launch?.env?.NODE_OPTIONS ?? "", /--experimental-strip-types/);
|
|
165
|
+
assert.match(launch?.env?.NODE_OPTIONS ?? "", /resolve-ts\.mjs/);
|
|
166
|
+
}
|
|
158
167
|
});
|
|
159
168
|
|
|
160
169
|
test("workflow MCP launch config reaches mutation tools over stdio", async () => {
|
|
@@ -165,12 +174,16 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
|
|
|
165
174
|
assert.ok(launch, "expected a workflow MCP launch config");
|
|
166
175
|
assert.match(
|
|
167
176
|
launch.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "",
|
|
168
|
-
/dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]tools[\/\\]workflow-tool-executors\.js$/,
|
|
177
|
+
/(dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]tools[\/\\]workflow-tool-executors\.js|src[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]tools[\/\\]workflow-tool-executors\.(js|ts))$/,
|
|
169
178
|
);
|
|
170
179
|
assert.match(
|
|
171
180
|
launch.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "",
|
|
172
|
-
/dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]bootstrap[\/\\]write-gate\.js$/,
|
|
181
|
+
/(dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]bootstrap[\/\\]write-gate\.js|src[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]bootstrap[\/\\]write-gate\.(js|ts))$/,
|
|
173
182
|
);
|
|
183
|
+
if ((launch.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "").endsWith(".ts")) {
|
|
184
|
+
assert.match(launch.env?.NODE_OPTIONS ?? "", /--experimental-strip-types/);
|
|
185
|
+
assert.match(launch.env?.NODE_OPTIONS ?? "", /resolve-ts\.mjs/);
|
|
186
|
+
}
|
|
174
187
|
|
|
175
188
|
const client = new Client({ name: "workflow-mcp-transport-test", version: "1.0.0" });
|
|
176
189
|
const transport = new StdioClientTransport({
|
|
@@ -189,6 +202,10 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
|
|
|
189
202
|
(tools.tools ?? []).some((tool) => tool.name === "gsd_plan_slice"),
|
|
190
203
|
"expected workflow MCP surface to expose gsd_plan_slice",
|
|
191
204
|
);
|
|
205
|
+
assert.ok(
|
|
206
|
+
(tools.tools ?? []).some((tool) => tool.name === "ask_user_questions"),
|
|
207
|
+
"expected workflow MCP surface to expose ask_user_questions",
|
|
208
|
+
);
|
|
192
209
|
|
|
193
210
|
const milestoneResult = await client.callTool(
|
|
194
211
|
{
|
|
@@ -275,6 +292,30 @@ test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
|
275
292
|
assert.equal(usesWorkflowMcpTransport("oauth", "local://custom"), false);
|
|
276
293
|
});
|
|
277
294
|
|
|
295
|
+
test("supportsStructuredQuestions disables structured ask flow on workflow MCP transports", () => {
|
|
296
|
+
assert.equal(
|
|
297
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
298
|
+
authMode: "externalCli",
|
|
299
|
+
baseUrl: "local://claude-code",
|
|
300
|
+
}),
|
|
301
|
+
false,
|
|
302
|
+
);
|
|
303
|
+
assert.equal(
|
|
304
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
305
|
+
authMode: "oauth",
|
|
306
|
+
baseUrl: "https://api.anthropic.com",
|
|
307
|
+
}),
|
|
308
|
+
true,
|
|
309
|
+
);
|
|
310
|
+
assert.equal(
|
|
311
|
+
supportsStructuredQuestions([], {
|
|
312
|
+
authMode: "oauth",
|
|
313
|
+
baseUrl: "https://api.anthropic.com",
|
|
314
|
+
}),
|
|
315
|
+
false,
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
|
|
278
319
|
test("transport compatibility passes when required tools fit current MCP surface", () => {
|
|
279
320
|
const error = getWorkflowTransportSupportError(
|
|
280
321
|
"claude-code",
|
|
@@ -465,18 +506,18 @@ test("transport compatibility now allows replan-slice over workflow MCP surface"
|
|
|
465
506
|
test("transport compatibility still blocks units whose MCP tools are not exposed", () => {
|
|
466
507
|
const error = getWorkflowTransportSupportError(
|
|
467
508
|
"claude-code",
|
|
468
|
-
["
|
|
509
|
+
["secure_env_collect"],
|
|
469
510
|
{
|
|
470
511
|
projectRoot: "/tmp/project",
|
|
471
512
|
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
472
513
|
surface: "auto-mode",
|
|
473
|
-
unitType: "
|
|
514
|
+
unitType: "guided-discussion",
|
|
474
515
|
authMode: "externalCli",
|
|
475
516
|
baseUrl: "local://claude-code",
|
|
476
517
|
},
|
|
477
518
|
);
|
|
478
519
|
|
|
479
|
-
assert.match(error ?? "", /requires
|
|
520
|
+
assert.match(error ?? "", /requires secure_env_collect/);
|
|
480
521
|
assert.match(error ?? "", /currently exposes only/);
|
|
481
522
|
});
|
|
482
523
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
|
|
6
6
|
export interface WorkflowMcpLaunchConfig {
|
|
7
7
|
name: string;
|
|
@@ -21,22 +21,35 @@ export interface WorkflowCapabilityOptions {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const MCP_WORKFLOW_TOOL_SURFACE = new Set([
|
|
24
|
+
"ask_user_questions",
|
|
25
|
+
"gsd_decision_save",
|
|
24
26
|
"gsd_complete_milestone",
|
|
25
27
|
"gsd_complete_task",
|
|
26
28
|
"gsd_complete_slice",
|
|
29
|
+
"gsd_generate_milestone_id",
|
|
30
|
+
"gsd_journal_query",
|
|
27
31
|
"gsd_milestone_complete",
|
|
32
|
+
"gsd_milestone_generate_id",
|
|
28
33
|
"gsd_milestone_status",
|
|
29
34
|
"gsd_milestone_validate",
|
|
35
|
+
"gsd_plan_task",
|
|
30
36
|
"gsd_plan_milestone",
|
|
31
37
|
"gsd_plan_slice",
|
|
32
38
|
"gsd_replan_slice",
|
|
33
39
|
"gsd_reassess_roadmap",
|
|
40
|
+
"gsd_requirement_save",
|
|
41
|
+
"gsd_requirement_update",
|
|
34
42
|
"gsd_roadmap_reassess",
|
|
43
|
+
"gsd_save_decision",
|
|
35
44
|
"gsd_save_gate_result",
|
|
45
|
+
"gsd_save_requirement",
|
|
46
|
+
"gsd_skip_slice",
|
|
36
47
|
"gsd_slice_replan",
|
|
37
48
|
"gsd_slice_complete",
|
|
38
49
|
"gsd_summary_save",
|
|
50
|
+
"gsd_task_plan",
|
|
39
51
|
"gsd_task_complete",
|
|
52
|
+
"gsd_update_requirement",
|
|
40
53
|
"gsd_validate_milestone",
|
|
41
54
|
]);
|
|
42
55
|
|
|
@@ -95,6 +108,8 @@ function getBundledWorkflowMcpCliPath(env: NodeJS.ProcessEnv): string | null {
|
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
const candidates = [
|
|
111
|
+
resolve(fileURLToPath(new URL("../../../../packages/mcp-server/src/cli.ts", import.meta.url))),
|
|
112
|
+
resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/src/cli.ts", import.meta.url))),
|
|
98
113
|
resolve(fileURLToPath(new URL("../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
|
|
99
114
|
resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
|
|
100
115
|
];
|
|
@@ -108,9 +123,9 @@ function getBundledWorkflowMcpCliPath(env: NodeJS.ProcessEnv): string | null {
|
|
|
108
123
|
|
|
109
124
|
function getBundledWorkflowExecutorModulePath(): string | null {
|
|
110
125
|
const candidates = [
|
|
111
|
-
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
|
|
112
126
|
resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.js", import.meta.url))),
|
|
113
127
|
resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.ts", import.meta.url))),
|
|
128
|
+
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
|
|
114
129
|
];
|
|
115
130
|
|
|
116
131
|
for (const candidate of candidates) {
|
|
@@ -122,9 +137,22 @@ function getBundledWorkflowExecutorModulePath(): string | null {
|
|
|
122
137
|
|
|
123
138
|
function getBundledWorkflowWriteGateModulePath(): string | null {
|
|
124
139
|
const candidates = [
|
|
125
|
-
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
|
|
126
140
|
resolve(fileURLToPath(new URL("./bootstrap/write-gate.js", import.meta.url))),
|
|
127
141
|
resolve(fileURLToPath(new URL("./bootstrap/write-gate.ts", import.meta.url))),
|
|
142
|
+
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
for (const candidate of candidates) {
|
|
146
|
+
if (existsSync(candidate)) return candidate;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function getResolveTsHookPath(): string | null {
|
|
153
|
+
const candidates = [
|
|
154
|
+
resolve(fileURLToPath(new URL("./tests/resolve-ts.mjs", import.meta.url))),
|
|
155
|
+
resolve(fileURLToPath(new URL("../../../../src/resources/extensions/gsd/tests/resolve-ts.mjs", import.meta.url))),
|
|
128
156
|
];
|
|
129
157
|
|
|
130
158
|
for (const candidate of candidates) {
|
|
@@ -134,19 +162,45 @@ function getBundledWorkflowWriteGateModulePath(): string | null {
|
|
|
134
162
|
return null;
|
|
135
163
|
}
|
|
136
164
|
|
|
165
|
+
function mergeNodeOptions(existing: string | undefined, additions: string[]): string | undefined {
|
|
166
|
+
const tokens = (existing ?? "").split(/\s+/).map((value) => value.trim()).filter(Boolean);
|
|
167
|
+
for (const addition of additions) {
|
|
168
|
+
if (!tokens.includes(addition)) {
|
|
169
|
+
tokens.push(addition);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return tokens.length > 0 ? tokens.join(" ") : undefined;
|
|
173
|
+
}
|
|
174
|
+
|
|
137
175
|
function buildWorkflowLaunchEnv(
|
|
138
176
|
projectRoot: string,
|
|
139
177
|
gsdCliPath: string | undefined,
|
|
140
178
|
explicitEnv?: Record<string, string>,
|
|
179
|
+
workflowCliPath?: string,
|
|
141
180
|
): Record<string, string> {
|
|
142
181
|
const executorModulePath = getBundledWorkflowExecutorModulePath();
|
|
143
182
|
const writeGateModulePath = getBundledWorkflowWriteGateModulePath();
|
|
183
|
+
const resolveTsHookPath = getResolveTsHookPath();
|
|
184
|
+
const wantsSourceTs =
|
|
185
|
+
Boolean(resolveTsHookPath) &&
|
|
186
|
+
(
|
|
187
|
+
(workflowCliPath?.endsWith(".ts") ?? false) ||
|
|
188
|
+
(executorModulePath?.endsWith(".ts") ?? false) ||
|
|
189
|
+
(writeGateModulePath?.endsWith(".ts") ?? false)
|
|
190
|
+
);
|
|
191
|
+
const nodeOptions = wantsSourceTs
|
|
192
|
+
? mergeNodeOptions(explicitEnv?.NODE_OPTIONS, [
|
|
193
|
+
"--experimental-strip-types",
|
|
194
|
+
`--import=${pathToFileURL(resolveTsHookPath!).href}`,
|
|
195
|
+
])
|
|
196
|
+
: explicitEnv?.NODE_OPTIONS;
|
|
144
197
|
|
|
145
198
|
return {
|
|
146
199
|
...(explicitEnv ?? {}),
|
|
147
200
|
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
148
201
|
...(executorModulePath ? { GSD_WORKFLOW_EXECUTORS_MODULE: executorModulePath } : {}),
|
|
149
202
|
...(writeGateModulePath ? { GSD_WORKFLOW_WRITE_GATE_MODULE: writeGateModulePath } : {}),
|
|
203
|
+
...(nodeOptions ? { NODE_OPTIONS: nodeOptions } : {}),
|
|
150
204
|
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
151
205
|
GSD_WORKFLOW_PROJECT_ROOT: projectRoot,
|
|
152
206
|
};
|
|
@@ -188,7 +242,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
188
242
|
command: process.execPath,
|
|
189
243
|
args: [distCli],
|
|
190
244
|
cwd: resolvedWorkflowProjectRoot,
|
|
191
|
-
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
245
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath, undefined, distCli),
|
|
192
246
|
};
|
|
193
247
|
}
|
|
194
248
|
|
|
@@ -199,7 +253,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
199
253
|
command: process.execPath,
|
|
200
254
|
args: [bundledCli],
|
|
201
255
|
cwd: resolvedWorkflowProjectRoot,
|
|
202
|
-
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
256
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath, undefined, bundledCli),
|
|
203
257
|
};
|
|
204
258
|
}
|
|
205
259
|
|
|
@@ -294,6 +348,21 @@ export function usesWorkflowMcpTransport(
|
|
|
294
348
|
return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
|
|
295
349
|
}
|
|
296
350
|
|
|
351
|
+
export function supportsStructuredQuestions(
|
|
352
|
+
activeTools: string[],
|
|
353
|
+
options: Pick<WorkflowCapabilityOptions, "authMode" | "baseUrl"> = {},
|
|
354
|
+
): boolean {
|
|
355
|
+
if (!activeTools.includes("ask_user_questions")) return false;
|
|
356
|
+
|
|
357
|
+
// Workflow MCP currently exposes ask_user_questions via MCP form elicitation.
|
|
358
|
+
// Local external CLI transports such as Claude Code can invoke the tool, but
|
|
359
|
+
// do not reliably complete that elicitation round-trip yet, so guided discuss
|
|
360
|
+
// prompts must fall back to plain-text questioning.
|
|
361
|
+
if (usesWorkflowMcpTransport(options.authMode, options.baseUrl)) return false;
|
|
362
|
+
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
|
|
297
366
|
export function getWorkflowTransportSupportError(
|
|
298
367
|
provider: string | undefined,
|
|
299
368
|
requiredTools: string[],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},15726:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(2008),n.e(2826)]).then(n.bind(n,62826)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[62826]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=15726)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{2852:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))},19393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(2852))),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{52560:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=52560)),_N_E=e.O()}]);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Anthropic OAuth flow (Claude Pro/Max)
|
|
3
|
-
*/
|
|
4
|
-
import type { OAuthCredentials, OAuthProviderInterface } from "./types.js";
|
|
5
|
-
/**
|
|
6
|
-
* Login with Anthropic OAuth (device code flow)
|
|
7
|
-
*
|
|
8
|
-
* @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)
|
|
9
|
-
* @param onPromptCode - Callback to prompt user for the authorization code
|
|
10
|
-
*/
|
|
11
|
-
export declare function loginAnthropic(onAuthUrl: (url: string) => void, onPromptCode: () => Promise<string>): Promise<OAuthCredentials>;
|
|
12
|
-
/**
|
|
13
|
-
* Refresh Anthropic OAuth token
|
|
14
|
-
*/
|
|
15
|
-
export declare function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
16
|
-
export declare const anthropicOAuthProvider: OAuthProviderInterface;
|
|
17
|
-
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/anthropic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAuB,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAShG;;;;;GAKG;AACH,wBAAsB,cAAc,CACnC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA+D3B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4B3F;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAkBpC,CAAC"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Anthropic OAuth flow (Claude Pro/Max)
|
|
3
|
-
*/
|
|
4
|
-
import { generatePKCE } from "./pkce.js";
|
|
5
|
-
const decode = (s) => atob(s);
|
|
6
|
-
const CLIENT_ID = decode("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
|
|
7
|
-
const AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
8
|
-
const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
9
|
-
const REDIRECT_URI = "https://platform.claude.com/oauth/code/callback";
|
|
10
|
-
const SCOPES = "org:create_api_key user:profile user:inference";
|
|
11
|
-
/**
|
|
12
|
-
* Login with Anthropic OAuth (device code flow)
|
|
13
|
-
*
|
|
14
|
-
* @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)
|
|
15
|
-
* @param onPromptCode - Callback to prompt user for the authorization code
|
|
16
|
-
*/
|
|
17
|
-
export async function loginAnthropic(onAuthUrl, onPromptCode) {
|
|
18
|
-
const { verifier, challenge } = await generatePKCE();
|
|
19
|
-
// Build authorization URL
|
|
20
|
-
const authParams = new URLSearchParams({
|
|
21
|
-
code: "true",
|
|
22
|
-
client_id: CLIENT_ID,
|
|
23
|
-
response_type: "code",
|
|
24
|
-
redirect_uri: REDIRECT_URI,
|
|
25
|
-
scope: SCOPES,
|
|
26
|
-
code_challenge: challenge,
|
|
27
|
-
code_challenge_method: "S256",
|
|
28
|
-
state: verifier,
|
|
29
|
-
});
|
|
30
|
-
const authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;
|
|
31
|
-
// Notify caller with URL to open
|
|
32
|
-
onAuthUrl(authUrl);
|
|
33
|
-
// Wait for user to paste authorization code (format: code#state)
|
|
34
|
-
const authCode = await onPromptCode();
|
|
35
|
-
const splits = authCode.split("#");
|
|
36
|
-
const code = splits[0];
|
|
37
|
-
const state = splits[1];
|
|
38
|
-
// Exchange code for tokens
|
|
39
|
-
const tokenResponse = await fetch(TOKEN_URL, {
|
|
40
|
-
method: "POST",
|
|
41
|
-
headers: {
|
|
42
|
-
"Content-Type": "application/json",
|
|
43
|
-
},
|
|
44
|
-
body: JSON.stringify({
|
|
45
|
-
grant_type: "authorization_code",
|
|
46
|
-
client_id: CLIENT_ID,
|
|
47
|
-
code: code,
|
|
48
|
-
state: state,
|
|
49
|
-
redirect_uri: REDIRECT_URI,
|
|
50
|
-
code_verifier: verifier,
|
|
51
|
-
}),
|
|
52
|
-
signal: AbortSignal.timeout(30_000),
|
|
53
|
-
});
|
|
54
|
-
if (!tokenResponse.ok) {
|
|
55
|
-
const error = await tokenResponse.text();
|
|
56
|
-
throw new Error(`Token exchange failed: ${error}`);
|
|
57
|
-
}
|
|
58
|
-
const tokenData = (await tokenResponse.json());
|
|
59
|
-
// Calculate expiry time (current time + expires_in seconds - 5 min buffer)
|
|
60
|
-
const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;
|
|
61
|
-
// Save credentials
|
|
62
|
-
return {
|
|
63
|
-
refresh: tokenData.refresh_token,
|
|
64
|
-
access: tokenData.access_token,
|
|
65
|
-
expires: expiresAt,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Refresh Anthropic OAuth token
|
|
70
|
-
*/
|
|
71
|
-
export async function refreshAnthropicToken(refreshToken) {
|
|
72
|
-
const response = await fetch(TOKEN_URL, {
|
|
73
|
-
method: "POST",
|
|
74
|
-
headers: { "Content-Type": "application/json" },
|
|
75
|
-
body: JSON.stringify({
|
|
76
|
-
grant_type: "refresh_token",
|
|
77
|
-
client_id: CLIENT_ID,
|
|
78
|
-
refresh_token: refreshToken,
|
|
79
|
-
}),
|
|
80
|
-
signal: AbortSignal.timeout(30_000),
|
|
81
|
-
});
|
|
82
|
-
if (!response.ok) {
|
|
83
|
-
const error = await response.text();
|
|
84
|
-
throw new Error(`Anthropic token refresh failed: ${error}`);
|
|
85
|
-
}
|
|
86
|
-
const data = (await response.json());
|
|
87
|
-
return {
|
|
88
|
-
refresh: data.refresh_token,
|
|
89
|
-
access: data.access_token,
|
|
90
|
-
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
export const anthropicOAuthProvider = {
|
|
94
|
-
id: "anthropic",
|
|
95
|
-
name: "Anthropic (Claude Pro/Max)",
|
|
96
|
-
async login(callbacks) {
|
|
97
|
-
return loginAnthropic((url) => callbacks.onAuth({ url }), () => callbacks.onPrompt({ message: "Paste the authorization code:" }));
|
|
98
|
-
},
|
|
99
|
-
async refreshToken(credentials) {
|
|
100
|
-
return refreshAnthropicToken(credentials.refresh);
|
|
101
|
-
},
|
|
102
|
-
getApiKey(credentials) {
|
|
103
|
-
return credentials.access;
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
//# sourceMappingURL=anthropic.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/utils/oauth/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Anthropic OAuth flow (Claude Pro/Max)\n */\n\nimport { generatePKCE } from \"./pkce.js\";\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from \"./types.js\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl\");\nconst AUTHORIZE_URL = \"https://claude.ai/oauth/authorize\";\nconst TOKEN_URL = \"https://platform.claude.com/v1/oauth/token\";\nconst REDIRECT_URI = \"https://platform.claude.com/oauth/code/callback\";\nconst SCOPES = \"org:create_api_key user:profile user:inference\";\n\n/**\n * Login with Anthropic OAuth (device code flow)\n *\n * @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)\n * @param onPromptCode - Callback to prompt user for the authorization code\n */\nexport async function loginAnthropic(\n\tonAuthUrl: (url: string) => void,\n\tonPromptCode: () => Promise<string>,\n): Promise<OAuthCredentials> {\n\tconst { verifier, challenge } = await generatePKCE();\n\n\t// Build authorization URL\n\tconst authParams = new URLSearchParams({\n\t\tcode: \"true\",\n\t\tclient_id: CLIENT_ID,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: REDIRECT_URI,\n\t\tscope: SCOPES,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tstate: verifier,\n\t});\n\n\tconst authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;\n\n\t// Notify caller with URL to open\n\tonAuthUrl(authUrl);\n\n\t// Wait for user to paste authorization code (format: code#state)\n\tconst authCode = await onPromptCode();\n\tconst splits = authCode.split(\"#\");\n\tconst code = splits[0];\n\tconst state = splits[1];\n\n\t// Exchange code for tokens\n\tconst tokenResponse = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode: code,\n\t\t\tstate: state,\n\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\tcode_verifier: verifier,\n\t\t}),\n\t\tsignal: AbortSignal.timeout(30_000),\n\t});\n\n\tif (!tokenResponse.ok) {\n\t\tconst error = await tokenResponse.text();\n\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t}\n\n\tconst tokenData = (await tokenResponse.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\t// Calculate expiry time (current time + expires_in seconds - 5 min buffer)\n\tconst expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;\n\n\t// Save credentials\n\treturn {\n\t\trefresh: tokenData.refresh_token,\n\t\taccess: tokenData.access_token,\n\t\texpires: expiresAt,\n\t};\n}\n\n/**\n * Refresh Anthropic OAuth token\n */\nexport async function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\trefresh_token: refreshToken,\n\t\t}),\n\t\tsignal: AbortSignal.timeout(30_000),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.text();\n\t\tthrow new Error(`Anthropic token refresh failed: ${error}`);\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\treturn {\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n\t};\n}\n\nexport const anthropicOAuthProvider: OAuthProviderInterface = {\n\tid: \"anthropic\",\n\tname: \"Anthropic (Claude Pro/Max)\",\n\n\tasync login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n\t\treturn loginAnthropic(\n\t\t\t(url) => callbacks.onAuth({ url }),\n\t\t\t() => callbacks.onPrompt({ message: \"Paste the authorization code:\" }),\n\t\t);\n\t},\n\n\tasync refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n\t\treturn refreshAnthropicToken(credentials.refresh);\n\t},\n\n\tgetApiKey(credentials: OAuthCredentials): string {\n\t\treturn credentials.access;\n\t},\n};\n"]}
|