@opengsd/gsd-pi 1.1.1-dev.154fd443 → 1.1.1-dev.1854a79a
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/project-sessions.js +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/index.js +39 -22
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -9
- package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +659 -57
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -1
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +5 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +29 -0
- package/dist/resources/extensions/gsd/auto.js +62 -464
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -1
- package/dist/resources/extensions/gsd/debug-logger.js +10 -0
- package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +31 -32
- package/dist/resources/extensions/gsd/mcp-filter.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +9 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +6 -6
- package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +6 -4
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +0 -34
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +0 -34
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +39 -22
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -8
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +8 -119
- package/src/resources/extensions/gsd/auto/orchestrator.ts +794 -58
- package/src/resources/extensions/gsd/auto-prompts.ts +21 -1
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +5 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +33 -0
- package/src/resources/extensions/gsd/auto.ts +81 -500
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
- package/src/resources/extensions/gsd/debug-logger.ts +11 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
- package/src/resources/extensions/gsd/markdown-renderer.ts +38 -19
- package/src/resources/extensions/gsd/mcp-filter.ts +7 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +9 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
- package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +590 -855
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +19 -5
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
- package/dist/web/standalone/.next/server/chunks/678.js +0 -2
- /package/dist/web/standalone/.next/static/{vAecbJ3K9eO213bAxU8Mi → h38jfi0dnRY0y3hbyBszg}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{vAecbJ3K9eO213bAxU8Mi → h38jfi0dnRY0y3hbyBszg}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-coding-agent",
|
|
3
|
-
"version": "1.1.1-dev.
|
|
3
|
+
"version": "1.1.1-dev.1854a79a",
|
|
4
4
|
"description": "Coding agent CLI (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"copy-assets": "node scripts/copy-assets.cjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@opengsd/contracts": "^1.1.1-dev.
|
|
36
|
+
"@opengsd/contracts": "^1.1.1-dev.1854a79a",
|
|
37
37
|
"@mariozechner/jiti": "^2.6.2",
|
|
38
38
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
39
39
|
"chalk": "5.6.2",
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"typebox": "1.1.38",
|
|
54
54
|
"undici": "7.26.0",
|
|
55
55
|
"yaml": "2.9.0",
|
|
56
|
-
"@gsd/agent-core": "^1.1.1-dev.
|
|
57
|
-
"@gsd/native": "^1.1.1-dev.
|
|
58
|
-
"@gsd/pi-agent-core": "^1.1.1-dev.
|
|
59
|
-
"@gsd/pi-ai": "^1.1.1-dev.
|
|
60
|
-
"@gsd/pi-tui": "^1.1.1-dev.
|
|
56
|
+
"@gsd/agent-core": "^1.1.1-dev.1854a79a",
|
|
57
|
+
"@gsd/native": "^1.1.1-dev.1854a79a",
|
|
58
|
+
"@gsd/pi-agent-core": "^1.1.1-dev.1854a79a",
|
|
59
|
+
"@gsd/pi-ai": "^1.1.1-dev.1854a79a",
|
|
60
|
+
"@gsd/pi-tui": "^1.1.1-dev.1854a79a",
|
|
61
61
|
"@sinclair/typebox": "^0.34.41"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-tui",
|
|
3
|
-
"version": "1.1.1-dev.
|
|
3
|
+
"version": "1.1.1-dev.1854a79a",
|
|
4
4
|
"description": "Terminal UI library (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build": "node ../../scripts/clean-package-dist.cjs && tsc -p tsconfig.json --incremental false"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@gsd/native": "^1.1.1-dev.
|
|
24
|
+
"@gsd/native": "^1.1.1-dev.1854a79a",
|
|
25
25
|
"get-east-asian-width": "1.6.0",
|
|
26
26
|
"marked": "15.0.12",
|
|
27
27
|
"@sinclair/typebox": "^0.34.41"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/rpc-client",
|
|
3
|
-
"version": "1.1.1-dev.
|
|
3
|
+
"version": "1.1.1-dev.1854a79a",
|
|
4
4
|
"description": "Standalone RPC client SDK for GSD — zero internal dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test": "node --test dist/rpc-client.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@opengsd/contracts": "^1.1.1-dev.
|
|
37
|
+
"@opengsd/contracts": "^1.1.1-dev.1854a79a"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { importExtensionModule, type ExtensionAPI, type ExtensionContext } from
|
|
|
3
3
|
|
|
4
4
|
import { closeManagedGsdBrowser, registerManagedGsdBrowserTools, warmUpManagedGsdBrowser } from "./engine/managed-gsd-browser.js";
|
|
5
5
|
import { resolveBrowserEngineMode, type BrowserEngineMode } from "./engine/selection.js";
|
|
6
|
+
import { setArtifactRootForCwd } from "./state.js";
|
|
6
7
|
import { detectWebApp } from "./web-app-detect.js";
|
|
7
8
|
|
|
8
9
|
let legacyRegistrationPromise: Promise<void> | null = null;
|
|
@@ -119,28 +120,29 @@ async function registerLegacyBrowserTools(pi: ExtensionAPI): Promise<void> {
|
|
|
119
120
|
formatArtifactTimestamp: utils.formatArtifactTimestamp,
|
|
120
121
|
};
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
123
|
+
const cwdScopedPi = withBrowserArtifactCwdScope(pi);
|
|
124
|
+
navigation.registerNavigationTools(cwdScopedPi, deps);
|
|
125
|
+
screenshot.registerScreenshotTools(cwdScopedPi, deps);
|
|
126
|
+
interaction.registerInteractionTools(cwdScopedPi, deps);
|
|
127
|
+
inspection.registerInspectionTools(cwdScopedPi, deps);
|
|
128
|
+
session.registerSessionTools(cwdScopedPi, deps);
|
|
129
|
+
assertions.registerAssertionTools(cwdScopedPi, deps);
|
|
130
|
+
refTools.registerRefTools(cwdScopedPi, deps);
|
|
131
|
+
wait.registerWaitTools(cwdScopedPi, deps);
|
|
132
|
+
pages.registerPageTools(cwdScopedPi, deps);
|
|
133
|
+
forms.registerFormTools(cwdScopedPi, deps);
|
|
134
|
+
intent.registerIntentTools(cwdScopedPi, deps);
|
|
135
|
+
pdf.registerPdfTools(cwdScopedPi, deps);
|
|
136
|
+
statePersistence.registerStatePersistenceTools(cwdScopedPi, deps);
|
|
137
|
+
networkMock.registerNetworkMockTools(cwdScopedPi, deps);
|
|
138
|
+
device.registerDeviceTools(cwdScopedPi, deps);
|
|
139
|
+
extract.registerExtractTools(cwdScopedPi, deps);
|
|
140
|
+
visualDiff.registerVisualDiffTools(cwdScopedPi, deps);
|
|
141
|
+
zoom.registerZoomTools(cwdScopedPi, deps);
|
|
142
|
+
codegen.registerCodegenTools(cwdScopedPi, deps);
|
|
143
|
+
actionCache.registerActionCacheTools(cwdScopedPi, deps);
|
|
144
|
+
injectionDetection.registerInjectionDetectionTools(cwdScopedPi, deps);
|
|
145
|
+
verify.registerVerifyTools(cwdScopedPi, deps);
|
|
144
146
|
})().catch((error) => {
|
|
145
147
|
legacyRegistrationPromise = null;
|
|
146
148
|
throw error;
|
|
@@ -150,6 +152,21 @@ async function registerLegacyBrowserTools(pi: ExtensionAPI): Promise<void> {
|
|
|
150
152
|
return legacyRegistrationPromise;
|
|
151
153
|
}
|
|
152
154
|
|
|
155
|
+
function withBrowserArtifactCwdScope(pi: ExtensionAPI): ExtensionAPI {
|
|
156
|
+
return {
|
|
157
|
+
...pi,
|
|
158
|
+
registerTool(definition) {
|
|
159
|
+
pi.registerTool({
|
|
160
|
+
...definition,
|
|
161
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
162
|
+
if (ctx?.cwd) setArtifactRootForCwd(ctx.cwd);
|
|
163
|
+
return definition.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
153
170
|
async function registerBrowserTools(pi: ExtensionAPI): Promise<void> {
|
|
154
171
|
const engine = resolveBrowserEngineMode();
|
|
155
172
|
if (engine === "off") return;
|
|
@@ -186,6 +186,18 @@ export interface BrowserAssertionCheckInput {
|
|
|
186
186
|
// Mutable state variables — accessed only via get/set functions
|
|
187
187
|
// ---------------------------------------------------------------------------
|
|
188
188
|
|
|
189
|
+
// 0. artifactRoot
|
|
190
|
+
let _artifactRoot = ARTIFACT_ROOT;
|
|
191
|
+
export function getArtifactRoot(): string { return _artifactRoot; }
|
|
192
|
+
export function setArtifactRootForCwd(cwd: string): string {
|
|
193
|
+
const newRoot = path.resolve(cwd, ".artifacts", "browser");
|
|
194
|
+
if (newRoot !== _artifactRoot) {
|
|
195
|
+
_artifactRoot = newRoot;
|
|
196
|
+
_sessionArtifactDir = null;
|
|
197
|
+
}
|
|
198
|
+
return _artifactRoot;
|
|
199
|
+
}
|
|
200
|
+
|
|
189
201
|
// 1. browser
|
|
190
202
|
let _browser: Browser | null = null;
|
|
191
203
|
export function getBrowser(): Browser | null { return _browser; }
|
|
@@ -290,6 +302,7 @@ export function setHarState(h: HarState): void { _harState = h; }
|
|
|
290
302
|
// ---------------------------------------------------------------------------
|
|
291
303
|
|
|
292
304
|
export function resetAllState(): void {
|
|
305
|
+
_artifactRoot = ARTIFACT_ROOT;
|
|
293
306
|
_browser = null;
|
|
294
307
|
_context = null;
|
|
295
308
|
pageRegistry.pages = [];
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
const { describe, it, beforeEach } = require("node:test");
|
|
12
12
|
const assert = require("node:assert/strict");
|
|
13
|
+
const { mkdtempSync, rmSync } = require("node:fs");
|
|
14
|
+
const { tmpdir } = require("node:os");
|
|
15
|
+
const { join } = require("node:path");
|
|
13
16
|
const jiti = require("jiti")(__filename, { interopDefault: true, debug: false });
|
|
14
17
|
|
|
15
18
|
// ---------------------------------------------------------------------------
|
|
@@ -28,9 +31,12 @@ const {
|
|
|
28
31
|
getUrlHash,
|
|
29
32
|
firstErrorLine,
|
|
30
33
|
formatArtifactTimestamp,
|
|
34
|
+
ensureSessionArtifactDir,
|
|
31
35
|
} = jiti("../utils.ts");
|
|
32
36
|
|
|
33
37
|
const {
|
|
38
|
+
getArtifactRoot,
|
|
39
|
+
setArtifactRootForCwd,
|
|
34
40
|
getBrowser,
|
|
35
41
|
setBrowser,
|
|
36
42
|
getContext,
|
|
@@ -469,6 +475,57 @@ describe("state accessors", () => {
|
|
|
469
475
|
assert.equal(getSessionArtifactDir(), "/tmp/artifacts");
|
|
470
476
|
});
|
|
471
477
|
|
|
478
|
+
it("uses the active tool context cwd for session artifact paths", async (t) => {
|
|
479
|
+
const processRoot = mkdtempSync(join(tmpdir(), "browser-tools-process-"));
|
|
480
|
+
const contextRoot = mkdtempSync(join(tmpdir(), "browser-tools-context-"));
|
|
481
|
+
const previousCwd = process.cwd();
|
|
482
|
+
t.after(() => {
|
|
483
|
+
process.chdir(previousCwd);
|
|
484
|
+
rmSync(processRoot, { recursive: true, force: true });
|
|
485
|
+
rmSync(contextRoot, { recursive: true, force: true });
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
process.chdir(processRoot);
|
|
489
|
+
resetAllState();
|
|
490
|
+
const expectedRoot = join(contextRoot, ".artifacts", "browser");
|
|
491
|
+
setArtifactRootForCwd(contextRoot);
|
|
492
|
+
|
|
493
|
+
const sessionDir = await ensureSessionArtifactDir();
|
|
494
|
+
|
|
495
|
+
assert.equal(getArtifactRoot(), expectedRoot);
|
|
496
|
+
assert.ok(
|
|
497
|
+
sessionDir.startsWith(`${expectedRoot}/`),
|
|
498
|
+
`session artifact dir should stay under context cwd: ${sessionDir}`,
|
|
499
|
+
);
|
|
500
|
+
assert.ok(
|
|
501
|
+
!sessionDir.startsWith(join(processRoot, ".artifacts", "browser")),
|
|
502
|
+
`session artifact dir must not use process cwd: ${sessionDir}`,
|
|
503
|
+
);
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
it("session artifact dir is recomputed when artifact root changes", async (t) => {
|
|
507
|
+
const root1 = mkdtempSync(join(tmpdir(), "browser-tools-root1-"));
|
|
508
|
+
const root2 = mkdtempSync(join(tmpdir(), "browser-tools-root2-"));
|
|
509
|
+
t.after(() => {
|
|
510
|
+
rmSync(root1, { recursive: true, force: true });
|
|
511
|
+
rmSync(root2, { recursive: true, force: true });
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
resetAllState();
|
|
515
|
+
setArtifactRootForCwd(root1);
|
|
516
|
+
const sessionDir1 = await ensureSessionArtifactDir();
|
|
517
|
+
assert.ok(sessionDir1.startsWith(join(root1, ".artifacts", "browser")));
|
|
518
|
+
|
|
519
|
+
// Change the root — cached session dir must be invalidated
|
|
520
|
+
setArtifactRootForCwd(root2);
|
|
521
|
+
const sessionDir2 = await ensureSessionArtifactDir();
|
|
522
|
+
assert.ok(
|
|
523
|
+
sessionDir2.startsWith(join(root2, ".artifacts", "browser")),
|
|
524
|
+
`session dir should be under new root after root change: ${sessionDir2}`,
|
|
525
|
+
);
|
|
526
|
+
assert.notEqual(sessionDir1, sessionDir2, "session dir must differ after root change");
|
|
527
|
+
});
|
|
528
|
+
|
|
472
529
|
it("setCurrentRefMap/getCurrentRefMap round-trip", () => {
|
|
473
530
|
assert.deepStrictEqual(getCurrentRefMap(), {});
|
|
474
531
|
const refMap = { e1: { ref: "e1", tag: "button" } };
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
} from "../core.js";
|
|
10
10
|
import type { ToolDeps } from "../state.js";
|
|
11
11
|
import {
|
|
12
|
-
ARTIFACT_ROOT,
|
|
13
12
|
HAR_FILENAME,
|
|
13
|
+
getArtifactRoot,
|
|
14
14
|
getPageRegistry,
|
|
15
15
|
getActiveFrame,
|
|
16
16
|
getConsoleLogs,
|
|
@@ -315,7 +315,9 @@ export function registerSessionTools(pi: ExtensionAPI, deps: ToolDeps): void {
|
|
|
315
315
|
const { page: p } = await deps.ensureBrowser();
|
|
316
316
|
const startedAt = Date.now();
|
|
317
317
|
const sessionDir = await deps.ensureSessionArtifactDir();
|
|
318
|
-
const
|
|
318
|
+
const bundleName =
|
|
319
|
+
`${deps.formatArtifactTimestamp(startedAt)}-${deps.sanitizeArtifactName(params.name ?? "debug-bundle", "debug-bundle")}`;
|
|
320
|
+
const bundleDir = path.join(getArtifactRoot(), bundleName);
|
|
319
321
|
await ensureDir(bundleDir);
|
|
320
322
|
const pages = await deps.getLivePagesSnapshot();
|
|
321
323
|
const actionTimeline = getActionTimeline();
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
registryListPages,
|
|
22
22
|
} from "./core.js";
|
|
23
23
|
import {
|
|
24
|
-
ARTIFACT_ROOT,
|
|
25
24
|
getActiveFrame,
|
|
25
|
+
getArtifactRoot,
|
|
26
26
|
getActiveTraceSession,
|
|
27
27
|
getConsoleLogs,
|
|
28
28
|
getDialogLogs,
|
|
@@ -119,7 +119,7 @@ export async function ensureSessionArtifactDir(): Promise<string> {
|
|
|
119
119
|
return existing;
|
|
120
120
|
}
|
|
121
121
|
const startedAt = ensureSessionStartedAt();
|
|
122
|
-
const dir = path.join(
|
|
122
|
+
const dir = path.join(getArtifactRoot(), `${formatArtifactTimestamp(startedAt)}-session`);
|
|
123
123
|
setSessionArtifactDir(dir);
|
|
124
124
|
await ensureDir(dir);
|
|
125
125
|
return dir;
|
|
@@ -159,7 +159,7 @@ export function getActiveFrameMetadata() {
|
|
|
159
159
|
|
|
160
160
|
export function getSessionArtifactMetadata() {
|
|
161
161
|
return {
|
|
162
|
-
artifactRoot:
|
|
162
|
+
artifactRoot: getArtifactRoot(),
|
|
163
163
|
sessionStartedAt: getSessionStartedAt(),
|
|
164
164
|
sessionArtifactDir: getSessionArtifactDir(),
|
|
165
165
|
activeTraceSession: getActiveTraceSession(),
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
discoverBrowserMcpServerName,
|
|
39
39
|
discoverMcpServers,
|
|
40
40
|
discoverMcpServerNames,
|
|
41
|
+
discoverUserMcpServerNames,
|
|
41
42
|
discoverWorkflowMcpServerName,
|
|
42
43
|
computeMcpDisallowedTools,
|
|
43
44
|
} from "../gsd/mcp-filter.js";
|
|
@@ -1658,14 +1659,23 @@ export function buildSdkOptions(
|
|
|
1658
1659
|
const workflowServerName = projectWorkflowServerName ?? injectedWorkflowServerName;
|
|
1659
1660
|
const browserServerName = projectBrowserServerName ?? injectedBrowserServerName;
|
|
1660
1661
|
|
|
1661
|
-
//
|
|
1662
|
-
//
|
|
1663
|
-
//
|
|
1664
|
-
//
|
|
1662
|
+
// Non-strict (non-phase) sessions load ~/.claude/settings.json via settingSources
|
|
1663
|
+
// including "user". If the user declared the same server names there, injecting them
|
|
1664
|
+
// again via mcpServers causes duplicate registration and leaves MCP tools unavailable.
|
|
1665
|
+
// Strict (gsdPhase) sessions set settingSources=[] so user settings are not loaded.
|
|
1666
|
+
const userDiscovered = !gsdPhase ? discoverUserMcpServerNames() : [];
|
|
1667
|
+
const allDiscovered = discovered.length > 0 || userDiscovered.length > 0
|
|
1668
|
+
? [...discovered, ...userDiscovered]
|
|
1669
|
+
: discovered;
|
|
1670
|
+
|
|
1671
|
+
// If a default GSD MCP server is already declared in project config or in the user's
|
|
1672
|
+
// ~/.claude/settings.json (when that file will be loaded), do not inject it again via
|
|
1673
|
+
// mcpServers. Passing the same server name from two sources causes a duplicate
|
|
1674
|
+
// registration conflict that prevents the MCP server from loading (tools become unavailable).
|
|
1665
1675
|
const workflowAlreadyInProject = projectWorkflowServerName !== undefined
|
|
1666
|
-
|| (injectedWorkflowServerName !== undefined &&
|
|
1676
|
+
|| (injectedWorkflowServerName !== undefined && allDiscovered.includes(injectedWorkflowServerName));
|
|
1667
1677
|
const browserAlreadyInProject = projectBrowserServerName !== undefined
|
|
1668
|
-
|| (injectedBrowserServerName !== undefined &&
|
|
1678
|
+
|| (injectedBrowserServerName !== undefined && allDiscovered.includes(injectedBrowserServerName));
|
|
1669
1679
|
const mcpServersToInject = { ...defaultMcpServers.servers };
|
|
1670
1680
|
if (workflowAlreadyInProject && injectedWorkflowServerName) delete mcpServersToInject[injectedWorkflowServerName];
|
|
1671
1681
|
if (browserAlreadyInProject && injectedBrowserServerName) delete mcpServersToInject[injectedBrowserServerName];
|
|
@@ -1725,9 +1735,9 @@ export function buildSdkOptions(
|
|
|
1725
1735
|
const sdkMcpServers = inlinePhaseMcpServers ?? filteredMcpServers;
|
|
1726
1736
|
const strictMcpConfig = !!inlinePhaseMcpServers;
|
|
1727
1737
|
// Strict phase configs inline the exact MCP servers GSD needs. Loading
|
|
1728
|
-
//
|
|
1738
|
+
// Claude Code settings at the same time can duplicate those servers and
|
|
1729
1739
|
// leave allowed mcp__... tools with no registered backing tool.
|
|
1730
|
-
const settingSources = strictMcpConfig ? [] : ["project", "local"];
|
|
1740
|
+
const settingSources = strictMcpConfig ? [] : ["user", "project", "local"];
|
|
1731
1741
|
const exactWorkflowMcpTools = resolveExactWorkflowMcpToolsForPhase(
|
|
1732
1742
|
gsdPhase,
|
|
1733
1743
|
workflowServerName,
|
|
@@ -796,9 +796,9 @@ describe("stream-adapter — session persistence (#2859)", () => {
|
|
|
796
796
|
assert.equal(options.persistSession, true, "persistSession must default to true");
|
|
797
797
|
});
|
|
798
798
|
|
|
799
|
-
test("buildSdkOptions loads project and local settings so approved
|
|
799
|
+
test("buildSdkOptions loads user, project, and local settings so approved Claude Code config is active", () => {
|
|
800
800
|
const options = buildSdkOptions("claude-sonnet-4-20250514", "test prompt");
|
|
801
|
-
assert.deepEqual(options.settingSources, ["project", "local"]);
|
|
801
|
+
assert.deepEqual(options.settingSources, ["user", "project", "local"]);
|
|
802
802
|
});
|
|
803
803
|
|
|
804
804
|
test("buildSdkOptions sets model and prompt correctly", () => {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
|
-
// File Purpose: Auto Orchestration module
|
|
2
|
+
// File Purpose: Auto Orchestration module public contract types.
|
|
3
|
+
//
|
|
4
|
+
// Phase 2 of #442 collapsed the nine single-implementation adapter interfaces
|
|
5
|
+
// (DispatchAdapter, RecoveryAdapter, StateReconciliationAdapter,
|
|
6
|
+
// ToolContractAdapter, WorktreeAdapter, HealthAdapter, UokGateAdapter,
|
|
7
|
+
// RuntimePersistenceAdapter, NotificationAdapter) and AutoOrchestratorDeps
|
|
8
|
+
// into AutoOrchestrator itself (auto/orchestrator.ts). Only the public result
|
|
9
|
+
// and lifecycle-interface types remain here.
|
|
3
10
|
|
|
4
11
|
import type { GSDState } from "../types.js";
|
|
5
|
-
import type { MinimalModelRegistry } from "../context-budget.js";
|
|
6
|
-
import type { AutoSession } from "./session.js";
|
|
7
12
|
|
|
8
13
|
export interface AutoSessionContext {
|
|
9
14
|
basePath: string;
|
|
@@ -41,119 +46,3 @@ export interface AutoOrchestrationModule {
|
|
|
41
46
|
stop(reason: string): Promise<AutoAdvanceResult>;
|
|
42
47
|
getStatus(): AutoStatus;
|
|
43
48
|
}
|
|
44
|
-
|
|
45
|
-
export interface DispatchAdapter {
|
|
46
|
-
decideNextUnit(input: {
|
|
47
|
-
stateSnapshot: GSDState;
|
|
48
|
-
/** Optional live session context, forwarded to dispatch rules that need session-derived state. */
|
|
49
|
-
session?: AutoSession;
|
|
50
|
-
/** Mirrors `DispatchContext.structuredQuestionsAvailable` — "true"/"false" string per the dispatch contract. */
|
|
51
|
-
structuredQuestionsAvailable?: "true" | "false";
|
|
52
|
-
/** Session model context window in tokens, forwarded to the budget engine. */
|
|
53
|
-
sessionContextWindow?: number;
|
|
54
|
-
/** Session model provider, used for provider-specific effective context windows. */
|
|
55
|
-
sessionProvider?: string;
|
|
56
|
-
/** Model registry for executor-model lookups inside the budget engine. */
|
|
57
|
-
modelRegistry?: MinimalModelRegistry;
|
|
58
|
-
}): Promise<
|
|
59
|
-
| {
|
|
60
|
-
kind: "blocked";
|
|
61
|
-
reason: string;
|
|
62
|
-
action: "pause" | "stop";
|
|
63
|
-
}
|
|
64
|
-
| {
|
|
65
|
-
kind: "skipped";
|
|
66
|
-
reason: string;
|
|
67
|
-
}
|
|
68
|
-
| {
|
|
69
|
-
unitType: string;
|
|
70
|
-
unitId: string;
|
|
71
|
-
reason: string;
|
|
72
|
-
preconditions: string[];
|
|
73
|
-
}
|
|
74
|
-
| null
|
|
75
|
-
>;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface RecoveryAdapter {
|
|
79
|
-
classifyAndRecover(input: {
|
|
80
|
-
error: unknown;
|
|
81
|
-
unitType?: string;
|
|
82
|
-
unitId?: string;
|
|
83
|
-
}): Promise<{
|
|
84
|
-
action: "retry" | "escalate" | "stop";
|
|
85
|
-
reason: string;
|
|
86
|
-
}>;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export type InvariantAdapterResult =
|
|
90
|
-
| { ok: true; reason?: string; stateSnapshot?: GSDState }
|
|
91
|
-
| { ok: false; reason: string; stateSnapshot?: GSDState };
|
|
92
|
-
|
|
93
|
-
export interface StateReconciliationAdapter {
|
|
94
|
-
reconcileBeforeDispatch(): Promise<InvariantAdapterResult & { stateSnapshot?: GSDState }>;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface ToolContractAdapter {
|
|
98
|
-
compileUnitToolContract(unitType: string, unitId: string): Promise<InvariantAdapterResult>;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export interface WorktreeAdapter {
|
|
102
|
-
prepareForUnit(unitType: string, unitId: string): Promise<InvariantAdapterResult>;
|
|
103
|
-
syncAfterUnit(unitType: string, unitId: string): Promise<void>;
|
|
104
|
-
cleanupOnStop(reason: string): Promise<void>;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export type HealthGateResult =
|
|
108
|
-
| { kind: "pass"; fixesApplied?: readonly string[] }
|
|
109
|
-
| { kind: "fail"; reason: string; action?: "pause" | "stop" }
|
|
110
|
-
| { kind: "threw"; error: unknown };
|
|
111
|
-
|
|
112
|
-
export interface HealthAdapter {
|
|
113
|
-
checkResourcesStale(): string | null;
|
|
114
|
-
preAdvanceGate(): Promise<HealthGateResult>;
|
|
115
|
-
postAdvanceRecord(result: AutoAdvanceResult): Promise<void>;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface UokGateInput {
|
|
119
|
-
gateId: string;
|
|
120
|
-
gateType: "policy" | "execution";
|
|
121
|
-
outcome: "pass" | "fail" | "manual-attention";
|
|
122
|
-
failureClass: "none" | "policy" | "manual-attention";
|
|
123
|
-
rationale: string;
|
|
124
|
-
findings?: string;
|
|
125
|
-
milestoneId?: string;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export interface UokGateAdapter {
|
|
129
|
-
emit(input: UokGateInput): Promise<void>;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export interface RuntimePersistenceAdapter {
|
|
133
|
-
ensureLockOwnership(): Promise<void>;
|
|
134
|
-
journalTransition(event: {
|
|
135
|
-
name: string;
|
|
136
|
-
reason?: string;
|
|
137
|
-
unitType?: string;
|
|
138
|
-
unitId?: string;
|
|
139
|
-
}): Promise<void>;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface NotificationAdapter {
|
|
143
|
-
notifyLifecycle(event: {
|
|
144
|
-
name: string;
|
|
145
|
-
detail?: string;
|
|
146
|
-
}): Promise<void>;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export interface AutoOrchestratorDeps {
|
|
150
|
-
stateReconciliation: StateReconciliationAdapter;
|
|
151
|
-
dispatch: DispatchAdapter;
|
|
152
|
-
toolContract: ToolContractAdapter;
|
|
153
|
-
recovery: RecoveryAdapter;
|
|
154
|
-
worktree: WorktreeAdapter;
|
|
155
|
-
health: HealthAdapter;
|
|
156
|
-
runtime: RuntimePersistenceAdapter;
|
|
157
|
-
notifications: NotificationAdapter;
|
|
158
|
-
uokGate: UokGateAdapter;
|
|
159
|
-
}
|