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
package/dist/loader.js
CHANGED
|
@@ -93,6 +93,10 @@ if (!existsSync(appRoot)) {
|
|
|
93
93
|
}
|
|
94
94
|
// GSD_CODING_AGENT_DIR — tells pi's getAgentDir() to return ~/.gsd/agent/ instead of ~/.gsd/agent/
|
|
95
95
|
process.env.GSD_CODING_AGENT_DIR = agentDir;
|
|
96
|
+
// GSD_PKG_ROOT — absolute path to gsd-pi package root. Used by deployed extensions
|
|
97
|
+
// (e.g. auto.ts resume path) to import modules like resource-loader.js that live
|
|
98
|
+
// in the package tree, not in the deployed ~/.gsd/agent/ tree.
|
|
99
|
+
process.env.GSD_PKG_ROOT = gsdRoot;
|
|
96
100
|
// RTK environment — make ~/.gsd/agent/bin visible to all child-process paths,
|
|
97
101
|
// not just the bash tool, and force-disable RTK telemetry for GSD-managed use.
|
|
98
102
|
applyRtkProcessEnv(process.env);
|
|
@@ -10,6 +10,8 @@ import { EventStream } from "@gsd/pi-ai";
|
|
|
10
10
|
import { execSync } from "node:child_process";
|
|
11
11
|
import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
|
|
12
12
|
import { buildWorkflowMcpServers } from "../gsd/workflow-mcp.js";
|
|
13
|
+
import { showInterviewRound } from "../shared/tui.js";
|
|
14
|
+
const OTHER_OPTION_LABEL = "None of the above";
|
|
13
15
|
// ---------------------------------------------------------------------------
|
|
14
16
|
// Stream factory
|
|
15
17
|
// ---------------------------------------------------------------------------
|
|
@@ -124,6 +126,147 @@ export function makeStreamExhaustedErrorMessage(model, lastTextContent) {
|
|
|
124
126
|
}
|
|
125
127
|
return message;
|
|
126
128
|
}
|
|
129
|
+
function readElicitationChoices(options) {
|
|
130
|
+
if (!Array.isArray(options))
|
|
131
|
+
return [];
|
|
132
|
+
return options
|
|
133
|
+
.map((option) => (typeof option?.const === "string" ? option.const : typeof option?.title === "string" ? option.title : ""))
|
|
134
|
+
.filter((option) => option.length > 0);
|
|
135
|
+
}
|
|
136
|
+
export function parseAskUserQuestionsElicitation(request) {
|
|
137
|
+
if (request.mode && request.mode !== "form")
|
|
138
|
+
return null;
|
|
139
|
+
const properties = request.requestedSchema?.properties;
|
|
140
|
+
if (!properties || typeof properties !== "object")
|
|
141
|
+
return null;
|
|
142
|
+
const questions = [];
|
|
143
|
+
for (const [fieldId, rawField] of Object.entries(properties)) {
|
|
144
|
+
if (fieldId.endsWith("__note"))
|
|
145
|
+
continue;
|
|
146
|
+
if (!rawField || typeof rawField !== "object")
|
|
147
|
+
return null;
|
|
148
|
+
const header = typeof rawField.title === "string" && rawField.title.length > 0 ? rawField.title : fieldId;
|
|
149
|
+
const question = typeof rawField.description === "string" ? rawField.description : "";
|
|
150
|
+
if (rawField.type === "array") {
|
|
151
|
+
const options = readElicitationChoices(rawField.items?.anyOf).map((label) => ({ label, description: "" }));
|
|
152
|
+
if (options.length === 0)
|
|
153
|
+
return null;
|
|
154
|
+
questions.push({
|
|
155
|
+
id: fieldId,
|
|
156
|
+
header,
|
|
157
|
+
question,
|
|
158
|
+
options,
|
|
159
|
+
allowMultiple: true,
|
|
160
|
+
});
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (rawField.type === "string") {
|
|
164
|
+
const noteFieldId = Object.prototype.hasOwnProperty.call(properties, `${fieldId}__note`)
|
|
165
|
+
? `${fieldId}__note`
|
|
166
|
+
: undefined;
|
|
167
|
+
const options = readElicitationChoices(rawField.oneOf)
|
|
168
|
+
.filter((label) => label !== OTHER_OPTION_LABEL)
|
|
169
|
+
.map((label) => ({ label, description: "" }));
|
|
170
|
+
if (options.length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
questions.push({
|
|
173
|
+
id: fieldId,
|
|
174
|
+
header,
|
|
175
|
+
question,
|
|
176
|
+
options,
|
|
177
|
+
noteFieldId,
|
|
178
|
+
});
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
return questions.length > 0 ? questions : null;
|
|
184
|
+
}
|
|
185
|
+
export function roundResultToElicitationContent(questions, result) {
|
|
186
|
+
const content = {};
|
|
187
|
+
for (const question of questions) {
|
|
188
|
+
const answer = result.answers[question.id];
|
|
189
|
+
if (!answer)
|
|
190
|
+
continue;
|
|
191
|
+
if (question.allowMultiple) {
|
|
192
|
+
const selected = Array.isArray(answer.selected) ? answer.selected : [answer.selected];
|
|
193
|
+
content[question.id] = selected;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const selected = Array.isArray(answer.selected) ? answer.selected[0] ?? "" : answer.selected;
|
|
197
|
+
content[question.id] = selected;
|
|
198
|
+
if (question.noteFieldId && selected === OTHER_OPTION_LABEL && answer.notes.trim().length > 0) {
|
|
199
|
+
content[question.noteFieldId] = answer.notes.trim();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return content;
|
|
203
|
+
}
|
|
204
|
+
function buildElicitationPromptTitle(request, question) {
|
|
205
|
+
const parts = [
|
|
206
|
+
request.serverName ? `[${request.serverName}]` : "",
|
|
207
|
+
question.header,
|
|
208
|
+
question.question,
|
|
209
|
+
].filter((part) => part && part.trim().length > 0);
|
|
210
|
+
return parts.join("\n\n");
|
|
211
|
+
}
|
|
212
|
+
async function promptElicitationWithDialogs(request, questions, ui, signal) {
|
|
213
|
+
const content = {};
|
|
214
|
+
for (const question of questions) {
|
|
215
|
+
const title = buildElicitationPromptTitle(request, question);
|
|
216
|
+
if (question.allowMultiple) {
|
|
217
|
+
const selected = await ui.select(title, question.options.map((option) => option.label), {
|
|
218
|
+
allowMultiple: true,
|
|
219
|
+
signal,
|
|
220
|
+
});
|
|
221
|
+
if (Array.isArray(selected)) {
|
|
222
|
+
if (selected.length === 0)
|
|
223
|
+
return { action: "cancel" };
|
|
224
|
+
content[question.id] = selected;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (typeof selected === "string" && selected.length > 0) {
|
|
228
|
+
content[question.id] = [selected];
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
return { action: "cancel" };
|
|
232
|
+
}
|
|
233
|
+
const selected = await ui.select(title, [...question.options.map((option) => option.label), OTHER_OPTION_LABEL], { signal });
|
|
234
|
+
if (typeof selected !== "string" || selected.length === 0) {
|
|
235
|
+
return { action: "cancel" };
|
|
236
|
+
}
|
|
237
|
+
content[question.id] = selected;
|
|
238
|
+
if (question.noteFieldId && selected === OTHER_OPTION_LABEL) {
|
|
239
|
+
const note = await ui.input(`${question.header} note`, "Explain your answer", { signal });
|
|
240
|
+
if (note === undefined)
|
|
241
|
+
return { action: "cancel" };
|
|
242
|
+
if (note.trim().length > 0) {
|
|
243
|
+
content[question.noteFieldId] = note.trim();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return { action: "accept", content };
|
|
248
|
+
}
|
|
249
|
+
export function createClaudeCodeElicitationHandler(ui) {
|
|
250
|
+
if (!ui)
|
|
251
|
+
return undefined;
|
|
252
|
+
return async (request, { signal }) => {
|
|
253
|
+
if (request.mode === "url") {
|
|
254
|
+
return { action: "decline" };
|
|
255
|
+
}
|
|
256
|
+
const questions = parseAskUserQuestionsElicitation(request);
|
|
257
|
+
if (!questions) {
|
|
258
|
+
return { action: "decline" };
|
|
259
|
+
}
|
|
260
|
+
const interviewResult = await showInterviewRound(questions, { signal }, { ui }).catch(() => undefined);
|
|
261
|
+
if (interviewResult && Object.keys(interviewResult.answers).length > 0) {
|
|
262
|
+
return {
|
|
263
|
+
action: "accept",
|
|
264
|
+
content: roundResultToElicitationContent(questions, interviewResult),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return promptElicitationWithDialogs(request, questions, ui, signal);
|
|
268
|
+
};
|
|
269
|
+
}
|
|
127
270
|
// ---------------------------------------------------------------------------
|
|
128
271
|
// SDK options builder
|
|
129
272
|
// ---------------------------------------------------------------------------
|
|
@@ -133,7 +276,7 @@ export function makeStreamExhaustedErrorMessage(model, lastTextContent) {
|
|
|
133
276
|
* Extracted for testability — callers can verify session persistence,
|
|
134
277
|
* beta flags, and other configuration without mocking the full SDK.
|
|
135
278
|
*/
|
|
136
|
-
export function buildSdkOptions(modelId, prompt) {
|
|
279
|
+
export function buildSdkOptions(modelId, prompt, extraOptions = {}) {
|
|
137
280
|
const mcpServers = buildWorkflowMcpServers();
|
|
138
281
|
return {
|
|
139
282
|
pathToClaudeCodeExecutable: getClaudePath(),
|
|
@@ -147,6 +290,7 @@ export function buildSdkOptions(modelId, prompt) {
|
|
|
147
290
|
systemPrompt: { type: "preset", preset: "claude_code" },
|
|
148
291
|
...(mcpServers ? { mcpServers } : {}),
|
|
149
292
|
betas: modelId.includes("sonnet") ? ["context-1m-2025-08-07"] : [],
|
|
293
|
+
...extraOptions,
|
|
150
294
|
};
|
|
151
295
|
}
|
|
152
296
|
function normalizeToolResultContent(content) {
|
|
@@ -272,7 +416,11 @@ async function pumpSdkMessages(model, context, options, stream) {
|
|
|
272
416
|
options.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
273
417
|
}
|
|
274
418
|
const prompt = buildPromptFromContext(context);
|
|
275
|
-
const sdkOpts = buildSdkOptions(modelId, prompt
|
|
419
|
+
const sdkOpts = buildSdkOptions(modelId, prompt, typeof options?.extensionUIContext === "object"
|
|
420
|
+
? {
|
|
421
|
+
onElicitation: createClaudeCodeElicitationHandler(options?.extensionUIContext),
|
|
422
|
+
}
|
|
423
|
+
: {});
|
|
276
424
|
const queryResult = sdk.query({
|
|
277
425
|
prompt,
|
|
278
426
|
options: {
|
|
@@ -876,7 +876,7 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base) {
|
|
|
876
876
|
milestoneId: mid,
|
|
877
877
|
milestoneTitle: midTitle,
|
|
878
878
|
inlinedTemplates: discussTemplates,
|
|
879
|
-
structuredQuestionsAvailable: "
|
|
879
|
+
structuredQuestionsAvailable: "false",
|
|
880
880
|
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
881
881
|
fastPathInstruction: "",
|
|
882
882
|
});
|
|
@@ -1319,7 +1319,9 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
|
|
|
1319
1319
|
try {
|
|
1320
1320
|
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
1321
1321
|
if (isDbAvailable()) {
|
|
1322
|
-
sliceIds = getMilestoneSlices(mid)
|
|
1322
|
+
sliceIds = getMilestoneSlices(mid)
|
|
1323
|
+
.filter(s => s.status !== "skipped")
|
|
1324
|
+
.map(s => s.id);
|
|
1323
1325
|
}
|
|
1324
1326
|
}
|
|
1325
1327
|
catch (err) {
|
|
@@ -1415,7 +1417,9 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
|
|
|
1415
1417
|
try {
|
|
1416
1418
|
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
1417
1419
|
if (isDbAvailable()) {
|
|
1418
|
-
valSliceIds = getMilestoneSlices(mid)
|
|
1420
|
+
valSliceIds = getMilestoneSlices(mid)
|
|
1421
|
+
.filter(s => s.status !== "skipped")
|
|
1422
|
+
.map(s => s.id);
|
|
1419
1423
|
}
|
|
1420
1424
|
}
|
|
1421
1425
|
catch (err) {
|
|
@@ -37,9 +37,9 @@ import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
|
|
|
37
37
|
import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
|
|
38
38
|
import { logWarning } from "./workflow-logger.js";
|
|
39
39
|
import { homedir } from "node:os";
|
|
40
|
-
import { join
|
|
40
|
+
import { join } from "node:path";
|
|
41
|
+
import { pathToFileURL } from "node:url";
|
|
41
42
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
|
|
42
|
-
import { createRequire } from "node:module";
|
|
43
43
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
44
44
|
import { autoCommitCurrentBranch, captureIntegrationBranch, detectWorktreeName, getCurrentBranch, getMainBranch, setActiveMilestoneId, } from "./worktree.js";
|
|
45
45
|
import { GitServiceImpl } from "./git-service.js";
|
|
@@ -1021,13 +1021,17 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1021
1021
|
restoreHookState(s.basePath);
|
|
1022
1022
|
// Re-sync managed resources on resume so long-lived auto sessions pick up
|
|
1023
1023
|
// bundled extension updates before resume-time verification/state logic runs.
|
|
1024
|
+
// GSD_PKG_ROOT is set by loader.ts and points to the gsd-pi package root.
|
|
1025
|
+
// The relative import ("../../../resource-loader.js") only works from the source
|
|
1026
|
+
// tree; deployed extensions live at ~/.gsd/agent/extensions/gsd/ where the
|
|
1027
|
+
// relative path resolves to ~/.gsd/agent/resource-loader.js which doesn't exist.
|
|
1028
|
+
// Using GSD_PKG_ROOT constructs a correct absolute path in both contexts (#3949).
|
|
1024
1029
|
const agentDir = process.env.GSD_CODING_AGENT_DIR || join(process.env.GSD_HOME || homedir(), ".gsd", "agent");
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
const
|
|
1030
|
-
const { initResources } = await import(join(pkgRoot, "dist", "resource-loader.js"));
|
|
1030
|
+
const pkgRoot = process.env.GSD_PKG_ROOT;
|
|
1031
|
+
const resourceLoaderPath = pkgRoot
|
|
1032
|
+
? pathToFileURL(join(pkgRoot, "dist", "resource-loader.js")).href
|
|
1033
|
+
: new URL("../../../resource-loader.js", import.meta.url).href;
|
|
1034
|
+
const { initResources } = await import(resourceLoaderPath);
|
|
1031
1035
|
initResources(agentDir);
|
|
1032
1036
|
// Open the project DB before rebuild/derive so resume uses DB-backed
|
|
1033
1037
|
// state instead of falling back to stale markdown parsing (#2940).
|
|
@@ -16,6 +16,7 @@ import { deriveState } from "../state.js";
|
|
|
16
16
|
import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
|
|
17
17
|
import { toPosixPath } from "../../shared/mod.js";
|
|
18
18
|
import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../../cmux/index.js";
|
|
19
|
+
import { autoEnableCmuxPreferences } from "../commands-cmux.js";
|
|
19
20
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
20
21
|
/**
|
|
21
22
|
* Bundled skill triggers — resolved dynamically at runtime instead of
|
|
@@ -64,10 +65,13 @@ export async function buildBeforeAgentStartResult(event, ctx) {
|
|
|
64
65
|
shortcutDashboard: formatShortcut("Ctrl+Alt+G"),
|
|
65
66
|
shortcutShell: formatShortcut("Ctrl+Alt+B"),
|
|
66
67
|
});
|
|
67
|
-
|
|
68
|
+
let loadedPreferences = loadEffectiveGSDPreferences();
|
|
68
69
|
if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
|
|
69
70
|
markCmuxPromptShown();
|
|
70
|
-
|
|
71
|
+
if (autoEnableCmuxPreferences()) {
|
|
72
|
+
loadedPreferences = loadEffectiveGSDPreferences();
|
|
73
|
+
ctx.ui.notify("cmux detected — auto-enabled. Run /gsd cmux off to disable.", "info");
|
|
74
|
+
}
|
|
71
75
|
}
|
|
72
76
|
let preferenceBlock = "";
|
|
73
77
|
if (loadedPreferences) {
|
|
@@ -1,8 +1,37 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { clearCmuxSidebar, CmuxClient, detectCmuxEnvironment, resolveCmuxConfig } from "../cmux/index.js";
|
|
3
3
|
import { saveFile } from "./files.js";
|
|
4
4
|
import { getProjectGSDPreferencesPath, loadEffectiveGSDPreferences, loadProjectGSDPreferences, } from "./preferences.js";
|
|
5
5
|
import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./commands-prefs-wizard.js";
|
|
6
|
+
/**
|
|
7
|
+
* Auto-enable cmux in project preferences when detected but never configured.
|
|
8
|
+
* Called at boot (before agent start) — no ExtensionCommandContext needed.
|
|
9
|
+
* Returns true if preferences were written, false if skipped.
|
|
10
|
+
*/
|
|
11
|
+
export function autoEnableCmuxPreferences() {
|
|
12
|
+
const path = getProjectGSDPreferencesPath();
|
|
13
|
+
if (!existsSync(path))
|
|
14
|
+
return false;
|
|
15
|
+
const existing = loadProjectGSDPreferences();
|
|
16
|
+
const prefs = existing?.preferences ? { ...existing.preferences } : { version: 1 };
|
|
17
|
+
prefs.cmux = {
|
|
18
|
+
enabled: true,
|
|
19
|
+
notifications: true,
|
|
20
|
+
sidebar: true,
|
|
21
|
+
splits: false,
|
|
22
|
+
browser: false,
|
|
23
|
+
...(prefs.cmux ?? {}),
|
|
24
|
+
};
|
|
25
|
+
prefs.cmux.enabled = true;
|
|
26
|
+
prefs.version = prefs.version || 1;
|
|
27
|
+
const frontmatter = serializePreferencesToFrontmatter(prefs);
|
|
28
|
+
let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
|
|
29
|
+
const preserved = extractBodyAfterFrontmatter(readFileSync(path, "utf-8"));
|
|
30
|
+
if (preserved)
|
|
31
|
+
body = preserved;
|
|
32
|
+
writeFileSync(path, `---\n${frontmatter}---${body}`, "utf-8");
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
6
35
|
function extractBodyAfterFrontmatter(content) {
|
|
7
36
|
const start = content.startsWith("---\n") ? 4 : content.startsWith("---\r\n") ? 5 : -1;
|
|
8
37
|
if (start === -1)
|
|
@@ -15,6 +15,26 @@ import { isAutoActive, checkRemoteAutoSession } from "./auto.js";
|
|
|
15
15
|
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
16
16
|
import { projectRoot } from "./commands/context.js";
|
|
17
17
|
import { loadPrompt } from "./prompt-loader.js";
|
|
18
|
+
const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/gsd-pi/latest";
|
|
19
|
+
const UPDATE_FETCH_TIMEOUT_MS = 5000;
|
|
20
|
+
async function fetchLatestVersionForCommand() {
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const timeout = setTimeout(() => controller.abort(), UPDATE_FETCH_TIMEOUT_MS);
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(UPDATE_REGISTRY_URL, { signal: controller.signal });
|
|
25
|
+
if (!res.ok)
|
|
26
|
+
return null;
|
|
27
|
+
const data = (await res.json());
|
|
28
|
+
const latest = typeof data.version === "string" ? data.version.trim().replace(/^v/, "") : "";
|
|
29
|
+
return latest.length > 0 ? latest : null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
clearTimeout(timeout);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
18
38
|
export function dispatchDoctorHeal(pi, scope, reportText, structuredIssues) {
|
|
19
39
|
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md");
|
|
20
40
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
@@ -311,14 +331,8 @@ export async function handleUpdate(ctx) {
|
|
|
311
331
|
const NPM_PACKAGE = "gsd-pi";
|
|
312
332
|
const current = process.env.GSD_VERSION || "0.0.0";
|
|
313
333
|
ctx.ui.notify(`Current version: v${current}\nChecking npm registry...`, "info");
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
latest = execSync(`npm view ${NPM_PACKAGE} version`, {
|
|
317
|
-
encoding: "utf-8",
|
|
318
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
319
|
-
}).trim();
|
|
320
|
-
}
|
|
321
|
-
catch {
|
|
334
|
+
const latest = await fetchLatestVersionForCommand();
|
|
335
|
+
if (!latest) {
|
|
322
336
|
ctx.ui.notify("Failed to reach npm registry. Check your network connection.", "error");
|
|
323
337
|
return;
|
|
324
338
|
}
|
|
@@ -6,6 +6,18 @@ import { deriveState } from "./state.js";
|
|
|
6
6
|
import { readEvents } from "./workflow-events.js";
|
|
7
7
|
import { renderAllProjections } from "./workflow-projections.js";
|
|
8
8
|
export async function checkEngineHealth(basePath, issues, fixesApplied) {
|
|
9
|
+
const dbPath = join(basePath, ".gsd", "gsd.db");
|
|
10
|
+
if (!isDbAvailable() && existsSync(dbPath)) {
|
|
11
|
+
issues.push({
|
|
12
|
+
severity: "warning",
|
|
13
|
+
code: "db_unavailable",
|
|
14
|
+
scope: "project",
|
|
15
|
+
unitId: "project",
|
|
16
|
+
message: "Database unavailable — using filesystem state derivation (degraded mode). State queries may be slower and less reliable.",
|
|
17
|
+
file: ".gsd/gsd.db",
|
|
18
|
+
fixable: false,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
9
21
|
// ── DB constraint violation detection (full doctor only, not pre-dispatch per D-10) ──
|
|
10
22
|
try {
|
|
11
23
|
if (isDbAvailable()) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
function matchesScope(unitId, scope) {
|
|
2
2
|
if (!scope)
|
|
3
3
|
return true;
|
|
4
|
+
if (unitId === "project" || unitId === "environment")
|
|
5
|
+
return true;
|
|
4
6
|
return unitId === scope || unitId.startsWith(`${scope}/`) || unitId.startsWith(`${scope}`);
|
|
5
7
|
}
|
|
6
8
|
export function summarizeDoctorIssues(issues) {
|
|
@@ -35,7 +35,7 @@ import { findMilestoneIds, nextMilestoneId, reserveMilestoneId, getReservedMiles
|
|
|
35
35
|
import { parkMilestone, discardMilestone } from "./milestone-actions.js";
|
|
36
36
|
import { selectAndApplyModel } from "./auto-model-selection.js";
|
|
37
37
|
import { DISCUSS_TOOLS_ALLOWLIST } from "./constants.js";
|
|
38
|
-
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForGuidedUnit, } from "./workflow-mcp.js";
|
|
38
|
+
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForGuidedUnit, supportsStructuredQuestions, } from "./workflow-mcp.js";
|
|
39
39
|
import { runPreparation, formatCodebaseBrief, formatPriorContextBrief, } from "./preparation.js";
|
|
40
40
|
// ─── Re-exports (preserve public API for existing importers) ────────────────
|
|
41
41
|
export { MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId, extractMilestoneSeq, parseMilestoneId, milestoneIdSort, maxMilestoneNum, findMilestoneIds, reserveMilestoneId, claimReservedId, getReservedMilestoneIds, clearReservedMilestoneIds, } from "./milestone-ids.js";
|
|
@@ -294,6 +294,16 @@ async function dispatchWorkflow(pi, note, customType = "gsd-run", ctx, unitType)
|
|
|
294
294
|
pi.setActiveTools(savedTools);
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
|
+
function getStructuredQuestionsAvailability(pi, ctx) {
|
|
298
|
+
if (!ctx)
|
|
299
|
+
return "false";
|
|
300
|
+
const provider = ctx.model?.provider;
|
|
301
|
+
const authMode = provider ? ctx.modelRegistry.getProviderAuthMode(provider) : undefined;
|
|
302
|
+
return supportsStructuredQuestions(pi.getActiveTools(), {
|
|
303
|
+
authMode,
|
|
304
|
+
baseUrl: ctx.model?.baseUrl,
|
|
305
|
+
}) ? "true" : "false";
|
|
306
|
+
}
|
|
297
307
|
/**
|
|
298
308
|
* Resolve a model ID string to a model object from available models.
|
|
299
309
|
* Handles "provider/model" and bare ID formats.
|
|
@@ -600,7 +610,7 @@ export async function showDiscuss(ctx, pi, basePath) {
|
|
|
600
610
|
});
|
|
601
611
|
if (choice === "discuss_draft") {
|
|
602
612
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
603
|
-
const structuredQuestionsAvailable = pi
|
|
613
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
604
614
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
605
615
|
milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
606
616
|
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
@@ -614,7 +624,7 @@ export async function showDiscuss(ctx, pi, basePath) {
|
|
|
614
624
|
}
|
|
615
625
|
else if (choice === "discuss_fresh") {
|
|
616
626
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
617
|
-
const structuredQuestionsAvailable = pi
|
|
627
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
618
628
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: mid, step: false, createdAt: Date.now() });
|
|
619
629
|
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
620
630
|
milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
@@ -757,7 +767,7 @@ export async function showDiscuss(ctx, pi, basePath) {
|
|
|
757
767
|
if (confirm !== "rediscuss")
|
|
758
768
|
continue;
|
|
759
769
|
}
|
|
760
|
-
const sqAvail = pi
|
|
770
|
+
const sqAvail = getStructuredQuestionsAvailability(pi, ctx);
|
|
761
771
|
const prompt = await buildDiscussSlicePrompt(mid, chosen.id, chosen.title, basePath, { rediscuss: isRediscuss, structuredQuestionsAvailable: sqAvail });
|
|
762
772
|
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-slice");
|
|
763
773
|
// Wait for the discuss session to finish, then loop back to the picker
|
|
@@ -848,7 +858,7 @@ async function dispatchDiscussForMilestone(ctx, pi, basePath, mid, milestoneTitl
|
|
|
848
858
|
].join("\n")
|
|
849
859
|
: "";
|
|
850
860
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
851
|
-
const structuredQuestionsAvailable = pi
|
|
861
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
852
862
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
853
863
|
milestoneId: mid,
|
|
854
864
|
milestoneTitle,
|
|
@@ -1237,7 +1247,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1237
1247
|
});
|
|
1238
1248
|
if (choice === "discuss_draft") {
|
|
1239
1249
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1240
|
-
const structuredQuestionsAvailable = pi
|
|
1250
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1241
1251
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1242
1252
|
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
1243
1253
|
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
@@ -1251,7 +1261,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1251
1261
|
}
|
|
1252
1262
|
else if (choice === "discuss_fresh") {
|
|
1253
1263
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1254
|
-
const structuredQuestionsAvailable = pi
|
|
1264
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1255
1265
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId, step: stepMode, createdAt: Date.now() });
|
|
1256
1266
|
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
1257
1267
|
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
@@ -1342,7 +1352,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1342
1352
|
}
|
|
1343
1353
|
else if (choice === "discuss") {
|
|
1344
1354
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1345
|
-
const structuredQuestionsAvailable = pi
|
|
1355
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1346
1356
|
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
1347
1357
|
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
1348
1358
|
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
@@ -1480,7 +1490,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1480
1490
|
}), "gsd-run", ctx, "plan-slice");
|
|
1481
1491
|
}
|
|
1482
1492
|
else if (choice === "discuss") {
|
|
1483
|
-
const sqAvail = pi
|
|
1493
|
+
const sqAvail = getStructuredQuestionsAvailability(pi, ctx);
|
|
1484
1494
|
await dispatchWorkflow(pi, await buildDiscussSlicePrompt(milestoneId, sliceId, sliceTitle, basePath, { rediscuss: hasContext, structuredQuestionsAvailable: sqAvail }), "gsd-run", ctx, "discuss-slice");
|
|
1485
1495
|
}
|
|
1486
1496
|
else if (choice === "research") {
|
|
@@ -216,9 +216,9 @@ function extractPathFromAnnotation(raw) {
|
|
|
216
216
|
const trimmed = raw.trim();
|
|
217
217
|
if (!trimmed)
|
|
218
218
|
return trimmed;
|
|
219
|
-
const backtickMatch = trimmed.match(
|
|
219
|
+
const backtickMatch = trimmed.match(/^(`+)([^`]+)\1(?:(?:\s+[—–-]\s+.+)|(?:\s+\([^()]+\)))?$/);
|
|
220
220
|
if (backtickMatch) {
|
|
221
|
-
return backtickMatch[
|
|
221
|
+
return backtickMatch[2].trim();
|
|
222
222
|
}
|
|
223
223
|
const annotatedMatch = trimmed.match(/^(.+?)\s+[—–-]\s+.+$/);
|
|
224
224
|
if (annotatedMatch) {
|