gsd-pi 2.76.0-dev.4100bd590 → 2.76.0-dev.76f9a2dc5
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/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/extensions/gsd/auto/phases.js +4 -1
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto-model-selection.js +13 -2
- package/dist/resources/extensions/gsd/auto-start.js +12 -7
- package/dist/resources/extensions/gsd/auto.js +4 -1
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -20
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -20
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +76 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +86 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +4 -0
- package/src/resources/extensions/gsd/auto/session.ts +7 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -1
- package/src/resources/extensions/gsd/auto-start.ts +12 -7
- package/src/resources/extensions/gsd/auto.ts +4 -1
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → UMCfv_sVnLXawpUAjvArc}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → UMCfv_sVnLXawpUAjvArc}/_ssgManifest.js +0 -0
|
@@ -21,6 +21,6 @@ export declare function getNewerManagedResourceVersion(agentDir: string, current
|
|
|
21
21
|
*
|
|
22
22
|
* Inspectable: `ls ~/.gsd/agent/extensions/`
|
|
23
23
|
*/
|
|
24
|
-
export declare function initResources(agentDir: string): void;
|
|
24
|
+
export declare function initResources(agentDir: string, skillsDir?: string): void;
|
|
25
25
|
export declare function hasStaleCompiledExtensionSiblings(extensionsDir: string, sourceDir?: string): boolean;
|
|
26
26
|
export declare function buildResourceLoader(agentDir: string): DefaultResourceLoader;
|
package/dist/resource-loader.js
CHANGED
|
@@ -506,7 +506,7 @@ function pruneRemovedBundledExtensions(manifest, agentDir) {
|
|
|
506
506
|
*
|
|
507
507
|
* Inspectable: `ls ~/.gsd/agent/extensions/`
|
|
508
508
|
*/
|
|
509
|
-
export function initResources(agentDir) {
|
|
509
|
+
export function initResources(agentDir, skillsDir = join(homedir(), '.agents', 'skills')) {
|
|
510
510
|
mkdirSync(agentDir, { recursive: true });
|
|
511
511
|
const currentVersion = getBundledGsdVersion();
|
|
512
512
|
const manifest = readManagedResourceManifest(agentDir);
|
|
@@ -538,13 +538,7 @@ export function initResources(agentDir) {
|
|
|
538
538
|
// Sync bundled resources — overwrite so updates land on next launch.
|
|
539
539
|
syncResourceDir(bundledExtensionsDir, join(agentDir, 'extensions'));
|
|
540
540
|
syncResourceDir(join(resourcesDir, 'agents'), join(agentDir, 'agents'));
|
|
541
|
-
|
|
542
|
-
// skills.sh CLI (`npx skills add <repo>`) into ~/.agents/skills/ which
|
|
543
|
-
// is the industry-standard Agent Skills ecosystem directory.
|
|
544
|
-
//
|
|
545
|
-
// Migration from the legacy ~/.gsd/agent/skills/ directory is handled
|
|
546
|
-
// above the manifest check so it runs on every launch (including retries
|
|
547
|
-
// after partial copy failures).
|
|
541
|
+
syncResourceDir(join(resourcesDir, 'skills'), skillsDir);
|
|
548
542
|
// Sync GSD-WORKFLOW.md to agentDir as a fallback for when GSD_WORKFLOW_PATH
|
|
549
543
|
// env var is not set (e.g. fork/dev builds, alternative entry points).
|
|
550
544
|
const workflowSrc = join(resourcesDir, 'GSD-WORKFLOW.md');
|
|
@@ -1094,7 +1094,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1094
1094
|
logWarning("engine", "Prompt reorder failed", { error: msg });
|
|
1095
1095
|
}
|
|
1096
1096
|
// Select and apply model (with tier escalation on retry — normal units only)
|
|
1097
|
-
const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier }, undefined, s.manualSessionModelOverride);
|
|
1097
|
+
const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier }, undefined, s.manualSessionModelOverride, s.autoModeStartThinkingLevel);
|
|
1098
1098
|
s.currentUnitRouting =
|
|
1099
1099
|
modelResult.routing;
|
|
1100
1100
|
s.currentUnitModel =
|
|
@@ -1107,6 +1107,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1107
1107
|
if (match) {
|
|
1108
1108
|
const ok = await pi.setModel(match, { persist: false });
|
|
1109
1109
|
if (ok) {
|
|
1110
|
+
if (s.autoModeStartThinkingLevel) {
|
|
1111
|
+
pi.setThinkingLevel(s.autoModeStartThinkingLevel);
|
|
1112
|
+
}
|
|
1110
1113
|
s.currentUnitModel = match;
|
|
1111
1114
|
ctx.ui.notify(`Hook model override: ${match.provider}/${match.id}`, "info");
|
|
1112
1115
|
}
|
|
@@ -65,6 +65,8 @@ export class AutoSession {
|
|
|
65
65
|
currentDispatchedModelId = null;
|
|
66
66
|
originalModelId = null;
|
|
67
67
|
originalModelProvider = null;
|
|
68
|
+
autoModeStartThinkingLevel = null;
|
|
69
|
+
originalThinkingLevel = null;
|
|
68
70
|
lastBudgetAlertLevel = 0;
|
|
69
71
|
// ── Recovery ─────────────────────────────────────────────────────────────
|
|
70
72
|
pendingCrashRecovery = null;
|
|
@@ -177,6 +179,8 @@ export class AutoSession {
|
|
|
177
179
|
this.currentDispatchedModelId = null;
|
|
178
180
|
this.originalModelId = null;
|
|
179
181
|
this.originalModelProvider = null;
|
|
182
|
+
this.autoModeStartThinkingLevel = null;
|
|
183
|
+
this.originalThinkingLevel = null;
|
|
180
184
|
this.lastBudgetAlertLevel = 0;
|
|
181
185
|
// Recovery
|
|
182
186
|
this.pendingCrashRecovery = null;
|
|
@@ -13,6 +13,11 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
13
13
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
14
14
|
import { applyModelPolicyFilter } from "./uok/model-policy.js";
|
|
15
15
|
import { isModelBlocked } from "./blocked-models.js";
|
|
16
|
+
function reapplyThinkingLevel(pi, level) {
|
|
17
|
+
if (!level)
|
|
18
|
+
return;
|
|
19
|
+
pi.setThinkingLevel(level);
|
|
20
|
+
}
|
|
16
21
|
export function resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode = true) {
|
|
17
22
|
const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
18
23
|
if (explicitConfig) {
|
|
@@ -58,7 +63,9 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
|
|
|
58
63
|
* Dynamic routing only applies in auto-mode where cost optimization is expected. (#3962) */
|
|
59
64
|
isAutoMode = true,
|
|
60
65
|
/** Explicit /gsd model pin captured at bootstrap for long-running auto loops. */
|
|
61
|
-
sessionModelOverride
|
|
66
|
+
sessionModelOverride,
|
|
67
|
+
/** Thinking level captured at auto-mode start and re-applied after model swaps. */
|
|
68
|
+
autoModeStartThinkingLevel) {
|
|
62
69
|
const uokFlags = resolveUokFlags(prefs);
|
|
63
70
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
64
71
|
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
@@ -280,6 +287,7 @@ sessionModelOverride) {
|
|
|
280
287
|
const ok = await pi.setModel(model, { persist: false });
|
|
281
288
|
if (ok) {
|
|
282
289
|
appliedModel = model;
|
|
290
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
283
291
|
// ADR-005: Adjust active tool set for the selected model's provider capabilities.
|
|
284
292
|
// Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
|
|
285
293
|
const activeToolNames = pi.getActiveTools();
|
|
@@ -346,12 +354,15 @@ sessionModelOverride) {
|
|
|
346
354
|
const byId = availableModels.find(m => m.id === autoModeStartModel.id && !isModelBlocked(basePath, m.provider, m.id));
|
|
347
355
|
if (byId) {
|
|
348
356
|
const fallbackOk = await pi.setModel(byId, { persist: false });
|
|
349
|
-
if (fallbackOk)
|
|
357
|
+
if (fallbackOk) {
|
|
350
358
|
appliedModel = byId;
|
|
359
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
360
|
+
}
|
|
351
361
|
}
|
|
352
362
|
}
|
|
353
363
|
else {
|
|
354
364
|
appliedModel = startModel;
|
|
365
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
355
366
|
}
|
|
356
367
|
}
|
|
357
368
|
}
|
|
@@ -190,8 +190,8 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
190
190
|
//
|
|
191
191
|
// Precedence:
|
|
192
192
|
// 1) Explicit session override via /gsd model (this session)
|
|
193
|
-
// 2)
|
|
194
|
-
// 3)
|
|
193
|
+
// 2) Current session model from settings/session restore (if provider ready)
|
|
194
|
+
// 3) GSD model preferences from PREFERENCES.md (validated against live auth)
|
|
195
195
|
//
|
|
196
196
|
// This preserves #3517 defaults while honoring explicit runtime model
|
|
197
197
|
// selection for subsequent /gsd runs in the same session.
|
|
@@ -224,11 +224,14 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
const sessionModelReady = ctx.model && ctx.modelRegistry.isProviderRequestReady(ctx.model.provider);
|
|
227
|
+
const currentSessionModel = (sessionModelReady && ctx.model)
|
|
228
|
+
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
229
|
+
: null;
|
|
230
|
+
const startThinkingSnapshot = pi.getThinkingLevel();
|
|
227
231
|
const startModelSnapshot = manualSessionOverride
|
|
232
|
+
?? currentSessionModel
|
|
228
233
|
?? validatedPreferredModel
|
|
229
|
-
??
|
|
230
|
-
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
231
|
-
: null);
|
|
234
|
+
?? null;
|
|
232
235
|
try {
|
|
233
236
|
// Validate GSD_PROJECT_ID early so the user gets immediate feedback
|
|
234
237
|
const customProjectId = process.env.GSD_PROJECT_ID;
|
|
@@ -506,8 +509,9 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
506
509
|
s.pendingQuickTasks = [];
|
|
507
510
|
s.currentUnit = null;
|
|
508
511
|
s.currentMilestoneId = state.activeMilestone?.id ?? null;
|
|
509
|
-
s.originalModelId = ctx.model?.id ?? null;
|
|
510
|
-
s.originalModelProvider = ctx.model?.provider ?? null;
|
|
512
|
+
s.originalModelId = startModelSnapshot?.id ?? ctx.model?.id ?? null;
|
|
513
|
+
s.originalModelProvider = startModelSnapshot?.provider ?? ctx.model?.provider ?? null;
|
|
514
|
+
s.originalThinkingLevel = startThinkingSnapshot ?? null;
|
|
511
515
|
// Register SIGTERM handler
|
|
512
516
|
registerSigtermHandler(base);
|
|
513
517
|
// Capture integration branch
|
|
@@ -608,6 +612,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
608
612
|
id: startModelSnapshot.id,
|
|
609
613
|
};
|
|
610
614
|
}
|
|
615
|
+
s.autoModeStartThinkingLevel = startThinkingSnapshot ?? null;
|
|
611
616
|
s.manualSessionModelOverride = manualSessionOverride ?? null;
|
|
612
617
|
// Apply worker model override from parallel orchestrator (#worker-model).
|
|
613
618
|
// GSD_WORKER_MODEL is injected by the coordinator when parallel.worker_model
|
|
@@ -695,13 +695,16 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
695
695
|
catch (err) { /* non-fatal */
|
|
696
696
|
logWarning("engine", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
697
697
|
}
|
|
698
|
-
// ── Step 13: Restore original model (before reset clears IDs) ──
|
|
698
|
+
// ── Step 13: Restore original model + thinking (before reset clears IDs) ──
|
|
699
699
|
try {
|
|
700
700
|
if (pi && ctx && s.originalModelId && s.originalModelProvider) {
|
|
701
701
|
const original = ctx.modelRegistry.find(s.originalModelProvider, s.originalModelId);
|
|
702
702
|
if (original)
|
|
703
703
|
await pi.setModel(original);
|
|
704
704
|
}
|
|
705
|
+
if (pi && s.originalThinkingLevel) {
|
|
706
|
+
pi.setThinkingLevel(s.originalThinkingLevel);
|
|
707
|
+
}
|
|
705
708
|
}
|
|
706
709
|
catch (e) {
|
|
707
710
|
debugLog("stop-cleanup-model", { error: e instanceof Error ? e.message : String(e) });
|
|
@@ -8,10 +8,12 @@ import { getAdaptiveTierAdjustment } from "./routing-history.js";
|
|
|
8
8
|
import { parseUnitId } from "./unit-id.js";
|
|
9
9
|
// ─── Unit Type → Default Tier Mapping ────────────────────────────────────────
|
|
10
10
|
const UNIT_TYPE_TIERS = {
|
|
11
|
-
// Tier 1 — Light:
|
|
12
|
-
"complete-slice": "light",
|
|
11
|
+
// Tier 1 — Light: compact verification turns
|
|
13
12
|
"run-uat": "light",
|
|
14
|
-
// Tier 2 — Standard: research, routine discussion
|
|
13
|
+
// Tier 2 — Standard: research, routine discussion, slice completion
|
|
14
|
+
// complete-slice can carry large inlined context; avoid routing it to the
|
|
15
|
+
// cheapest "light" model by default (#4520).
|
|
16
|
+
"complete-slice": "standard",
|
|
15
17
|
"discuss-milestone": "standard",
|
|
16
18
|
"discuss-slice": "standard",
|
|
17
19
|
"research-milestone": "standard",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { showNextAction } from "../shared/tui.js";
|
|
11
|
-
import { nativeInit } from "./native-git-bridge.js";
|
|
11
|
+
import { nativeInit, nativeAddAll, nativeCommit } from "./native-git-bridge.js";
|
|
12
12
|
import { ensureGitignore, untrackRuntimeFiles } from "./gitignore.js";
|
|
13
13
|
import { gsdRoot } from "./paths.js";
|
|
14
14
|
import { assertSafeDirectory } from "./validate-directory.js";
|
|
@@ -40,6 +40,7 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
40
40
|
ctx.ui.notify(`Project detected:\n${detectionSummary.join("\n")}`, "info");
|
|
41
41
|
}
|
|
42
42
|
// ── Step 2: Git setup ──────────────────────────────────────────────────────
|
|
43
|
+
let didInitGit = false;
|
|
43
44
|
if (!signals.isGitRepo) {
|
|
44
45
|
const gitChoice = await showNextAction(ctx, {
|
|
45
46
|
title: "GSD — Project Setup",
|
|
@@ -54,6 +55,7 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
54
55
|
return { completed: false, bootstrapped: false };
|
|
55
56
|
if (gitChoice === "init_git") {
|
|
56
57
|
nativeInit(basePath, prefs.mainBranch);
|
|
58
|
+
didInitGit = true;
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
else {
|
|
@@ -244,6 +246,18 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
244
246
|
// Ensure .gitignore
|
|
245
247
|
ensureGitignore(basePath);
|
|
246
248
|
untrackRuntimeFiles(basePath);
|
|
249
|
+
// Create initial commit so git log and git worktree work immediately (#4530).
|
|
250
|
+
// Without this, the branch is "unborn" (zero commits) and downstream operations
|
|
251
|
+
// like `git log` and `git worktree add` fail.
|
|
252
|
+
if (didInitGit) {
|
|
253
|
+
try {
|
|
254
|
+
nativeAddAll(basePath);
|
|
255
|
+
nativeCommit(basePath, "chore: init project");
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// Non-fatal — user can commit manually; don't block project init
|
|
259
|
+
}
|
|
260
|
+
}
|
|
247
261
|
// Auto-generate codebase map for instant agent orientation
|
|
248
262
|
try {
|
|
249
263
|
const result = generateCodebaseMap(basePath);
|
|
@@ -22,6 +22,27 @@ import { join, dirname } from "node:path";
|
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
23
|
import { homedir } from "node:os";
|
|
24
24
|
import { logWarning } from "./workflow-logger.js";
|
|
25
|
+
function hasRequiredExtensionAssets(rootDir, exists = existsSync) {
|
|
26
|
+
return (exists(join(rootDir, "prompts")) &&
|
|
27
|
+
exists(join(rootDir, "templates", "task-summary.md")));
|
|
28
|
+
}
|
|
29
|
+
export function resolveExtensionDirFromCandidates(moduleDir, agentGsdDir, exists = existsSync) {
|
|
30
|
+
const moduleUsable = hasRequiredExtensionAssets(moduleDir, exists);
|
|
31
|
+
const agentUsable = hasRequiredExtensionAssets(agentGsdDir, exists);
|
|
32
|
+
// Prefer the user-local extension tree when both are valid. This avoids
|
|
33
|
+
// leaking npm/global-install paths into prompts on Windows.
|
|
34
|
+
if (agentUsable)
|
|
35
|
+
return agentGsdDir;
|
|
36
|
+
if (moduleUsable)
|
|
37
|
+
return moduleDir;
|
|
38
|
+
// Degraded fallback: if required template is missing in both locations,
|
|
39
|
+
// keep previous behavior and prefer whichever still has prompts/.
|
|
40
|
+
if (exists(join(moduleDir, "prompts")))
|
|
41
|
+
return moduleDir;
|
|
42
|
+
if (exists(join(agentGsdDir, "prompts")))
|
|
43
|
+
return agentGsdDir;
|
|
44
|
+
return moduleDir;
|
|
45
|
+
}
|
|
25
46
|
/**
|
|
26
47
|
* Resolve the GSD extension directory.
|
|
27
48
|
*
|
|
@@ -34,15 +55,9 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
34
55
|
*/
|
|
35
56
|
function resolveExtensionDir() {
|
|
36
57
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
37
|
-
if (existsSync(join(moduleDir, "prompts")))
|
|
38
|
-
return moduleDir;
|
|
39
|
-
// Fallback: user-local agent directory
|
|
40
58
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
41
59
|
const agentGsdDir = join(gsdHome, "agent", "extensions", "gsd");
|
|
42
|
-
|
|
43
|
-
return agentGsdDir;
|
|
44
|
-
// Last resort: return the module dir (warmCache will silently handle the miss)
|
|
45
|
-
return moduleDir;
|
|
60
|
+
return resolveExtensionDirFromCandidates(moduleDir, agentGsdDir);
|
|
46
61
|
}
|
|
47
62
|
const __extensionDir = resolveExtensionDir();
|
|
48
63
|
const promptsDir = join(__extensionDir, "prompts");
|
|
@@ -62,7 +62,7 @@ export function validateFileChanges(basePath, expectedOutput, plannedFiles) {
|
|
|
62
62
|
// ─── Internals ──────────────────────────────────────────────────────────────
|
|
63
63
|
function getChangedFilesFromLastCommit(basePath) {
|
|
64
64
|
try {
|
|
65
|
-
const result = execFileSync("git", ["diff", "--
|
|
65
|
+
const result = execFileSync("git", ["diff-tree", "--root", "--no-commit-id", "-r", "--name-only", "HEAD"], { cwd: basePath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
66
66
|
return result ? result.split("\n").filter(Boolean) : [];
|
|
67
67
|
}
|
|
68
68
|
catch (e) {
|