create-quiver 0.14.1 → 0.15.0
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/CHANGELOG.md +16 -0
- package/README.md +4 -0
- package/README_FOR_AI.md +8 -2
- package/ROADMAP.md +8 -2
- package/docs/CLI_UX_GUIDE.md +64 -4
- package/docs/COMMANDS.md.template +7 -1
- package/docs/reference/commands.md +4 -0
- package/package.json +1 -1
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/EVIDENCE_REPORT.md +213 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/EXECUTION_PLAN.md +85 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/SPEC.md +213 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/STATUS.md +31 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/pr.md +103 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +56 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/slice.json +71 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/slice.json +69 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/EXECUTION_BRIEF.md +56 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/slice.json +81 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/slice.json +75 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/slice.json +85 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/slice.json +85 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/CLOSURE_BRIEF.md +35 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/EXECUTION_BRIEF.md +55 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/slice.json +81 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/EXECUTION_BRIEF.md +55 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/slice.json +85 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/EXECUTION_BRIEF.md +59 -0
- package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/slice.json +95 -0
- package/src/create-quiver/commands/ai.js +364 -81
- package/src/create-quiver/commands/spec.js +106 -6
- package/src/create-quiver/index.js +533 -70
- package/src/create-quiver/lib/agent-profiles.js +111 -10
- package/src/create-quiver/lib/ai/execution-plan.js +106 -8
- package/src/create-quiver/lib/ai/executor.js +284 -28
- package/src/create-quiver/lib/ai/providers.js +71 -1
- package/src/create-quiver/lib/cli/selectors.js +107 -0
- package/src/create-quiver/lib/cli/theme.js +5 -2
- package/src/create-quiver/lib/cli/ux-flags.js +18 -0
- package/src/create-quiver/lib/cli/ux.js +100 -5
|
@@ -57,7 +57,10 @@ const {
|
|
|
57
57
|
agentProfilesPath,
|
|
58
58
|
buildAgentProfileState,
|
|
59
59
|
getAgentProfile,
|
|
60
|
+
getAgentProfileById,
|
|
60
61
|
listAgentProfiles,
|
|
62
|
+
normalizeAgentProfileRole,
|
|
63
|
+
resolveAgentProfileDisplayName,
|
|
61
64
|
resolveProfileProvider,
|
|
62
65
|
setAgentProfile,
|
|
63
66
|
} = require('../lib/agent-profiles');
|
|
@@ -122,11 +125,119 @@ function normalizeTimeout(timeoutMs) {
|
|
|
122
125
|
return parsed;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
function profileOptionForRole(options, role) {
|
|
129
|
+
const normalized = normalizeAgentProfileRole(role);
|
|
130
|
+
if (normalized === 'planner') {
|
|
131
|
+
return options.plannerProfile || options.profileId || '';
|
|
132
|
+
}
|
|
133
|
+
if (normalized === 'executor') {
|
|
134
|
+
return options.executorProfile || options.profileId || '';
|
|
135
|
+
}
|
|
136
|
+
if (normalized === 'reviewer') {
|
|
137
|
+
return options.reviewerProfile || options.profileId || '';
|
|
138
|
+
}
|
|
139
|
+
if (normalized === 'doctor') {
|
|
140
|
+
return options.doctorProfile || options.profileId || '';
|
|
141
|
+
}
|
|
142
|
+
return options.profileId || '';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function resolveRuntimeAgentProfile(repoRoot, role, options = {}, fallbackProvider = DEFAULT_PLAN_PROVIDER) {
|
|
146
|
+
const normalizedRole = normalizeAgentProfileRole(role);
|
|
147
|
+
const explicitProvider = options.providerExplicit === true || (options.provider && options.providerExplicit !== false);
|
|
148
|
+
const explicitModel = String(options.model || '').trim();
|
|
149
|
+
|
|
150
|
+
if (explicitProvider) {
|
|
151
|
+
const provider = String(options.provider || fallbackProvider).trim().toLowerCase();
|
|
152
|
+
return {
|
|
153
|
+
role: normalizedRole,
|
|
154
|
+
profile: null,
|
|
155
|
+
profileId: '',
|
|
156
|
+
displayName: provider,
|
|
157
|
+
provider,
|
|
158
|
+
model: explicitModel,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const profileId = profileOptionForRole(options, normalizedRole);
|
|
163
|
+
const profile = profileId
|
|
164
|
+
? getAgentProfileById(repoRoot, normalizedRole, profileId)
|
|
165
|
+
: getAgentProfile(repoRoot, normalizedRole);
|
|
166
|
+
const provider = profile?.provider || resolveProfileProvider(repoRoot, normalizedRole, fallbackProvider);
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
role: normalizedRole,
|
|
170
|
+
profile,
|
|
171
|
+
profileId: profile?.id || profileId || '',
|
|
172
|
+
displayName: profile ? resolveAgentProfileDisplayName(profile) : provider,
|
|
173
|
+
provider,
|
|
174
|
+
model: explicitModel || profile?.model || '',
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function createCommandUx(options = {}) {
|
|
179
|
+
if (options.ux) {
|
|
180
|
+
return options.ux;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return createUx({
|
|
184
|
+
env: options.env || process.env,
|
|
185
|
+
input: options.inputStream,
|
|
186
|
+
output: options.outputStream,
|
|
187
|
+
error: options.errorStream,
|
|
188
|
+
interactive: options.interactive,
|
|
189
|
+
json: options.json,
|
|
190
|
+
noColor: options.noColor,
|
|
191
|
+
prompts: options.prompts,
|
|
192
|
+
spinner: options.spinner,
|
|
193
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
194
|
+
stdoutIsTTY: options.stdoutIsTTY,
|
|
195
|
+
stderrIsTTY: options.stderrIsTTY,
|
|
196
|
+
write: options.write,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function shouldShowHumanProgress(ux, options = {}) {
|
|
201
|
+
return options.progress !== false
|
|
202
|
+
&& options.dryRun !== true
|
|
203
|
+
&& options.printPrompt !== true
|
|
204
|
+
&& ux?.mode?.decoration === true;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function plannerProgressTitle(action, runtimeProfile) {
|
|
208
|
+
return `${action} con ${runtimeProfile.displayName || runtimeProfile.model || runtimeProfile.provider}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function writeProgressChecks(ux, enabled, title, checks = []) {
|
|
212
|
+
if (!enabled) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
ux.heading(title);
|
|
216
|
+
for (const check of checks) {
|
|
217
|
+
ux.check(check);
|
|
128
218
|
}
|
|
129
|
-
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function runProviderWithProgress({ ux, enabled, message = 'Ejecutando agente...', successMessage = 'Agente finalizado', failureMessage = 'Fallo ejecutando agente', run }) {
|
|
222
|
+
async function runAndFailOnProviderResult() {
|
|
223
|
+
const result = await run();
|
|
224
|
+
if (result && result.ok === false) {
|
|
225
|
+
const error = new Error(result.error?.message || 'provider run failed');
|
|
226
|
+
error.code = result.error?.code || 'AI_PROVIDER_RUN_FAILED';
|
|
227
|
+
error.providerResult = result;
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!enabled) {
|
|
234
|
+
return run();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return ux.withSpinner(message, runAndFailOnProviderResult, {
|
|
238
|
+
successMessage,
|
|
239
|
+
failureMessage,
|
|
240
|
+
});
|
|
130
241
|
}
|
|
131
242
|
|
|
132
243
|
function buildPlanContext({ role, context, phase, inputText, inputPath, repoRoot, revise = false }) {
|
|
@@ -210,6 +321,10 @@ function formatDryRunReport({ task, provider, role, contextPack, phase, invocati
|
|
|
210
321
|
lines.push(`Timeout: ${invocation.timeoutMs}ms`);
|
|
211
322
|
lines.push(`Prompt transport: ${invocation.promptTransport.mode}`);
|
|
212
323
|
lines.push(`Prompt length: ${invocation.promptLength} bytes`);
|
|
324
|
+
if (invocation.modelSelection && invocation.modelSelection.model) {
|
|
325
|
+
lines.push(`Model: ${invocation.modelSelection.model}`);
|
|
326
|
+
lines.push(`Model support: ${invocation.modelSelection.supported ? 'supported' : 'unsupported'} (${invocation.modelSelection.reason})`);
|
|
327
|
+
}
|
|
213
328
|
|
|
214
329
|
if (onboardingPlan) {
|
|
215
330
|
lines.push(`Prompt source: ${onboardingPlan.promptSource}`);
|
|
@@ -236,6 +351,10 @@ function formatPromptOnlyReport({ task, provider, role, contextPack, phase, invo
|
|
|
236
351
|
lines.push(`Timeout: ${invocation.timeoutMs}ms`);
|
|
237
352
|
lines.push(`Prompt transport: ${invocation.promptTransport.mode}`);
|
|
238
353
|
lines.push(`Prompt length: ${invocation.promptLength} bytes`);
|
|
354
|
+
if (invocation.modelSelection && invocation.modelSelection.model) {
|
|
355
|
+
lines.push(`Model: ${invocation.modelSelection.model}`);
|
|
356
|
+
lines.push(`Model support: ${invocation.modelSelection.supported ? 'supported' : 'unsupported'} (${invocation.modelSelection.reason})`);
|
|
357
|
+
}
|
|
239
358
|
|
|
240
359
|
if (onboardingPlan) {
|
|
241
360
|
lines.push(`Prompt source: ${onboardingPlan.promptSource}`);
|
|
@@ -407,6 +526,12 @@ function formatPrepareContextPlannerDryRunReport({ provider, role, context, invo
|
|
|
407
526
|
`Context pack: ${context}`,
|
|
408
527
|
`Command: ${invocation.command} ${invocation.args.join(' ')}`.trim(),
|
|
409
528
|
`Prompt bytes: ${invocation.promptLength}`,
|
|
529
|
+
invocation.modelSelection && invocation.modelSelection.model
|
|
530
|
+
? `Model: ${invocation.modelSelection.model}`
|
|
531
|
+
: '',
|
|
532
|
+
invocation.modelSelection && invocation.modelSelection.model
|
|
533
|
+
? `Model support: ${invocation.modelSelection.supported ? 'supported' : 'unsupported'} (${invocation.modelSelection.reason})`
|
|
534
|
+
: '',
|
|
410
535
|
`Prompt source: ${promptInfo.promptSource}`,
|
|
411
536
|
`Review requested: ${review ? 'yes' : 'no'}`,
|
|
412
537
|
`Interactive requested: ${interactive ? 'yes' : 'no'}`,
|
|
@@ -424,7 +549,7 @@ function formatPrepareContextPlannerDryRunReport({ provider, role, context, invo
|
|
|
424
549
|
'- npx create-quiver ai prepare-context --with-planner',
|
|
425
550
|
];
|
|
426
551
|
|
|
427
|
-
return `${lines.join('\n')}\n`;
|
|
552
|
+
return `${lines.filter(Boolean).join('\n')}\n`;
|
|
428
553
|
}
|
|
429
554
|
|
|
430
555
|
function serializeProposalForReview(proposal) {
|
|
@@ -1108,7 +1233,8 @@ function annotateGitHubError(error, scope) {
|
|
|
1108
1233
|
|
|
1109
1234
|
async function runOnboard(repoRoot, options = {}) {
|
|
1110
1235
|
const role = normalizeRole(options.role || DEFAULT_ONBOARD_ROLE);
|
|
1111
|
-
const
|
|
1236
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_ONBOARD_PROVIDER);
|
|
1237
|
+
const provider = runtimeProfile.provider;
|
|
1112
1238
|
const context = options.context || DEFAULT_ONBOARD_CONTEXT;
|
|
1113
1239
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1114
1240
|
const inputText = readTextFile(options.input, repoRoot);
|
|
@@ -1121,9 +1247,15 @@ async function runOnboard(repoRoot, options = {}) {
|
|
|
1121
1247
|
prompt,
|
|
1122
1248
|
cwd: repoRoot,
|
|
1123
1249
|
timeoutMs,
|
|
1250
|
+
model: runtimeProfile.model,
|
|
1251
|
+
enforceModelSelection: false,
|
|
1124
1252
|
});
|
|
1125
1253
|
} catch (error) {
|
|
1126
|
-
|
|
1254
|
+
if (error.providerResult) {
|
|
1255
|
+
result = error.providerResult;
|
|
1256
|
+
} else {
|
|
1257
|
+
throw annotateProviderError(error, 'onboard');
|
|
1258
|
+
}
|
|
1127
1259
|
}
|
|
1128
1260
|
|
|
1129
1261
|
if (options.dryRun) {
|
|
@@ -1134,6 +1266,7 @@ async function runOnboard(repoRoot, options = {}) {
|
|
|
1134
1266
|
contextPack: context,
|
|
1135
1267
|
invocation,
|
|
1136
1268
|
onboardingPlan: contextInfo.plan,
|
|
1269
|
+
profile: runtimeProfile,
|
|
1137
1270
|
};
|
|
1138
1271
|
process.stdout.write(formatDryRunReport(report));
|
|
1139
1272
|
return report;
|
|
@@ -1148,23 +1281,39 @@ async function runOnboard(repoRoot, options = {}) {
|
|
|
1148
1281
|
invocation,
|
|
1149
1282
|
onboardingPlan: contextInfo.plan,
|
|
1150
1283
|
prompt,
|
|
1284
|
+
profile: runtimeProfile,
|
|
1151
1285
|
};
|
|
1152
1286
|
process.stdout.write(formatPromptOnlyReport(report));
|
|
1153
1287
|
return report;
|
|
1154
1288
|
}
|
|
1155
1289
|
|
|
1290
|
+
const ux = createCommandUx(options);
|
|
1291
|
+
const showProgress = shouldShowHumanProgress(ux, options);
|
|
1292
|
+
writeProgressChecks(
|
|
1293
|
+
ux,
|
|
1294
|
+
showProgress,
|
|
1295
|
+
plannerProgressTitle('Ejecutando onboarding', runtimeProfile),
|
|
1296
|
+
['Leyendo docs base', 'Detectando estructura', 'Preparando prompt'],
|
|
1297
|
+
);
|
|
1298
|
+
|
|
1156
1299
|
let result;
|
|
1157
1300
|
try {
|
|
1158
|
-
result = await (
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1301
|
+
result = await runProviderWithProgress({
|
|
1302
|
+
ux,
|
|
1303
|
+
enabled: showProgress,
|
|
1304
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
1305
|
+
prompt,
|
|
1306
|
+
cwd: repoRoot,
|
|
1307
|
+
timeoutMs,
|
|
1308
|
+
dryRun: false,
|
|
1309
|
+
probe: options.probe,
|
|
1310
|
+
spawn: options.spawn,
|
|
1311
|
+
tempRoot: options.tempRoot,
|
|
1312
|
+
tempFileName: options.tempFileName,
|
|
1313
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
1314
|
+
model: runtimeProfile.model,
|
|
1315
|
+
enforceModelSelection: Boolean(runtimeProfile.model),
|
|
1316
|
+
}),
|
|
1168
1317
|
});
|
|
1169
1318
|
} catch (error) {
|
|
1170
1319
|
throw annotateProviderError(error, 'onboard');
|
|
@@ -1185,6 +1334,7 @@ async function runOnboard(repoRoot, options = {}) {
|
|
|
1185
1334
|
contextPack: context,
|
|
1186
1335
|
invocation,
|
|
1187
1336
|
onboardingPlan: contextInfo.plan,
|
|
1337
|
+
profile: runtimeProfile,
|
|
1188
1338
|
result,
|
|
1189
1339
|
};
|
|
1190
1340
|
}
|
|
@@ -1257,7 +1407,8 @@ async function runPrepareContext(repoRoot, options = {}) {
|
|
|
1257
1407
|
|
|
1258
1408
|
async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
1259
1409
|
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1260
|
-
const
|
|
1410
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
1411
|
+
const provider = runtimeProfile.provider;
|
|
1261
1412
|
const context = options.context || DEFAULT_PLAN_CONTEXT;
|
|
1262
1413
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1263
1414
|
const draftPack = buildContextPreparationDrafts(repoRoot);
|
|
@@ -1276,9 +1427,15 @@ async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
|
1276
1427
|
prompt,
|
|
1277
1428
|
cwd: repoRoot,
|
|
1278
1429
|
timeoutMs,
|
|
1430
|
+
model: runtimeProfile.model,
|
|
1431
|
+
enforceModelSelection: false,
|
|
1279
1432
|
});
|
|
1280
1433
|
} catch (error) {
|
|
1281
|
-
|
|
1434
|
+
if (error.providerResult) {
|
|
1435
|
+
result = error.providerResult;
|
|
1436
|
+
} else {
|
|
1437
|
+
throw annotateProviderError(error, 'prepare-context');
|
|
1438
|
+
}
|
|
1282
1439
|
}
|
|
1283
1440
|
|
|
1284
1441
|
if (options.dryRun) {
|
|
@@ -1292,6 +1449,7 @@ async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
|
1292
1449
|
invocation,
|
|
1293
1450
|
candidateDocs: promptInfo.allowedPaths,
|
|
1294
1451
|
plan: draftPack.plan,
|
|
1452
|
+
profile: runtimeProfile,
|
|
1295
1453
|
};
|
|
1296
1454
|
process.stdout.write(formatPrepareContextPlannerDryRunReport({
|
|
1297
1455
|
provider,
|
|
@@ -1314,23 +1472,39 @@ async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
|
1314
1472
|
invocation,
|
|
1315
1473
|
prompt,
|
|
1316
1474
|
promptSource: promptInfo.promptSource,
|
|
1475
|
+
profile: runtimeProfile,
|
|
1317
1476
|
};
|
|
1318
1477
|
process.stdout.write(formatPromptOnlyReport(report));
|
|
1319
1478
|
return report;
|
|
1320
1479
|
}
|
|
1321
1480
|
|
|
1481
|
+
const ux = createCommandUx(options);
|
|
1482
|
+
const showProgress = shouldShowHumanProgress(ux, options);
|
|
1483
|
+
writeProgressChecks(
|
|
1484
|
+
ux,
|
|
1485
|
+
showProgress,
|
|
1486
|
+
plannerProgressTitle('Ejecutando onboarding', runtimeProfile),
|
|
1487
|
+
['Leyendo docs base', 'Detectando estructura', 'Preparando prompt'],
|
|
1488
|
+
);
|
|
1489
|
+
|
|
1322
1490
|
let result;
|
|
1323
1491
|
try {
|
|
1324
|
-
result = await (
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1492
|
+
result = await runProviderWithProgress({
|
|
1493
|
+
ux,
|
|
1494
|
+
enabled: showProgress,
|
|
1495
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
1496
|
+
prompt,
|
|
1497
|
+
cwd: repoRoot,
|
|
1498
|
+
timeoutMs,
|
|
1499
|
+
dryRun: false,
|
|
1500
|
+
probe: options.probe,
|
|
1501
|
+
spawn: options.spawn,
|
|
1502
|
+
tempRoot: options.tempRoot,
|
|
1503
|
+
tempFileName: options.tempFileName,
|
|
1504
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
1505
|
+
model: runtimeProfile.model,
|
|
1506
|
+
enforceModelSelection: Boolean(runtimeProfile.model),
|
|
1507
|
+
}),
|
|
1334
1508
|
});
|
|
1335
1509
|
} catch (error) {
|
|
1336
1510
|
throw annotateProviderError(error, 'prepare-context');
|
|
@@ -1404,7 +1578,8 @@ async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
|
1404
1578
|
async function runPlan(repoRoot, options = {}) {
|
|
1405
1579
|
const phase = normalizePlannerPhase(options.phase || DEFAULT_PLAN_PHASE);
|
|
1406
1580
|
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1407
|
-
const
|
|
1581
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
1582
|
+
const provider = runtimeProfile.provider;
|
|
1408
1583
|
const context = options.context || DEFAULT_PLAN_CONTEXT;
|
|
1409
1584
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1410
1585
|
let inputPath = options.input || '';
|
|
@@ -1506,9 +1681,15 @@ async function runPlan(repoRoot, options = {}) {
|
|
|
1506
1681
|
prompt,
|
|
1507
1682
|
cwd: repoRoot,
|
|
1508
1683
|
timeoutMs,
|
|
1684
|
+
model: runtimeProfile.model,
|
|
1685
|
+
enforceModelSelection: false,
|
|
1509
1686
|
});
|
|
1510
1687
|
} catch (error) {
|
|
1511
|
-
|
|
1688
|
+
if (error.providerResult) {
|
|
1689
|
+
result = error.providerResult;
|
|
1690
|
+
} else {
|
|
1691
|
+
throw annotateProviderError(error, 'plan', phase);
|
|
1692
|
+
}
|
|
1512
1693
|
}
|
|
1513
1694
|
|
|
1514
1695
|
if (options.dryRun) {
|
|
@@ -1519,6 +1700,7 @@ async function runPlan(repoRoot, options = {}) {
|
|
|
1519
1700
|
contextPack: contextInfo.pack.packName,
|
|
1520
1701
|
phase,
|
|
1521
1702
|
invocation,
|
|
1703
|
+
profile: runtimeProfile,
|
|
1522
1704
|
};
|
|
1523
1705
|
process.stdout.write(formatDryRunReport(report));
|
|
1524
1706
|
if (options.withPlanner === true) {
|
|
@@ -1542,23 +1724,39 @@ async function runPlan(repoRoot, options = {}) {
|
|
|
1542
1724
|
phase,
|
|
1543
1725
|
invocation,
|
|
1544
1726
|
prompt,
|
|
1727
|
+
profile: runtimeProfile,
|
|
1545
1728
|
};
|
|
1546
1729
|
process.stdout.write(formatPromptOnlyReport(report));
|
|
1547
1730
|
return report;
|
|
1548
1731
|
}
|
|
1549
1732
|
|
|
1733
|
+
const ux = createCommandUx(options);
|
|
1734
|
+
const showProgress = shouldShowHumanProgress(ux, options);
|
|
1735
|
+
writeProgressChecks(
|
|
1736
|
+
ux,
|
|
1737
|
+
showProgress,
|
|
1738
|
+
plannerProgressTitle(`Ejecutando plan ${phase}`, runtimeProfile),
|
|
1739
|
+
['Leyendo entrada', 'Preparando contexto', 'Preparando prompt'],
|
|
1740
|
+
);
|
|
1741
|
+
|
|
1550
1742
|
let result;
|
|
1551
1743
|
try {
|
|
1552
|
-
result = await (
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1744
|
+
result = await runProviderWithProgress({
|
|
1745
|
+
ux,
|
|
1746
|
+
enabled: showProgress,
|
|
1747
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
1748
|
+
prompt,
|
|
1749
|
+
cwd: repoRoot,
|
|
1750
|
+
timeoutMs,
|
|
1751
|
+
dryRun: false,
|
|
1752
|
+
probe: options.probe,
|
|
1753
|
+
spawn: options.spawn,
|
|
1754
|
+
tempRoot: options.tempRoot,
|
|
1755
|
+
tempFileName: options.tempFileName,
|
|
1756
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
1757
|
+
model: runtimeProfile.model,
|
|
1758
|
+
enforceModelSelection: Boolean(runtimeProfile.model),
|
|
1759
|
+
}),
|
|
1562
1760
|
});
|
|
1563
1761
|
} catch (error) {
|
|
1564
1762
|
throw annotateProviderError(error, 'plan', phase);
|
|
@@ -1625,7 +1823,8 @@ async function runPlan(repoRoot, options = {}) {
|
|
|
1625
1823
|
|
|
1626
1824
|
async function runReviewPlan(repoRoot, options = {}) {
|
|
1627
1825
|
const role = 'planner';
|
|
1628
|
-
const
|
|
1826
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, 'reviewer', options, DEFAULT_PLAN_PROVIDER);
|
|
1827
|
+
const provider = runtimeProfile.provider;
|
|
1629
1828
|
const context = options.context || DEFAULT_PLAN_CONTEXT;
|
|
1630
1829
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1631
1830
|
const resolved = resolveTechnicalPlanReviewInput(repoRoot, options.input || undefined);
|
|
@@ -1649,9 +1848,15 @@ async function runReviewPlan(repoRoot, options = {}) {
|
|
|
1649
1848
|
prompt: built.prompt,
|
|
1650
1849
|
cwd: repoRoot,
|
|
1651
1850
|
timeoutMs,
|
|
1851
|
+
model: runtimeProfile.model,
|
|
1852
|
+
enforceModelSelection: false,
|
|
1652
1853
|
});
|
|
1653
1854
|
} catch (error) {
|
|
1654
|
-
|
|
1855
|
+
if (error.providerResult) {
|
|
1856
|
+
result = error.providerResult;
|
|
1857
|
+
} else {
|
|
1858
|
+
throw annotateProviderError(error, 'review-plan');
|
|
1859
|
+
}
|
|
1655
1860
|
}
|
|
1656
1861
|
|
|
1657
1862
|
if (options.dryRun) {
|
|
@@ -1665,6 +1870,7 @@ async function runReviewPlan(repoRoot, options = {}) {
|
|
|
1665
1870
|
inputPath,
|
|
1666
1871
|
inputKind: resolved.kind,
|
|
1667
1872
|
inputVersion: resolved.version,
|
|
1873
|
+
profile: runtimeProfile,
|
|
1668
1874
|
};
|
|
1669
1875
|
process.stdout.write(formatDryRunReport({
|
|
1670
1876
|
task: 'review-plan',
|
|
@@ -1696,23 +1902,39 @@ async function runReviewPlan(repoRoot, options = {}) {
|
|
|
1696
1902
|
inputPath,
|
|
1697
1903
|
inputKind: resolved.kind,
|
|
1698
1904
|
inputVersion: resolved.version,
|
|
1905
|
+
profile: runtimeProfile,
|
|
1699
1906
|
};
|
|
1700
1907
|
process.stdout.write(formatPromptOnlyReport(report));
|
|
1701
1908
|
return report;
|
|
1702
1909
|
}
|
|
1703
1910
|
|
|
1911
|
+
const ux = createCommandUx(options);
|
|
1912
|
+
const showProgress = shouldShowHumanProgress(ux, options);
|
|
1913
|
+
writeProgressChecks(
|
|
1914
|
+
ux,
|
|
1915
|
+
showProgress,
|
|
1916
|
+
plannerProgressTitle('Ejecutando revisión del plan', runtimeProfile),
|
|
1917
|
+
['Leyendo plan técnico', 'Preparando contexto', 'Preparando prompt'],
|
|
1918
|
+
);
|
|
1919
|
+
|
|
1704
1920
|
let result;
|
|
1705
1921
|
try {
|
|
1706
|
-
result = await (
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1922
|
+
result = await runProviderWithProgress({
|
|
1923
|
+
ux,
|
|
1924
|
+
enabled: showProgress,
|
|
1925
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
1926
|
+
prompt: built.prompt,
|
|
1927
|
+
cwd: repoRoot,
|
|
1928
|
+
timeoutMs,
|
|
1929
|
+
dryRun: false,
|
|
1930
|
+
probe: options.probe,
|
|
1931
|
+
spawn: options.spawn,
|
|
1932
|
+
tempRoot: options.tempRoot,
|
|
1933
|
+
tempFileName: options.tempFileName,
|
|
1934
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
1935
|
+
model: runtimeProfile.model,
|
|
1936
|
+
enforceModelSelection: Boolean(runtimeProfile.model),
|
|
1937
|
+
}),
|
|
1716
1938
|
});
|
|
1717
1939
|
} catch (error) {
|
|
1718
1940
|
throw annotateProviderError(error, 'review-plan');
|
|
@@ -1770,7 +1992,8 @@ async function runReviewPlan(repoRoot, options = {}) {
|
|
|
1770
1992
|
|
|
1771
1993
|
async function runRepairPlan(repoRoot, options = {}) {
|
|
1772
1994
|
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1773
|
-
const
|
|
1995
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
1996
|
+
const provider = runtimeProfile.provider;
|
|
1774
1997
|
const context = options.context || DEFAULT_PLAN_CONTEXT;
|
|
1775
1998
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1776
1999
|
const source = resolveApprovedTechnicalPlanForRepair(repoRoot, options.input || '');
|
|
@@ -1790,9 +2013,15 @@ async function runRepairPlan(repoRoot, options = {}) {
|
|
|
1790
2013
|
prompt: built.prompt,
|
|
1791
2014
|
cwd: repoRoot,
|
|
1792
2015
|
timeoutMs,
|
|
2016
|
+
model: runtimeProfile.model,
|
|
2017
|
+
enforceModelSelection: false,
|
|
1793
2018
|
});
|
|
1794
2019
|
} catch (error) {
|
|
1795
|
-
|
|
2020
|
+
if (error.providerResult) {
|
|
2021
|
+
providerResult = error.providerResult;
|
|
2022
|
+
} else {
|
|
2023
|
+
throw annotateProviderError(error, 'repair-plan');
|
|
2024
|
+
}
|
|
1796
2025
|
}
|
|
1797
2026
|
|
|
1798
2027
|
if (options.dryRun) {
|
|
@@ -1803,6 +2032,7 @@ async function runRepairPlan(repoRoot, options = {}) {
|
|
|
1803
2032
|
contextPack: built.pack.packName,
|
|
1804
2033
|
phase: 'technical-plan',
|
|
1805
2034
|
invocation,
|
|
2035
|
+
profile: runtimeProfile,
|
|
1806
2036
|
};
|
|
1807
2037
|
process.stdout.write(formatDryRunReport(report));
|
|
1808
2038
|
process.stdout.write(`Source approved artifact: ${source.path}\n`);
|
|
@@ -1822,23 +2052,39 @@ async function runRepairPlan(repoRoot, options = {}) {
|
|
|
1822
2052
|
inputPath: source.path,
|
|
1823
2053
|
inputKind: 'approved',
|
|
1824
2054
|
inputVersion: source.approval.meta?.approved?.version || null,
|
|
2055
|
+
profile: runtimeProfile,
|
|
1825
2056
|
};
|
|
1826
2057
|
process.stdout.write(formatPromptOnlyReport(report));
|
|
1827
2058
|
return report;
|
|
1828
2059
|
}
|
|
1829
2060
|
|
|
2061
|
+
const ux = createCommandUx(options);
|
|
2062
|
+
const showProgress = shouldShowHumanProgress(ux, options);
|
|
2063
|
+
writeProgressChecks(
|
|
2064
|
+
ux,
|
|
2065
|
+
showProgress,
|
|
2066
|
+
plannerProgressTitle('Ejecutando reparación del plan', runtimeProfile),
|
|
2067
|
+
['Leyendo plan aprobado', 'Preparando contexto', 'Preparando prompt'],
|
|
2068
|
+
);
|
|
2069
|
+
|
|
1830
2070
|
let providerResult;
|
|
1831
2071
|
try {
|
|
1832
|
-
providerResult = await (
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
2072
|
+
providerResult = await runProviderWithProgress({
|
|
2073
|
+
ux,
|
|
2074
|
+
enabled: showProgress,
|
|
2075
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
2076
|
+
prompt: built.prompt,
|
|
2077
|
+
cwd: repoRoot,
|
|
2078
|
+
timeoutMs,
|
|
2079
|
+
dryRun: false,
|
|
2080
|
+
probe: options.probe,
|
|
2081
|
+
spawn: options.spawn,
|
|
2082
|
+
tempRoot: options.tempRoot,
|
|
2083
|
+
tempFileName: options.tempFileName,
|
|
2084
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
2085
|
+
model: runtimeProfile.model,
|
|
2086
|
+
enforceModelSelection: Boolean(runtimeProfile.model),
|
|
2087
|
+
}),
|
|
1842
2088
|
});
|
|
1843
2089
|
} catch (error) {
|
|
1844
2090
|
throw annotateProviderError(error, 'repair-plan');
|
|
@@ -2174,10 +2420,13 @@ function runLifecycleRun(repoRoot, options = {}) {
|
|
|
2174
2420
|
|
|
2175
2421
|
function formatAgentProfile(profile) {
|
|
2176
2422
|
const lines = [
|
|
2423
|
+
`ID: ${profile.id || 'default'}`,
|
|
2177
2424
|
`Role: ${profile.role}`,
|
|
2178
2425
|
`Provider: ${profile.provider}`,
|
|
2179
2426
|
`Model: ${profile.model || '(not set)'}`,
|
|
2180
2427
|
`Label: ${profile.label || '(not set)'}`,
|
|
2428
|
+
`Display name: ${resolveAgentProfileDisplayName(profile) || '(not set)'}`,
|
|
2429
|
+
`Default: ${profile.default === true ? 'yes' : 'no'}`,
|
|
2181
2430
|
`Context: ${profile.context || '(not set)'}`,
|
|
2182
2431
|
`Updated: ${profile.updated_at}`,
|
|
2183
2432
|
];
|
|
@@ -2193,7 +2442,9 @@ function formatAgentProfileList(profiles) {
|
|
|
2193
2442
|
}
|
|
2194
2443
|
const model = item.profile.model ? ` model=${item.profile.model}` : '';
|
|
2195
2444
|
const label = item.profile.label ? ` label=${item.profile.label}` : '';
|
|
2196
|
-
|
|
2445
|
+
const displayName = resolveAgentProfileDisplayName(item.profile);
|
|
2446
|
+
const alternatives = item.profiles.length > 1 ? ` options=${item.profiles.length}` : '';
|
|
2447
|
+
lines.push(`- ${item.role}: provider=${item.profile.provider}${model}${label} displayName=${displayName}${alternatives}`);
|
|
2197
2448
|
}
|
|
2198
2449
|
return `${lines.join('\n')}\n`;
|
|
2199
2450
|
}
|
|
@@ -2226,6 +2477,9 @@ function runAgent(repoRoot, options = {}) {
|
|
|
2226
2477
|
if (options.dryRun) {
|
|
2227
2478
|
const preview = buildAgentProfileState(repoRoot, options.role, {
|
|
2228
2479
|
context: options.context,
|
|
2480
|
+
default: options.defaultProfile,
|
|
2481
|
+
displayName: options.displayName,
|
|
2482
|
+
id: options.id,
|
|
2229
2483
|
label: options.label,
|
|
2230
2484
|
model: options.model,
|
|
2231
2485
|
provider: options.provider,
|
|
@@ -2241,6 +2495,9 @@ function runAgent(repoRoot, options = {}) {
|
|
|
2241
2495
|
}
|
|
2242
2496
|
const result = setAgentProfile(repoRoot, options.role, {
|
|
2243
2497
|
context: options.context,
|
|
2498
|
+
default: options.defaultProfile,
|
|
2499
|
+
displayName: options.displayName,
|
|
2500
|
+
id: options.id,
|
|
2244
2501
|
label: options.label,
|
|
2245
2502
|
model: options.model,
|
|
2246
2503
|
provider: options.provider,
|
|
@@ -2260,10 +2517,14 @@ function runAgent(repoRoot, options = {}) {
|
|
|
2260
2517
|
if (!options.role) {
|
|
2261
2518
|
throw new Error(formatError('missing agent role. Use: npx create-quiver ai agent show <planner|executor|reviewer|doctor>'));
|
|
2262
2519
|
}
|
|
2263
|
-
const profile =
|
|
2520
|
+
const profile = options.id
|
|
2521
|
+
? getAgentProfileById(repoRoot, options.role, options.id)
|
|
2522
|
+
: getAgentProfile(repoRoot, options.role);
|
|
2264
2523
|
if (!profile) {
|
|
2265
2524
|
throw new Error(formatActionableError({
|
|
2266
|
-
failure:
|
|
2525
|
+
failure: options.id
|
|
2526
|
+
? `agent profile '${options.role}/${options.id}' is not configured.`
|
|
2527
|
+
: `agent profile '${options.role}' is not configured.`,
|
|
2267
2528
|
impact: 'Quiver will fall back to default provider behavior and may use the wrong model/cost profile.',
|
|
2268
2529
|
fix: `Configure the ${options.role} profile with a supported provider and optional model label.`,
|
|
2269
2530
|
nextCommand: `npx create-quiver ai agent set ${options.role} --provider <provider> --model <label>`,
|
|
@@ -2324,20 +2585,32 @@ async function runGitHubTask(repoRoot, options = {}, mode = 'pr') {
|
|
|
2324
2585
|
async function runPr(repoRoot, options = {}) {
|
|
2325
2586
|
const dryRun = options.dryRun === true;
|
|
2326
2587
|
const create = options.create === true;
|
|
2588
|
+
const ux = createCommandUx(options);
|
|
2589
|
+
const showProgress = create && !dryRun && shouldShowHumanProgress(ux, options);
|
|
2590
|
+
if (showProgress) {
|
|
2591
|
+
ux.heading('Creando PR con gh');
|
|
2592
|
+
}
|
|
2327
2593
|
let preflight;
|
|
2328
2594
|
|
|
2329
2595
|
try {
|
|
2330
|
-
preflight = await (
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2596
|
+
preflight = await runProviderWithProgress({
|
|
2597
|
+
ux,
|
|
2598
|
+
enabled: showProgress,
|
|
2599
|
+
message: 'Ejecutando preflight de GitHub...',
|
|
2600
|
+
successMessage: 'Preflight de GitHub listo',
|
|
2601
|
+
failureMessage: 'Falló preflight de GitHub',
|
|
2602
|
+
run: () => (options.preflightFn || preflightGitHubPr)(repoRoot, {
|
|
2603
|
+
remote: options.remote,
|
|
2604
|
+
sshHostAlias: options.sshHostAlias,
|
|
2605
|
+
identityFile: options.identityFile,
|
|
2606
|
+
gitFlowGuidePath: options.gitFlowGuidePath,
|
|
2607
|
+
ghCommand: options.ghCommand,
|
|
2608
|
+
ghProbe: options.ghProbe,
|
|
2609
|
+
ghAuthProbe: options.ghAuthProbe,
|
|
2610
|
+
ghProbeArgs: options.ghProbeArgs,
|
|
2611
|
+
ghAuthArgs: options.ghAuthArgs,
|
|
2612
|
+
blockedBranches: options.blockedBranches,
|
|
2613
|
+
}),
|
|
2341
2614
|
});
|
|
2342
2615
|
} catch (error) {
|
|
2343
2616
|
throw annotateGitHubError(error, 'pr');
|
|
@@ -2352,6 +2625,9 @@ async function runPr(repoRoot, options = {}) {
|
|
|
2352
2625
|
prBodyPath: options.prBodyPath,
|
|
2353
2626
|
title: options.title,
|
|
2354
2627
|
});
|
|
2628
|
+
if (showProgress) {
|
|
2629
|
+
ux.check('Cuerpo del PR preparado');
|
|
2630
|
+
}
|
|
2355
2631
|
} catch (error) {
|
|
2356
2632
|
throw annotateGitHubError(error, 'pr');
|
|
2357
2633
|
}
|
|
@@ -2396,8 +2672,15 @@ async function runPr(repoRoot, options = {}) {
|
|
|
2396
2672
|
|
|
2397
2673
|
let result;
|
|
2398
2674
|
try {
|
|
2399
|
-
result =
|
|
2400
|
-
|
|
2675
|
+
result = await runProviderWithProgress({
|
|
2676
|
+
ux,
|
|
2677
|
+
enabled: showProgress,
|
|
2678
|
+
message: 'Creando PR en GitHub...',
|
|
2679
|
+
successMessage: 'PR creado',
|
|
2680
|
+
failureMessage: 'Falló creación del PR',
|
|
2681
|
+
run: () => runGhPrCreate(plan, {
|
|
2682
|
+
ghCreateRunner: options.ghCreateRunner,
|
|
2683
|
+
}),
|
|
2401
2684
|
});
|
|
2402
2685
|
} catch (error) {
|
|
2403
2686
|
throw annotateGitHubError(error, 'pr');
|