@prompts-gpt/client 0.2.3 → 0.2.5
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/README.md +49 -17
- package/dist/cli.js +949 -127
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -21
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +18 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +277 -6
- package/dist/runtime.js.map +1 -1
- package/dist/sweep.d.ts +7 -1
- package/dist/sweep.d.ts.map +1 -1
- package/dist/sweep.js +28 -8
- package/dist/sweep.js.map +1 -1
- package/package.json +4 -5
- package/CHANGELOG.md +0 -110
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { parseArgs } from "node:util";
|
|
5
|
-
import { DEFAULT_PROMPTS_GPT_API_URL, DEFAULT_PROMPTS_GPT_OUT_DIR, DEFAULT_RUN_CONFIG_PATH, PROMPTS_GPT_CREDENTIALS_FILE, PromptsGptApiError, PromptsGptClient, doctor, initRunConfig, loadRunConfig, normalizeOrchestrationAgent, ORCHESTRATION_AGENT_PROFILES, runBatch, runPrompt, sweepPrompt, validateRunConfig, discoverWorkspaceAssets, SUPPORTED_AGENT_TARGETS, detectProviders, loadLocalCredentials, saveLocalCredentials, syncPrompts, writeAgentFiles, writePromptManifest, writePromptMarkdownFiles, } from "./index.js";
|
|
5
|
+
import { hasTokenUsage, DEFAULT_PROMPTS_GPT_API_URL, DEFAULT_PROMPTS_GPT_OUT_DIR, DEFAULT_RUN_CONFIG_PATH, PROMPTS_GPT_CREDENTIALS_FILE, PromptsGptApiError, PromptsGptClient, doctor, initRunConfig, loadRunConfig, normalizeOrchestrationAgent, ORCHESTRATION_AGENT_PROFILES, runBatch, runPrompt, resolveRunProvider, warnModelProviderMismatch, sweepPrompt, validateRunConfig, discoverWorkspaceAssets, SUPPORTED_AGENT_TARGETS, detectProviders, loadLocalCredentials, saveLocalCredentials, syncPrompts, writeAgentFiles, writePromptManifest, writePromptMarkdownFiles, } from "./index.js";
|
|
6
6
|
const CLI_EXIT_CODES = {
|
|
7
7
|
success: 0,
|
|
8
8
|
general: 1,
|
|
@@ -12,7 +12,7 @@ const CLI_EXIT_CODES = {
|
|
|
12
12
|
usage: 64,
|
|
13
13
|
};
|
|
14
14
|
const VALID_TOOLS = ["Codex", "Claude Code", "Cursor", "GitHub Copilot", "ChatGPT", "Gemini", "Perplexity", "Grok", "DeepSeek", "Claude"];
|
|
15
|
-
const COMMANDS = ["setup", "init", "project", "pull", "generate", "sync", "run", "run-batch", "sweep", "list", "status", "validate", "providers", "doctor", "load-config", "version", "help"];
|
|
15
|
+
const COMMANDS = ["setup", "init", "project", "pull", "generate", "sync", "run", "run-batch", "sweep", "list", "status", "validate", "providers", "doctor", "load-config", "quickstart", "version", "help"];
|
|
16
16
|
const MAX_STDIN_TOKEN_LENGTH = 4_096;
|
|
17
17
|
class CliError extends Error {
|
|
18
18
|
exitCode;
|
|
@@ -27,12 +27,15 @@ class CliError extends Error {
|
|
|
27
27
|
async function main() {
|
|
28
28
|
const argv = process.argv.slice(2);
|
|
29
29
|
if (argv.length === 0) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
console.log(`Prompts-GPT CLI — sync and run AI prompt packs locally
|
|
31
|
+
|
|
32
|
+
Get started:
|
|
33
|
+
prompts-gpt quickstart — setup credentials, config, and first run
|
|
34
|
+
prompts-gpt list — see available prompts and sweeps
|
|
35
|
+
prompts-gpt sweep — run a multi-iteration sweep (auto-detects local sweeps)
|
|
36
|
+
|
|
37
|
+
Run \`prompts-gpt help\` for the full command list.
|
|
38
|
+
`);
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
const first = argv[0];
|
|
@@ -83,7 +86,11 @@ async function runCommand(command, flags) {
|
|
|
83
86
|
}
|
|
84
87
|
console.log(`Workspace: ${cwd}`);
|
|
85
88
|
for (const provider of providers) {
|
|
86
|
-
|
|
89
|
+
const status = provider.available ? "✓ available" : "✗ missing";
|
|
90
|
+
console.log(`${provider.provider}: ${status} | bin=${provider.bin} | model=${provider.modelDefault}${provider.version ? ` | version=${provider.version}` : ""}`);
|
|
91
|
+
if (!provider.available) {
|
|
92
|
+
console.log(` install: ${provider.installHint}`);
|
|
93
|
+
}
|
|
87
94
|
}
|
|
88
95
|
return;
|
|
89
96
|
}
|
|
@@ -123,31 +130,24 @@ async function runCommand(command, flags) {
|
|
|
123
130
|
console.log(JSON.stringify(result, null, 2));
|
|
124
131
|
return;
|
|
125
132
|
}
|
|
126
|
-
console.log(`
|
|
127
|
-
console.log(`
|
|
128
|
-
console.log(`Provider order: ${(result.config.providerOrder ?? []).join(", ")}`);
|
|
133
|
+
console.log(`Config: ${result.configPath}`);
|
|
134
|
+
console.log(`Agent: ${result.config.defaultAgent ?? "router"} | Providers: ${(result.config.providerOrder ?? []).join(", ")}`);
|
|
129
135
|
if (result.sourceSummary.defaultPromptFile) {
|
|
130
|
-
console.log(`Default prompt
|
|
136
|
+
console.log(`Default prompt: ${result.sourceSummary.defaultPromptFile}`);
|
|
131
137
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
console.log(`Batch default prompt files: ${result.sourceSummary.promptFiles.length}`);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
console.log("Batch default prompt sources: none detected");
|
|
140
|
-
}
|
|
141
|
-
console.log("Detected providers:");
|
|
142
|
-
for (const provider of result.providerSummary) {
|
|
143
|
-
console.log(`- ${provider.provider}: ${provider.available ? "available" : "missing"} | bin=${provider.bin}`);
|
|
138
|
+
const availableCount = result.providerSummary.filter((p) => p.available).length;
|
|
139
|
+
console.log(`Providers: ${availableCount}/${result.providerSummary.length} available`);
|
|
140
|
+
if (availableCount === 0) {
|
|
141
|
+
console.log("⚠ No provider CLIs detected. Install codex, cursor agent, claude, or copilot.");
|
|
144
142
|
}
|
|
143
|
+
const setupAssets = await discoverWorkspaceAssets(cwd);
|
|
145
144
|
console.log("Next steps:");
|
|
146
145
|
console.log(` prompts-gpt run${result.sourceSummary.defaultPromptFile ? "" : " --prompt-file <path>"}`);
|
|
147
|
-
|
|
146
|
+
if (setupAssets.sweeps.length > 0) {
|
|
147
|
+
console.log(` prompts-gpt sweep — run a multi-iteration sweep (${setupAssets.sweeps.length} found)`);
|
|
148
|
+
}
|
|
148
149
|
console.log(" prompts-gpt list — see all runnable assets");
|
|
149
150
|
console.log(" prompts-gpt status — check workspace readiness");
|
|
150
|
-
console.log(" prompts-gpt validate — validate your config");
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
if (command === "doctor") {
|
|
@@ -180,10 +180,15 @@ async function runCommand(command, flags) {
|
|
|
180
180
|
}
|
|
181
181
|
console.log(`Workspace: ${cwd}`);
|
|
182
182
|
console.log("");
|
|
183
|
+
const providers = await detectProviders(cwd);
|
|
184
|
+
const availableProviderNames = providers.filter((p) => p.available).map((p) => p.provider);
|
|
183
185
|
if (assets.prompts.length > 0) {
|
|
184
186
|
console.log(`Prompt packs (${assets.prompts.length}):`);
|
|
185
187
|
for (const p of assets.prompts) {
|
|
186
|
-
|
|
188
|
+
const providerHint = availableProviderNames.length > 0
|
|
189
|
+
? ` (run with: ${availableProviderNames[0]})`
|
|
190
|
+
: "";
|
|
191
|
+
console.log(` ${p.slug} — ${p.title} [${p.source}]${providerHint}`);
|
|
187
192
|
console.log(` file: .prompts-gpt/${p.file}`);
|
|
188
193
|
console.log(` run: prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
189
194
|
}
|
|
@@ -197,9 +202,12 @@ async function runCommand(command, flags) {
|
|
|
197
202
|
if (assets.sweeps.length > 0) {
|
|
198
203
|
console.log(`Sweep prompts (${assets.sweeps.length}):`);
|
|
199
204
|
for (const s of assets.sweeps) {
|
|
200
|
-
|
|
205
|
+
const iterCount = await readSweepIterationsFromFrontmatter(path.resolve(cwd, s.file));
|
|
206
|
+
const iterHint = iterCount ? ` (${iterCount} iterations)` : "";
|
|
207
|
+
const iterFlag = iterCount ? ` --iterations ${iterCount}` : "";
|
|
208
|
+
console.log(` ${s.name}${iterHint}`);
|
|
201
209
|
console.log(` file: ${s.file}`);
|
|
202
|
-
console.log(` sweep: prompts-gpt sweep --prompt-file ${s.file}`);
|
|
210
|
+
console.log(` sweep: prompts-gpt sweep --prompt-file ${s.file}${iterFlag}`);
|
|
203
211
|
}
|
|
204
212
|
console.log("");
|
|
205
213
|
}
|
|
@@ -223,6 +231,30 @@ async function runCommand(command, flags) {
|
|
|
223
231
|
console.log(`Config: ${assets.configFound ? "found" : "not found — run `prompts-gpt setup`"}`);
|
|
224
232
|
console.log(`Manifest: ${assets.manifestFound ? "found" : "not found — run `prompts-gpt sync`"}`);
|
|
225
233
|
console.log(`Credentials: ${assets.credentialsFound ? "found" : "not found — run `prompts-gpt init --token <token>`"}`);
|
|
234
|
+
if (isTTYInteractive() && availableProviderNames.length > 0) {
|
|
235
|
+
const runnableOptions = [];
|
|
236
|
+
for (const p of assets.prompts) {
|
|
237
|
+
runnableOptions.push({ label: `run: ${p.slug} — ${p.title}`, value: `run:.prompts-gpt/${p.file}` });
|
|
238
|
+
}
|
|
239
|
+
for (const s of assets.sweeps) {
|
|
240
|
+
runnableOptions.push({ label: `sweep: ${s.name}`, value: `sweep:${s.file}` });
|
|
241
|
+
}
|
|
242
|
+
if (runnableOptions.length > 1) {
|
|
243
|
+
console.log("");
|
|
244
|
+
const picked = await interactiveSelect("Run something now?", [
|
|
245
|
+
...runnableOptions,
|
|
246
|
+
{ label: "(exit)", value: "exit" },
|
|
247
|
+
]);
|
|
248
|
+
if (picked !== "exit") {
|
|
249
|
+
const [action, file] = picked.split(":", 2);
|
|
250
|
+
const cmd = action === "sweep" ? "sweep" : "run";
|
|
251
|
+
console.log(`\nRunning: prompts-gpt ${cmd} -f ${file}\n`);
|
|
252
|
+
const { spawnSync: spSync } = await import("node:child_process");
|
|
253
|
+
const result = spSync(process.execPath, [process.argv[1], cmd, "-f", file], { stdio: "inherit", cwd });
|
|
254
|
+
process.exitCode = result.status ?? 1;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
226
258
|
return;
|
|
227
259
|
}
|
|
228
260
|
if (command === "status") {
|
|
@@ -240,20 +272,38 @@ async function runCommand(command, flags) {
|
|
|
240
272
|
console.log(` Credentials: ${assets.credentialsFound ? "✓" : "✗ — run \`prompts-gpt init --token <token>\`"}`);
|
|
241
273
|
console.log(` Config: ${assets.configFound ? "✓" : "✗ — run \`prompts-gpt setup\`"}`);
|
|
242
274
|
console.log(` Manifest: ${assets.manifestFound ? "✓" : "✗ — run \`prompts-gpt sync\`"}`);
|
|
243
|
-
|
|
275
|
+
const cloudCount = assets.prompts.filter((p) => p.source === "library" || p.source === "generated").length;
|
|
276
|
+
const localCount = assets.prompts.filter((p) => p.source === "local").length;
|
|
277
|
+
const promptSummary = assets.prompts.length > 0
|
|
278
|
+
? `✓ (${assets.prompts.length}${cloudCount > 0 ? `, ${cloudCount} synced` : ""}${localCount > 0 ? `, ${localCount} local-only` : ""})`
|
|
279
|
+
: "✗ — none found";
|
|
280
|
+
console.log(` Prompts: ${promptSummary}`);
|
|
244
281
|
console.log(` Sweeps: ${assets.sweeps.length > 0 ? `✓ (${assets.sweeps.length})` : "— none found"}`);
|
|
245
282
|
console.log(` Agents: ${assets.agents.length > 0 ? `✓ (${assets.agents.length} targets)` : "✗ — run \`prompts-gpt sync\`"}`);
|
|
246
|
-
|
|
283
|
+
if (availableProviders.length > 0) {
|
|
284
|
+
console.log(` Providers: ✓`);
|
|
285
|
+
for (const p of availableProviders) {
|
|
286
|
+
console.log(` ${p.provider}: ${p.bin} | model: ${p.modelDefault}${p.version ? ` | ${p.version}` : ""}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.log(" Providers: ✗ — no CLI found");
|
|
291
|
+
}
|
|
247
292
|
console.log("");
|
|
248
293
|
if (assets.prompts.length > 0 && availableProviders.length > 0) {
|
|
249
294
|
console.log("Ready to run:");
|
|
250
295
|
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${assets.prompts[0].file}`);
|
|
251
296
|
if (assets.sweeps.length > 0) {
|
|
252
|
-
|
|
297
|
+
for (const s of assets.sweeps) {
|
|
298
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
299
|
+
}
|
|
253
300
|
}
|
|
254
301
|
}
|
|
255
302
|
else {
|
|
256
|
-
console.log("
|
|
303
|
+
console.log("Not ready yet. Quick fix:");
|
|
304
|
+
console.log(" prompts-gpt quickstart");
|
|
305
|
+
console.log("");
|
|
306
|
+
console.log("Or step by step:");
|
|
257
307
|
let step = 1;
|
|
258
308
|
if (!assets.credentialsFound)
|
|
259
309
|
console.log(` ${step++}. prompts-gpt init --token <project-token>`);
|
|
@@ -294,18 +344,26 @@ async function runCommand(command, flags) {
|
|
|
294
344
|
if (!promptFile && !Boolean(flags.json)) {
|
|
295
345
|
if (!config.defaultPromptFile && config.batchDefaults.promptFiles.length === 0 && !config.batchDefaults.manifestPath) {
|
|
296
346
|
const assets = await discoverWorkspaceAssets(cwd);
|
|
297
|
-
if (assets.prompts.length > 0
|
|
298
|
-
|
|
347
|
+
if (assets.prompts.length > 0 && isTTYInteractive(flags)) {
|
|
348
|
+
const promptOptions = assets.prompts.map((p) => ({
|
|
349
|
+
label: `${p.slug} — ${p.title}`,
|
|
350
|
+
value: `.prompts-gpt/${p.file}`,
|
|
351
|
+
}));
|
|
352
|
+
const picked = await interactiveSelect("Select a prompt to run:", promptOptions);
|
|
353
|
+
flags["prompt-file"] = picked;
|
|
354
|
+
}
|
|
355
|
+
else if (assets.prompts.length > 0 || assets.sweeps.length > 0) {
|
|
356
|
+
console.log("No default prompt configured. Available options:\n");
|
|
299
357
|
if (assets.prompts.length > 0) {
|
|
300
358
|
console.log("Prompt packs:");
|
|
301
359
|
for (const p of assets.prompts) {
|
|
302
|
-
console.log(` prompts-gpt run
|
|
360
|
+
console.log(` prompts-gpt run -f .prompts-gpt/${p.file}`);
|
|
303
361
|
}
|
|
304
362
|
}
|
|
305
363
|
if (assets.sweeps.length > 0) {
|
|
306
|
-
console.log("\nSweep prompts:");
|
|
364
|
+
console.log("\nSweep prompts (use `sweep` command):");
|
|
307
365
|
for (const s of assets.sweeps) {
|
|
308
|
-
console.log(` prompts-gpt sweep
|
|
366
|
+
console.log(` prompts-gpt sweep -f ${s.file}`);
|
|
309
367
|
}
|
|
310
368
|
}
|
|
311
369
|
console.log("\nOr set a default: prompts-gpt setup --prompt-file <path>");
|
|
@@ -313,12 +371,54 @@ async function runCommand(command, flags) {
|
|
|
313
371
|
}
|
|
314
372
|
}
|
|
315
373
|
}
|
|
374
|
+
const runProviders = await detectProviders(cwd);
|
|
375
|
+
const runAvailable = runProviders.filter((p) => p.available);
|
|
376
|
+
if (!getStringFlag(flags, "agent") && isTTYInteractive(flags) && !Boolean(flags.json) && runAvailable.length > 1) {
|
|
377
|
+
const providerOpts = runAvailable.map((p) => ({
|
|
378
|
+
label: `${p.provider} (${p.modelDefault}${p.version ? `, ${p.version}` : ""})`,
|
|
379
|
+
value: p.provider,
|
|
380
|
+
}));
|
|
381
|
+
providerOpts.push({ label: "router (auto-select)", value: "router" });
|
|
382
|
+
flags.agent = await interactiveSelect("Select a provider:", providerOpts);
|
|
383
|
+
}
|
|
316
384
|
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
385
|
+
if (Boolean(flags["dry-run"])) {
|
|
386
|
+
const providers = await detectProviders(cwd);
|
|
387
|
+
const resolvedProvider = resolveRunProvider(agent, providers, config.providerOrder);
|
|
388
|
+
const resolvedModel = getStringFlag(flags, "model")?.trim() || config.modelOverrides[resolvedProvider]?.trim() || "";
|
|
389
|
+
let resolvedPrompt = promptFile || getStringFlag(flags, "prompt-file") || config.defaultPromptFile || null;
|
|
390
|
+
if (!resolvedPrompt) {
|
|
391
|
+
try {
|
|
392
|
+
const { resolveDefaultPromptFile: resolvePf } = await import("./index.js");
|
|
393
|
+
resolvedPrompt = await resolvePf(cwd, config);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
resolvedPrompt = null;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const agentStr = getStringFlag(flags, "agent") ? agent : `${agent} (auto-selected)`;
|
|
400
|
+
console.log("[dry-run] Would execute:");
|
|
401
|
+
console.log(` Agent: ${agentStr}`);
|
|
402
|
+
console.log(` Provider: ${resolvedProvider}`);
|
|
403
|
+
console.log(` Model: ${resolvedModel || "(default)"}`);
|
|
404
|
+
console.log(` Prompt: ${resolvedPrompt || "(none found — pass --prompt-file)"}`);
|
|
405
|
+
console.log(` Timeout: ${getStringFlag(flags, "timeout") || config.timeoutSeconds}s`);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const modelFlag = getStringFlag(flags, "model");
|
|
409
|
+
if (modelFlag && !Boolean(flags.json) && agent !== "router") {
|
|
410
|
+
const providers = await detectProviders(cwd);
|
|
411
|
+
const resolvedProvider = resolveRunProvider(agent, providers, config.providerOrder);
|
|
412
|
+
const mismatchWarning = warnModelProviderMismatch(resolvedProvider, modelFlag);
|
|
413
|
+
if (mismatchWarning) {
|
|
414
|
+
console.error(`[warning] ${mismatchWarning}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
317
417
|
const result = await runPrompt({
|
|
318
418
|
cwd,
|
|
319
419
|
promptFile,
|
|
320
420
|
agent,
|
|
321
|
-
model:
|
|
421
|
+
model: modelFlag,
|
|
322
422
|
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
323
423
|
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
324
424
|
runId: getStringFlag(flags, "run-id"),
|
|
@@ -331,14 +431,31 @@ async function runCommand(command, flags) {
|
|
|
331
431
|
console.log(JSON.stringify(result, null, 2));
|
|
332
432
|
return;
|
|
333
433
|
}
|
|
334
|
-
const agentLabel = getStringFlag(flags, "agent") ? result.provider : `${result.provider} (auto
|
|
434
|
+
const agentLabel = getStringFlag(flags, "agent") ? result.provider : `${result.provider} (auto — first available from provider order)`;
|
|
335
435
|
console.log(`Run ID: ${result.runId}`);
|
|
336
436
|
console.log(`Provider: ${agentLabel} | Model: ${result.model}`);
|
|
337
437
|
console.log(`Exit code: ${result.exitCode}`);
|
|
338
438
|
console.log(`Duration: ${formatDuration(result.durationMs)}`);
|
|
439
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
440
|
+
console.log(`Tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
441
|
+
}
|
|
339
442
|
console.log(`Run dir: ${result.runDir}`);
|
|
340
443
|
console.log(`Summary: ${result.summaryFile}`);
|
|
341
444
|
console.log(`Log: ${result.logFile}`);
|
|
445
|
+
if (result.exitCode === 0) {
|
|
446
|
+
console.log("");
|
|
447
|
+
console.log(`View results: cat ${result.summaryFile}`);
|
|
448
|
+
}
|
|
449
|
+
if (result.exitCode !== 0) {
|
|
450
|
+
const diagnostics = await extractRunDiagnostics(result.logFile, result.provider, result.model);
|
|
451
|
+
if (diagnostics.length > 0) {
|
|
452
|
+
console.log("");
|
|
453
|
+
console.log("Diagnostics:");
|
|
454
|
+
for (const d of diagnostics) {
|
|
455
|
+
console.log(` ${d}`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
342
459
|
return;
|
|
343
460
|
}
|
|
344
461
|
if (command === "run-batch") {
|
|
@@ -379,9 +496,13 @@ async function runCommand(command, flags) {
|
|
|
379
496
|
return;
|
|
380
497
|
}
|
|
381
498
|
console.log(`Batch complete: total=${result.total} success=${result.success} failed=${result.failed}`);
|
|
499
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
500
|
+
console.log(`Batch tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
501
|
+
}
|
|
382
502
|
for (const [idx, run] of result.results.entries()) {
|
|
383
503
|
const status = run.exitCode === 0 ? "ok" : "FAIL";
|
|
384
|
-
|
|
504
|
+
const usageStr = hasTokenUsage(run.tokenUsage) ? `, tokens=${run.tokenUsage.totalTokens.toLocaleString()}` : "";
|
|
505
|
+
console.log(` [${idx + 1}/${result.total}] ${status} ${path.basename(run.promptFile)} -> ${run.provider} (exit=${run.exitCode}, ${formatDuration(run.durationMs)}${usageStr})`);
|
|
385
506
|
}
|
|
386
507
|
return;
|
|
387
508
|
}
|
|
@@ -391,41 +512,141 @@ async function runCommand(command, flags) {
|
|
|
391
512
|
const config = await loadRunConfig(cwd);
|
|
392
513
|
warnOnConfigIssues(config);
|
|
393
514
|
if (!sweepPromptFile && !Boolean(flags.json)) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
515
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
516
|
+
if (assets.sweeps.length === 1) {
|
|
517
|
+
const autoFile = assets.sweeps[0].file;
|
|
518
|
+
const iterFromFm = await readSweepIterationsFromFrontmatter(path.resolve(cwd, autoFile));
|
|
519
|
+
console.log(`Auto-selected sweep: ${path.basename(autoFile)}${iterFromFm ? ` (${iterFromFm} iterations from frontmatter)` : ""}`);
|
|
520
|
+
flags["prompt-file"] = autoFile;
|
|
521
|
+
if (iterFromFm && !getStringFlag(flags, "iterations")) {
|
|
522
|
+
flags.iterations = String(iterFromFm);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
else if (assets.sweeps.length > 1) {
|
|
526
|
+
if (isTTYInteractive(flags)) {
|
|
527
|
+
const sweepOptions = await Promise.all(assets.sweeps.map(async (s) => {
|
|
528
|
+
const fm = await readSweepFrontmatter(path.resolve(cwd, s.file));
|
|
529
|
+
const iterLabel = fm.iterations ? ` (${fm.iterations} iterations)` : "";
|
|
530
|
+
const titleLabel = fm.title ? ` — ${fm.title}` : "";
|
|
531
|
+
return { label: `${path.basename(s.file, ".md")}${titleLabel}${iterLabel}`, value: s.file };
|
|
532
|
+
}));
|
|
533
|
+
const picked = await interactiveSelect("Select a sweep file:", sweepOptions);
|
|
534
|
+
flags["prompt-file"] = picked;
|
|
535
|
+
const iterFromFm = await readSweepIterationsFromFrontmatter(path.resolve(cwd, picked));
|
|
536
|
+
if (iterFromFm && !getStringFlag(flags, "iterations")) {
|
|
537
|
+
flags.iterations = String(iterFromFm);
|
|
400
538
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
console.log(`${assets.sweeps.length} sweep files found. Pick one with --prompt-file:\n`);
|
|
542
|
+
for (const s of assets.sweeps) {
|
|
543
|
+
const iterCount = await readSweepIterationsFromFrontmatter(path.resolve(cwd, s.file));
|
|
544
|
+
const iterFlag = iterCount ? ` --iterations ${iterCount}` : "";
|
|
545
|
+
console.log(` prompts-gpt sweep -f ${s.file}${iterFlag}`);
|
|
406
546
|
}
|
|
407
|
-
console.log("\nOr set a default: prompts-gpt setup --prompt-file <path>");
|
|
408
547
|
return;
|
|
409
548
|
}
|
|
410
549
|
}
|
|
550
|
+
else {
|
|
551
|
+
console.log("No sweep files found.");
|
|
552
|
+
console.log(" Create .prompts-gpt/sweeps/<name>.md to add sweep prompts.");
|
|
553
|
+
console.log(" Run `prompts-gpt list` to see what's available.");
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
if (!getStringFlag(flags, "iterations") && getStringFlag(flags, "prompt-file")) {
|
|
558
|
+
const iterFromFm = await readSweepIterationsFromFrontmatter(path.resolve(cwd, getStringFlag(flags, "prompt-file")));
|
|
559
|
+
if (iterFromFm) {
|
|
560
|
+
flags.iterations = String(iterFromFm);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const providers = await detectProviders(cwd);
|
|
564
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
565
|
+
if (!getStringFlag(flags, "agent") && isTTYInteractive(flags) && !Boolean(flags.json) && availableProviders.length > 1) {
|
|
566
|
+
const providerOptions = availableProviders.map((p) => ({
|
|
567
|
+
label: `${p.provider} (${p.modelDefault}${p.version ? `, ${p.version}` : ""})`,
|
|
568
|
+
value: p.provider,
|
|
569
|
+
}));
|
|
570
|
+
providerOptions.push({ label: "router (auto-select best available)", value: "router" });
|
|
571
|
+
const picked = await interactiveSelect("Select a provider:", providerOptions);
|
|
572
|
+
flags.agent = picked;
|
|
573
|
+
}
|
|
574
|
+
if (!getStringFlag(flags, "model") && isTTYInteractive(flags) && !Boolean(flags.json)) {
|
|
575
|
+
const currentAgent = resolveRunAgent(flags, config.defaultAgent);
|
|
576
|
+
if (currentAgent !== "router") {
|
|
577
|
+
const defaultModel = config.modelOverrides[currentAgent]?.trim() || "";
|
|
578
|
+
const providerDefault = availableProviders.find((p) => p.provider === currentAgent)?.modelDefault || "";
|
|
579
|
+
const hint = defaultModel || providerDefault;
|
|
580
|
+
const modelInput = await interactiveInput("Model", hint);
|
|
581
|
+
if (modelInput && modelInput !== hint) {
|
|
582
|
+
flags.model = modelInput;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
if (!getStringFlag(flags, "iterations") && isTTYInteractive(flags) && !Boolean(flags.json)) {
|
|
587
|
+
const fmIter = await readSweepIterationsFromFrontmatter(path.resolve(cwd, getStringFlag(flags, "prompt-file")));
|
|
588
|
+
const defaultIter = fmIter ? String(fmIter) : "1";
|
|
589
|
+
const iterInput = await interactiveInput("Iterations", defaultIter);
|
|
590
|
+
if (iterInput) {
|
|
591
|
+
flags.iterations = iterInput;
|
|
592
|
+
}
|
|
411
593
|
}
|
|
412
594
|
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
595
|
+
if (isTTYInteractive(flags) && !Boolean(flags.json) && !Boolean(flags["dry-run"])) {
|
|
596
|
+
const resolvedProvider = resolveRunProvider(agent, providers, config.providerOrder);
|
|
597
|
+
const resolvedModel = getStringFlag(flags, "model")?.trim() || config.modelOverrides[resolvedProvider]?.trim() || availableProviders.find((p) => p.provider === resolvedProvider)?.modelDefault || "auto";
|
|
598
|
+
const resolvedIter = getStringFlag(flags, "iterations") || "1";
|
|
599
|
+
const sweepFile = getStringFlag(flags, "prompt-file") || "(default)";
|
|
600
|
+
const iterTimeout = parsePositiveIntFlag(getStringFlag(flags, "iteration-timeout"), "iteration-timeout") ?? 5400;
|
|
601
|
+
const estMaxMs = parseInt(resolvedIter, 10) * iterTimeout * 1000;
|
|
602
|
+
console.log("");
|
|
603
|
+
console.log(` Sweep: ${path.basename(sweepFile)}`);
|
|
604
|
+
console.log(` Provider: ${resolvedProvider}`);
|
|
605
|
+
console.log(` Model: ${resolvedModel}`);
|
|
606
|
+
console.log(` Iterations: ${resolvedIter}`);
|
|
607
|
+
console.log(` Max time: ~${formatDuration(estMaxMs)}`);
|
|
608
|
+
console.log("");
|
|
609
|
+
const confirm = await interactiveInput("Run this sweep? [Y/n]", "Y");
|
|
610
|
+
if (confirm.toLowerCase() === "n" || confirm.toLowerCase() === "no") {
|
|
611
|
+
console.log("Cancelled.");
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
413
615
|
const onProgress = Boolean(flags.json)
|
|
414
616
|
? undefined
|
|
415
617
|
: (event) => {
|
|
416
618
|
if (event.type === "preflight") {
|
|
417
619
|
const report = JSON.parse(event.message);
|
|
418
|
-
console.log(`
|
|
419
|
-
console.log(`
|
|
620
|
+
console.log(`Provider: ${report.provider} | Model: ${report.model} | Iterations: ${report.iterations}`);
|
|
621
|
+
console.log(`Branch: ${report.gitBranch} | Dirty files: ${report.gitDirtyFiles} | Free disk: ${report.diskFreeMb}MB`);
|
|
622
|
+
console.log(`Prompt: ${path.basename(report.promptFile)}`);
|
|
420
623
|
for (const w of report.warnings)
|
|
421
|
-
console.log(
|
|
624
|
+
console.log(`⚠ ${w}`);
|
|
422
625
|
}
|
|
423
626
|
else if (event.type === "iteration_start") {
|
|
424
627
|
console.log(`\n--- Iteration ${event.iteration}/${event.total} ---`);
|
|
628
|
+
if (process.stdout.isTTY) {
|
|
629
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
630
|
+
let fi = 0;
|
|
631
|
+
const startMs = Date.now();
|
|
632
|
+
const spinner = setInterval(() => {
|
|
633
|
+
const elapsed = formatDuration(Date.now() - startMs);
|
|
634
|
+
process.stdout.write(`\r${frames[fi++ % frames.length]} Running ${event.provider}... ${elapsed} `);
|
|
635
|
+
}, 120);
|
|
636
|
+
spinner.unref?.();
|
|
637
|
+
const clearSpinner = () => { clearInterval(spinner); process.stdout.write("\r\x1b[K"); };
|
|
638
|
+
globalThis.__sweepSpinner = clearSpinner;
|
|
639
|
+
}
|
|
425
640
|
}
|
|
426
641
|
else if (event.type === "iteration_end") {
|
|
642
|
+
const clearFn = globalThis.__sweepSpinner;
|
|
643
|
+
if (clearFn) {
|
|
644
|
+
clearFn();
|
|
645
|
+
delete globalThis.__sweepSpinner;
|
|
646
|
+
}
|
|
427
647
|
const elapsed = formatDuration(event.durationMs);
|
|
428
|
-
|
|
648
|
+
const icon = event.status === "success" ? "✓" : "✗";
|
|
649
|
+
console.log(`${icon} Iteration ${event.iteration} ${event.status} (${elapsed})`);
|
|
429
650
|
}
|
|
430
651
|
else if (event.type === "attempt_retry") {
|
|
431
652
|
console.log(`[retry] iteration ${event.iteration}, attempt ${event.attempt}/${event.maxAttempts}, backoff ${event.backoffMs}ms`);
|
|
@@ -454,6 +675,8 @@ async function runCommand(command, flags) {
|
|
|
454
675
|
dryRun: Boolean(flags["dry-run"]),
|
|
455
676
|
maxRunDirs: parsePositiveIntFlag(getStringFlag(flags, "max-run-dirs"), "max-run-dirs"),
|
|
456
677
|
summaryLines: parsePositiveIntFlag(getStringFlag(flags, "summary-lines"), "summary-lines"),
|
|
678
|
+
background: Boolean(flags.background),
|
|
679
|
+
permissionMode: getStringFlag(flags, "permission-mode"),
|
|
457
680
|
onProgress,
|
|
458
681
|
});
|
|
459
682
|
if (Boolean(flags.json)) {
|
|
@@ -461,11 +684,25 @@ async function runCommand(command, flags) {
|
|
|
461
684
|
return;
|
|
462
685
|
}
|
|
463
686
|
if (result.dryRun) {
|
|
687
|
+
const iterTimeout = parsePositiveIntFlag(getStringFlag(flags, "iteration-timeout"), "iteration-timeout") ?? 5400;
|
|
688
|
+
const estMaxDuration = result.totalIterations * iterTimeout;
|
|
464
689
|
console.log("[dry-run] Would execute sweep with:");
|
|
465
690
|
console.log(` Provider: ${result.provider}`);
|
|
466
691
|
console.log(` Model: ${result.model}`);
|
|
467
692
|
console.log(` Iterations: ${result.totalIterations}`);
|
|
468
693
|
console.log(` Prompt: ${result.promptFile}`);
|
|
694
|
+
console.log(` Max duration: ~${formatDuration(estMaxDuration * 1000)} (${result.totalIterations} x ${formatDuration(iterTimeout * 1000)})`);
|
|
695
|
+
try {
|
|
696
|
+
const { readFile: fsRead } = await import("node:fs/promises");
|
|
697
|
+
const previewText = await fsRead(result.promptFile, "utf8");
|
|
698
|
+
const previewLines = previewText.split("\n").slice(0, 5);
|
|
699
|
+
console.log(` Prompt preview:`);
|
|
700
|
+
for (const line of previewLines)
|
|
701
|
+
console.log(` ${line}`);
|
|
702
|
+
if (previewText.split("\n").length > 5)
|
|
703
|
+
console.log(` ... (${previewText.split("\n").length - 5} more lines)`);
|
|
704
|
+
}
|
|
705
|
+
catch { /* skip preview */ }
|
|
469
706
|
return;
|
|
470
707
|
}
|
|
471
708
|
console.log(`Run ID: ${result.runId}`);
|
|
@@ -473,13 +710,154 @@ async function runCommand(command, flags) {
|
|
|
473
710
|
console.log(`Prompt: ${result.promptFile}`);
|
|
474
711
|
console.log(`Iterations: ${result.succeeded}/${result.totalIterations} succeeded`);
|
|
475
712
|
console.log(`Duration: ${formatDuration(result.totalDurationMs)}`);
|
|
713
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
714
|
+
console.log(`Tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
715
|
+
}
|
|
476
716
|
console.log(`Run dir: ${result.runDir}`);
|
|
477
717
|
console.log(`Manifest: ${result.manifestFile}`);
|
|
718
|
+
if (result.iterations.length > 1) {
|
|
719
|
+
console.log("");
|
|
720
|
+
console.log("Per-iteration results:");
|
|
721
|
+
for (const iter of result.iterations) {
|
|
722
|
+
const tools = iter.toolCounts;
|
|
723
|
+
const toolStr = tools.total > 0 ? ` | tools: ${tools.total} (R:${tools.reads} W:${tools.writes} S:${tools.shells})` : "";
|
|
724
|
+
const usageStr = hasTokenUsage(iter.tokenUsage) ? ` | tokens: ${iter.tokenUsage.totalTokens.toLocaleString()}` : "";
|
|
725
|
+
console.log(` [${iter.iteration}/${result.totalIterations}] ${iter.status} (${formatDuration(iter.durationMs)})${toolStr}${usageStr}`);
|
|
726
|
+
}
|
|
727
|
+
const totalTools = result.iterations.reduce((acc, i) => ({
|
|
728
|
+
reads: acc.reads + i.toolCounts.reads, writes: acc.writes + i.toolCounts.writes,
|
|
729
|
+
shells: acc.shells + i.toolCounts.shells, searches: acc.searches + i.toolCounts.searches,
|
|
730
|
+
webSearches: acc.webSearches + i.toolCounts.webSearches, total: acc.total + i.toolCounts.total,
|
|
731
|
+
}), { reads: 0, writes: 0, shells: 0, searches: 0, webSearches: 0, total: 0 });
|
|
732
|
+
if (totalTools.total > 0) {
|
|
733
|
+
console.log(` Total tools: ${totalTools.total} (reads: ${totalTools.reads}, writes: ${totalTools.writes}, shells: ${totalTools.shells}, searches: ${totalTools.searches})`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
console.log("");
|
|
737
|
+
console.log("Inspect results:");
|
|
738
|
+
console.log(` cat ${result.manifestFile}`);
|
|
739
|
+
console.log(` ls ${result.runDir}`);
|
|
478
740
|
if (result.failed > 0) {
|
|
479
741
|
process.exitCode = 1;
|
|
480
742
|
}
|
|
481
743
|
return;
|
|
482
744
|
}
|
|
745
|
+
if (command === "quickstart") {
|
|
746
|
+
const cwd = getResolvedCwd(flags);
|
|
747
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
748
|
+
const providers = await detectProviders(cwd);
|
|
749
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
750
|
+
console.log("Prompts-GPT Quickstart");
|
|
751
|
+
console.log("======================");
|
|
752
|
+
console.log("");
|
|
753
|
+
if (!assets.credentialsFound) {
|
|
754
|
+
console.log("Step 1: Save your project token");
|
|
755
|
+
console.log(" prompts-gpt init --token-prompt");
|
|
756
|
+
console.log("");
|
|
757
|
+
console.log(" Get your token from: https://prompts-gpt.com/studio/projects");
|
|
758
|
+
console.log("");
|
|
759
|
+
console.log("Run `prompts-gpt quickstart` again after saving your token.");
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
console.log("✓ Credentials found");
|
|
763
|
+
if (!assets.configFound) {
|
|
764
|
+
console.log("→ Setting up config...");
|
|
765
|
+
try {
|
|
766
|
+
await initRunConfig({ cwd, overwrite: false });
|
|
767
|
+
console.log("✓ Config created");
|
|
768
|
+
}
|
|
769
|
+
catch {
|
|
770
|
+
console.log("✓ Config already exists");
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
console.log("✓ Config found");
|
|
775
|
+
}
|
|
776
|
+
if (availableProviders.length === 0) {
|
|
777
|
+
console.log("");
|
|
778
|
+
console.log("✗ No provider CLIs found. Install at least one:");
|
|
779
|
+
console.log(" - codex: npm install -g @openai/codex");
|
|
780
|
+
console.log(" - claude: npm install -g @anthropic-ai/claude-code");
|
|
781
|
+
console.log(" - cursor: Install Cursor IDE (includes `agent` CLI)");
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
console.log(`✓ Providers: ${availableProviders.map((p) => p.provider).join(", ")}`);
|
|
785
|
+
if (assets.prompts.length === 0 && assets.sweeps.length === 0) {
|
|
786
|
+
console.log("");
|
|
787
|
+
console.log("→ No prompts found. Syncing from Prompts Studio...");
|
|
788
|
+
try {
|
|
789
|
+
const clientOpts = await resolveClientOptions("quickstart", flags).catch(() => null);
|
|
790
|
+
if (clientOpts) {
|
|
791
|
+
const qsClient = new PromptsGptClient(clientOpts);
|
|
792
|
+
const pulledPrompts = await qsClient.pullPrompts();
|
|
793
|
+
if (pulledPrompts.length > 0) {
|
|
794
|
+
const syncResult = await syncPrompts(pulledPrompts, { cwd, agent: "all" });
|
|
795
|
+
console.log(`✓ Synced ${syncResult.markdown.written.length} prompt(s) and ${syncResult.agents.written.length} agent file(s)`);
|
|
796
|
+
const refreshed = await discoverWorkspaceAssets(cwd);
|
|
797
|
+
if (refreshed.prompts.length > 0 || refreshed.sweeps.length > 0) {
|
|
798
|
+
console.log(`✓ Prompts: ${refreshed.prompts.length} prompt packs, ${refreshed.sweeps.length} sweeps`);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
console.log("No prompts found in your Prompts Studio library.");
|
|
803
|
+
console.log(" Configure prompts at: https://prompts-gpt.com/studio/projects");
|
|
804
|
+
console.log(" Or run: prompts-gpt generate --goal \"Your task\"");
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
console.log("✗ Could not sync (credentials issue). Run manually:");
|
|
810
|
+
console.log(" prompts-gpt sync");
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
catch (syncErr) {
|
|
815
|
+
console.log(`✗ Sync failed: ${syncErr instanceof Error ? syncErr.message : String(syncErr)}`);
|
|
816
|
+
console.log(" Run manually: prompts-gpt sync");
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
const refreshedAssets = await discoverWorkspaceAssets(cwd);
|
|
820
|
+
if (refreshedAssets.prompts.length === 0 && refreshedAssets.sweeps.length === 0) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
console.log(`✓ Prompts: ${assets.prompts.length} prompt packs, ${assets.sweeps.length} sweeps`);
|
|
825
|
+
console.log("");
|
|
826
|
+
console.log("You're ready!");
|
|
827
|
+
if (isTTYInteractive() && (assets.prompts.length > 0 || assets.sweeps.length > 0)) {
|
|
828
|
+
const qsOptions = [];
|
|
829
|
+
for (const s of assets.sweeps) {
|
|
830
|
+
qsOptions.push({ label: `sweep: ${s.name}`, value: `sweep:${s.file}` });
|
|
831
|
+
}
|
|
832
|
+
for (const p of assets.prompts.slice(0, 5)) {
|
|
833
|
+
qsOptions.push({ label: `run: ${p.title}`, value: `run:.prompts-gpt/${p.file}` });
|
|
834
|
+
}
|
|
835
|
+
qsOptions.push({ label: "(show commands and exit)", value: "exit" });
|
|
836
|
+
console.log("");
|
|
837
|
+
const qsPicked = await interactiveSelect("Run something now?", qsOptions);
|
|
838
|
+
if (qsPicked !== "exit") {
|
|
839
|
+
const [action, file] = qsPicked.split(":", 2);
|
|
840
|
+
const cmd = action === "sweep" ? "sweep" : "run";
|
|
841
|
+
console.log(`\nRunning: prompts-gpt ${cmd} -f ${file}\n`);
|
|
842
|
+
const { spawnSync: spSync } = await import("node:child_process");
|
|
843
|
+
const result = spSync(process.execPath, [process.argv[1], cmd, "-f", file], { stdio: "inherit", cwd });
|
|
844
|
+
process.exitCode = result.status ?? 1;
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
console.log("");
|
|
849
|
+
console.log("Try these commands:");
|
|
850
|
+
console.log("");
|
|
851
|
+
if (assets.prompts.length > 0) {
|
|
852
|
+
console.log(` prompts-gpt run -f .prompts-gpt/${assets.prompts[0].file}`);
|
|
853
|
+
}
|
|
854
|
+
if (assets.sweeps.length > 0) {
|
|
855
|
+
console.log(` prompts-gpt sweep -f ${assets.sweeps[0].file}`);
|
|
856
|
+
}
|
|
857
|
+
console.log(" prompts-gpt list — see all available prompts and sweeps");
|
|
858
|
+
console.log(" prompts-gpt status — check workspace readiness");
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
483
861
|
if (command === "load-config") {
|
|
484
862
|
const cwd = getResolvedCwd(flags);
|
|
485
863
|
const client = await createClientForCommand(command, flags);
|
|
@@ -532,10 +910,22 @@ async function runCommand(command, flags) {
|
|
|
532
910
|
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${firstFile}`);
|
|
533
911
|
}
|
|
534
912
|
}
|
|
913
|
+
const lcAssets = await discoverWorkspaceAssets(cwd);
|
|
914
|
+
if (lcAssets.sweeps.length > 0) {
|
|
915
|
+
console.log(`\nSweep files available (${lcAssets.sweeps.length}):`);
|
|
916
|
+
for (const s of lcAssets.sweeps) {
|
|
917
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
535
920
|
return;
|
|
536
921
|
}
|
|
537
922
|
if (command === "init") {
|
|
538
|
-
|
|
923
|
+
let token = await resolveTokenInput(flags, { command });
|
|
924
|
+
if (!token && process.stdin.isTTY && process.stdout.isTTY) {
|
|
925
|
+
console.log("No token flag provided — prompting interactively.");
|
|
926
|
+
console.log("Get your token from: https://prompts-gpt.com/studio/projects\n");
|
|
927
|
+
token = await readTokenFromPrompt(command);
|
|
928
|
+
}
|
|
539
929
|
if (!token) {
|
|
540
930
|
throw new CliError("Run `prompts-gpt init --token <project-token>`, `--token-stdin`, or `--token-prompt`.", CLI_EXIT_CODES.validation, {
|
|
541
931
|
helpCommand: "init",
|
|
@@ -573,7 +963,10 @@ async function runCommand(command, flags) {
|
|
|
573
963
|
});
|
|
574
964
|
console.log(`Saved Prompts-GPT credentials to ${result.credentialsPath}`);
|
|
575
965
|
console.log("The credentials file is added to .gitignore.");
|
|
576
|
-
console.log("
|
|
966
|
+
console.log("");
|
|
967
|
+
console.log("Next steps:");
|
|
968
|
+
console.log(" prompts-gpt quickstart — interactive setup (recommended)");
|
|
969
|
+
console.log(" prompts-gpt sync — pull prompts and sync agent files");
|
|
577
970
|
return;
|
|
578
971
|
}
|
|
579
972
|
if (command === "pull") {
|
|
@@ -593,28 +986,30 @@ async function runCommand(command, flags) {
|
|
|
593
986
|
if (result.skipped.length) {
|
|
594
987
|
console.log(`Skipped ${result.skipped.length} existing file(s). Use --overwrite to replace them.`);
|
|
595
988
|
}
|
|
989
|
+
if (result.written.length > 0) {
|
|
990
|
+
console.log("");
|
|
991
|
+
console.log("Run a pulled prompt:");
|
|
992
|
+
console.log(` prompts-gpt run --prompt-file ${result.written[0]}`);
|
|
993
|
+
console.log(" prompts-gpt list — see all available prompts");
|
|
994
|
+
}
|
|
596
995
|
return;
|
|
597
996
|
}
|
|
598
997
|
if (command === "generate") {
|
|
599
998
|
validateToolFlag(getStringFlag(flags, "tool"));
|
|
600
999
|
const goal = getStringFlag(flags, "goal");
|
|
601
1000
|
if (!goal) {
|
|
602
|
-
throw new CliError("Prompt generation requires `--goal
|
|
603
|
-
|
|
604
|
-
|
|
1001
|
+
throw new CliError("Prompt generation requires `--goal`.\n\n" +
|
|
1002
|
+
"Example:\n" +
|
|
1003
|
+
" prompts-gpt generate --goal \"Review pull requests for security issues\"\n" +
|
|
1004
|
+
" prompts-gpt generate --goal \"Write unit tests\" --sync-agents\n\n" +
|
|
1005
|
+
"Use --sync-agents to also write agent files (AGENTS.md, .cursor/rules, etc.).", CLI_EXIT_CODES.validation, { helpCommand: "generate" });
|
|
605
1006
|
}
|
|
606
1007
|
validateAgentFlag(getStringFlag(flags, "agent"));
|
|
1008
|
+
if (!Boolean(flags.json)) {
|
|
1009
|
+
printDataTransmissionNotice("generate", { goal, context: getStringFlag(flags, "context"), constraints: getStringFlag(flags, "constraints") });
|
|
1010
|
+
}
|
|
607
1011
|
const client = await createClientForCommand(command, flags);
|
|
608
|
-
const prompt = await client.generatePrompt(
|
|
609
|
-
goal,
|
|
610
|
-
context: getStringFlag(flags, "context") || "",
|
|
611
|
-
constraints: getStringFlag(flags, "constraints") || "",
|
|
612
|
-
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
613
|
-
tool: getStringFlag(flags, "tool") || "Codex",
|
|
614
|
-
mode: getStringFlag(flags, "mode") || "implement",
|
|
615
|
-
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
616
|
-
includeWebSearch: Boolean(flags["web-search"]),
|
|
617
|
-
});
|
|
1012
|
+
const prompt = await client.generatePrompt(buildGenerateInput(flags));
|
|
618
1013
|
const cwd = getResolvedCwd(flags);
|
|
619
1014
|
const result = await writePromptMarkdownFiles([prompt], {
|
|
620
1015
|
cwd,
|
|
@@ -624,7 +1019,12 @@ async function runCommand(command, flags) {
|
|
|
624
1019
|
const shouldSyncAgents = Boolean(flags["sync-agents"]) || typeof getStringFlag(flags, "agent") === "string";
|
|
625
1020
|
if (shouldSyncAgents) {
|
|
626
1021
|
const target = getStringFlag(flags, "agent") || "all";
|
|
627
|
-
const pulled = await client.pullPrompts().catch(() =>
|
|
1022
|
+
const pulled = await client.pullPrompts().catch((err) => {
|
|
1023
|
+
if (!Boolean(flags.json)) {
|
|
1024
|
+
console.error(`[warning] Could not pull existing prompts for agent sync: ${err.message}`);
|
|
1025
|
+
}
|
|
1026
|
+
return [];
|
|
1027
|
+
});
|
|
628
1028
|
const syncedPrompts = mergePromptPacks([prompt, ...pulled]);
|
|
629
1029
|
const agentResult = await writeAgentFiles(syncedPrompts, {
|
|
630
1030
|
cwd,
|
|
@@ -653,17 +1053,11 @@ async function runCommand(command, flags) {
|
|
|
653
1053
|
const goal = getStringFlag(flags, "goal");
|
|
654
1054
|
const generatedOnly = Boolean(flags["generated-only"]);
|
|
655
1055
|
const client = await createClientForCommand(command, flags);
|
|
1056
|
+
if (goal && !Boolean(flags.json)) {
|
|
1057
|
+
printDataTransmissionNotice("sync", { goal, context: getStringFlag(flags, "context"), constraints: getStringFlag(flags, "constraints") });
|
|
1058
|
+
}
|
|
656
1059
|
if (goal) {
|
|
657
|
-
prompts.push(await client.generatePrompt(
|
|
658
|
-
goal,
|
|
659
|
-
context: getStringFlag(flags, "context") || "",
|
|
660
|
-
constraints: getStringFlag(flags, "constraints") || "",
|
|
661
|
-
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
662
|
-
tool: getStringFlag(flags, "tool") || "Codex",
|
|
663
|
-
mode: getStringFlag(flags, "mode") || "implement",
|
|
664
|
-
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
665
|
-
includeWebSearch: Boolean(flags["web-search"]),
|
|
666
|
-
}));
|
|
1060
|
+
prompts.push(await client.generatePrompt(buildGenerateInput(flags)));
|
|
667
1061
|
}
|
|
668
1062
|
if (!generatedOnly) {
|
|
669
1063
|
prompts.push(...await client.pullPrompts(buildPullQuery(flags, parsedLimit)));
|
|
@@ -691,6 +1085,21 @@ async function runCommand(command, flags) {
|
|
|
691
1085
|
}
|
|
692
1086
|
console.log(`Synced ${result.agents.written.length} agent file(s): ${result.agents.targets.join(", ")}.`);
|
|
693
1087
|
console.log(`Manifest: ${result.manifest.manifestPath}`);
|
|
1088
|
+
const syncCwd = getResolvedCwd(flags);
|
|
1089
|
+
const postSyncAssets = await discoverWorkspaceAssets(syncCwd);
|
|
1090
|
+
if (postSyncAssets.sweeps.length > 0) {
|
|
1091
|
+
console.log(`Sweeps: ${postSyncAssets.sweeps.length} sweep file(s) available.`);
|
|
1092
|
+
}
|
|
1093
|
+
const postProviders = await detectProviders(syncCwd);
|
|
1094
|
+
const postAvailable = postProviders.filter((p) => p.available);
|
|
1095
|
+
if (postAvailable.length > 0 && postSyncAssets.prompts.length > 0) {
|
|
1096
|
+
console.log("");
|
|
1097
|
+
console.log("Next steps:");
|
|
1098
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${postSyncAssets.prompts[0].file}`);
|
|
1099
|
+
if (postSyncAssets.sweeps.length > 0) {
|
|
1100
|
+
console.log(` prompts-gpt sweep --prompt-file ${postSyncAssets.sweeps[0].file}`);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
694
1103
|
return;
|
|
695
1104
|
}
|
|
696
1105
|
if (command === "project") {
|
|
@@ -744,7 +1153,11 @@ async function resolveClientOptions(command, flags) {
|
|
|
744
1153
|
}
|
|
745
1154
|
}
|
|
746
1155
|
if (!token) {
|
|
747
|
-
|
|
1156
|
+
const cloudCommands = new Set(["sync", "generate", "pull", "load-config", "project"]);
|
|
1157
|
+
const extra = cloudCommands.has(command)
|
|
1158
|
+
? `\n\nThis command connects to prompts-gpt.com. Set up credentials first:\n prompts-gpt init --token <project-token>\n prompts-gpt quickstart`
|
|
1159
|
+
: "";
|
|
1160
|
+
throw new CliError(`Project token is missing. Run \`prompts-gpt init --token <project-token>\` or pass \`--token\`, \`--token-stdin\`, or \`--token-prompt\` for this command.${extra}`, CLI_EXIT_CODES.auth, { helpCommand: command });
|
|
748
1161
|
}
|
|
749
1162
|
return {
|
|
750
1163
|
token,
|
|
@@ -911,7 +1324,7 @@ function getCommandOptions(command) {
|
|
|
911
1324
|
help: { type: "boolean" },
|
|
912
1325
|
cwd: { type: "string" },
|
|
913
1326
|
json: { type: "boolean" },
|
|
914
|
-
"prompt-file": { type: "string" },
|
|
1327
|
+
"prompt-file": { type: "string", short: "f" },
|
|
915
1328
|
agent: { type: "string" },
|
|
916
1329
|
model: { type: "string" },
|
|
917
1330
|
timeout: { type: "string" },
|
|
@@ -921,6 +1334,8 @@ function getCommandOptions(command) {
|
|
|
921
1334
|
"no-approve-mcps": { type: "boolean" },
|
|
922
1335
|
background: { type: "boolean" },
|
|
923
1336
|
"permission-mode": { type: "string" },
|
|
1337
|
+
"dry-run": { type: "boolean" },
|
|
1338
|
+
"non-interactive": { type: "boolean" },
|
|
924
1339
|
};
|
|
925
1340
|
}
|
|
926
1341
|
if (command === "sweep") {
|
|
@@ -928,10 +1343,10 @@ function getCommandOptions(command) {
|
|
|
928
1343
|
help: { type: "boolean" },
|
|
929
1344
|
cwd: { type: "string" },
|
|
930
1345
|
json: { type: "boolean" },
|
|
931
|
-
"prompt-file": { type: "string" },
|
|
1346
|
+
"prompt-file": { type: "string", short: "f" },
|
|
932
1347
|
agent: { type: "string" },
|
|
933
1348
|
model: { type: "string" },
|
|
934
|
-
iterations: { type: "string" },
|
|
1349
|
+
iterations: { type: "string", short: "n" },
|
|
935
1350
|
"iteration-timeout": { type: "string" },
|
|
936
1351
|
"max-retries": { type: "string" },
|
|
937
1352
|
"artifacts-dir": { type: "string" },
|
|
@@ -944,6 +1359,7 @@ function getCommandOptions(command) {
|
|
|
944
1359
|
"summary-lines": { type: "string" },
|
|
945
1360
|
background: { type: "boolean" },
|
|
946
1361
|
"permission-mode": { type: "string" },
|
|
1362
|
+
"non-interactive": { type: "boolean" },
|
|
947
1363
|
};
|
|
948
1364
|
}
|
|
949
1365
|
if (command === "run-batch") {
|
|
@@ -967,7 +1383,7 @@ function getCommandOptions(command) {
|
|
|
967
1383
|
agent: { type: "string" },
|
|
968
1384
|
};
|
|
969
1385
|
}
|
|
970
|
-
if (command === "list" || command === "status" || command === "validate" || command === "providers" || command === "doctor") {
|
|
1386
|
+
if (command === "quickstart" || command === "list" || command === "status" || command === "validate" || command === "providers" || command === "doctor") {
|
|
971
1387
|
return {
|
|
972
1388
|
help: { type: "boolean" },
|
|
973
1389
|
cwd: { type: "string" },
|
|
@@ -979,18 +1395,61 @@ function getCommandOptions(command) {
|
|
|
979
1395
|
});
|
|
980
1396
|
}
|
|
981
1397
|
function toCliParseError(error, command) {
|
|
982
|
-
const
|
|
1398
|
+
const runnableCmd = isRunnableCommand(command) ? command : undefined;
|
|
1399
|
+
const message = normalizeParseErrorMessage(error instanceof Error ? error.message : String(error), runnableCmd);
|
|
983
1400
|
return new CliError(message, CLI_EXIT_CODES.usage, {
|
|
984
1401
|
helpCommand: command,
|
|
985
1402
|
});
|
|
986
1403
|
}
|
|
987
|
-
function normalizeParseErrorMessage(message) {
|
|
1404
|
+
function normalizeParseErrorMessage(message, command) {
|
|
988
1405
|
const trimmed = message.trim();
|
|
989
1406
|
if (trimmed.startsWith("Unknown option")) {
|
|
990
|
-
|
|
1407
|
+
const match = trimmed.match(/Unknown option '(--[^']+)'/);
|
|
1408
|
+
const unknownFlag = match?.[1];
|
|
1409
|
+
const base = trimmed.endsWith(".") ? trimmed : `${trimmed}.`;
|
|
1410
|
+
if (unknownFlag && command) {
|
|
1411
|
+
const suggestion = suggestClosestFlag(unknownFlag, command);
|
|
1412
|
+
if (suggestion) {
|
|
1413
|
+
return `${base} Did you mean ${suggestion}?`;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
return base;
|
|
991
1417
|
}
|
|
992
1418
|
return trimmed;
|
|
993
1419
|
}
|
|
1420
|
+
function suggestClosestFlag(unknown, command) {
|
|
1421
|
+
const options = getCommandOptions(command);
|
|
1422
|
+
const flagName = unknown.replace(/^--/, "");
|
|
1423
|
+
const candidates = Object.keys(options);
|
|
1424
|
+
let best = null;
|
|
1425
|
+
let bestScore = 0;
|
|
1426
|
+
for (const candidate of candidates) {
|
|
1427
|
+
const score = computeFlagSimilarity(flagName, candidate);
|
|
1428
|
+
if (score > bestScore && score >= 0.4) {
|
|
1429
|
+
bestScore = score;
|
|
1430
|
+
best = candidate;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
return best ? `--${best}` : null;
|
|
1434
|
+
}
|
|
1435
|
+
function computeFlagSimilarity(a, b) {
|
|
1436
|
+
if (a === b)
|
|
1437
|
+
return 1;
|
|
1438
|
+
const shorter = a.length < b.length ? a : b;
|
|
1439
|
+
const longer = a.length < b.length ? b : a;
|
|
1440
|
+
if (longer.startsWith(shorter) || longer.endsWith(shorter))
|
|
1441
|
+
return 0.8;
|
|
1442
|
+
if (longer.includes(shorter) && shorter.length >= 3)
|
|
1443
|
+
return 0.6;
|
|
1444
|
+
if (shorter.length === 0)
|
|
1445
|
+
return 0;
|
|
1446
|
+
let matches = 0;
|
|
1447
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
|
1448
|
+
if (a[i] === b[i])
|
|
1449
|
+
matches++;
|
|
1450
|
+
}
|
|
1451
|
+
return matches / Math.max(a.length, b.length);
|
|
1452
|
+
}
|
|
994
1453
|
function validateFlagConflicts(command, flags) {
|
|
995
1454
|
const tokenSourceCount = [Boolean(flags.token), Boolean(flags["token-stdin"]), Boolean(flags["token-prompt"])].filter(Boolean).length;
|
|
996
1455
|
if (tokenSourceCount > 1) {
|
|
@@ -1266,32 +1725,36 @@ Usage:
|
|
|
1266
1725
|
prompts-gpt help [command]
|
|
1267
1726
|
prompts-gpt version
|
|
1268
1727
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
pull Download prompt packs as Markdown files
|
|
1274
|
-
generate Generate one prompt pack from a goal
|
|
1275
|
-
sync Generate and/or pull prompt packs, then sync agent files
|
|
1276
|
-
list Show available prompts, sweeps, and agent integrations
|
|
1728
|
+
Setup:
|
|
1729
|
+
quickstart Interactive setup — credentials, config, and first run
|
|
1730
|
+
init Save a project token
|
|
1731
|
+
setup Scaffold local orchestration config
|
|
1277
1732
|
status Show workspace readiness and next steps
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1733
|
+
doctor Validate prerequisites and config
|
|
1734
|
+
|
|
1735
|
+
Sync & Generate:
|
|
1736
|
+
sync Pull prompt packs and sync agent files
|
|
1737
|
+
pull Download prompt packs as Markdown files
|
|
1738
|
+
generate Generate a prompt pack from a goal
|
|
1739
|
+
load-config Pull config and prompts from Prompts Studio
|
|
1740
|
+
|
|
1741
|
+
Run:
|
|
1742
|
+
run Execute one prompt with a local agent (-f <file>)
|
|
1743
|
+
run-batch Execute multiple prompts
|
|
1744
|
+
sweep Multi-iteration execution (-f <file> -n <count>)
|
|
1745
|
+
|
|
1746
|
+
Inspect:
|
|
1747
|
+
list Show prompts, sweeps, and agent integrations
|
|
1748
|
+
validate Check config for errors
|
|
1749
|
+
providers Show detected provider CLIs
|
|
1750
|
+
project Show project linked to the token
|
|
1287
1751
|
|
|
1288
1752
|
Global options:
|
|
1289
1753
|
--help Show help
|
|
1290
1754
|
--version Show the current CLI version
|
|
1291
1755
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
Run agent profiles: ${ORCHESTRATION_AGENT_PROFILES.join(", ")}
|
|
1756
|
+
Providers: ${ORCHESTRATION_AGENT_PROFILES.filter((p) => p !== "router").join(", ")} (or router for auto-select)
|
|
1757
|
+
Agent targets: ${SUPPORTED_AGENT_TARGETS.join(", ")}
|
|
1295
1758
|
`);
|
|
1296
1759
|
}
|
|
1297
1760
|
function parsePositiveIntFlag(raw, flagName) {
|
|
@@ -1339,18 +1802,24 @@ function getCommandHelp(command) {
|
|
|
1339
1802
|
return `prompts-gpt init
|
|
1340
1803
|
|
|
1341
1804
|
Usage:
|
|
1342
|
-
prompts-gpt init
|
|
1805
|
+
prompts-gpt init [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1343
1806
|
|
|
1344
1807
|
Why use it:
|
|
1345
|
-
Stores a project token
|
|
1808
|
+
Stores a project token locally so you don't have to pass it on every command.
|
|
1809
|
+
If run without flags in an interactive terminal, it will prompt for the token.
|
|
1346
1810
|
|
|
1347
1811
|
Options:
|
|
1348
1812
|
--token <token> Project API token. Must start with pgpt_.
|
|
1349
|
-
--token-stdin Read the project token from stdin
|
|
1813
|
+
--token-stdin Read the project token from stdin (for CI/CD pipelines).
|
|
1350
1814
|
--token-prompt Prompt for the project token without echoing it.
|
|
1351
1815
|
--api-url <url> Custom API base URL for self-hosted instances.
|
|
1352
|
-
--cwd <path> Target project directory
|
|
1816
|
+
--cwd <path> Target project directory.
|
|
1353
1817
|
--help Show this command help.
|
|
1818
|
+
|
|
1819
|
+
Examples:
|
|
1820
|
+
prompts-gpt init # interactive prompt
|
|
1821
|
+
prompts-gpt init --token pgpt_abc123 # direct token
|
|
1822
|
+
printf '%s' "$TOKEN" | prompts-gpt init --token-stdin # CI/CD
|
|
1354
1823
|
`;
|
|
1355
1824
|
}
|
|
1356
1825
|
if (command === "setup") {
|
|
@@ -1411,6 +1880,10 @@ Usage:
|
|
|
1411
1880
|
Why use it:
|
|
1412
1881
|
Pulls prompt packs into local Markdown files so teams can review and use the same prompt assets inside their repository.
|
|
1413
1882
|
|
|
1883
|
+
Data privacy:
|
|
1884
|
+
Downloads prompts from your prompts-gpt.com project library.
|
|
1885
|
+
No local files or repo content are uploaded.
|
|
1886
|
+
|
|
1414
1887
|
Options:
|
|
1415
1888
|
--query <text> Search query for the project prompt library.
|
|
1416
1889
|
--q <text> Short alias for --query.
|
|
@@ -1437,6 +1910,11 @@ Usage:
|
|
|
1437
1910
|
Why use it:
|
|
1438
1911
|
Creates a new reusable prompt pack from a concrete developer goal, then optionally installs agent-readable files immediately.
|
|
1439
1912
|
|
|
1913
|
+
Data privacy:
|
|
1914
|
+
The text you pass via --goal, --context, and --constraints is sent to prompts-gpt.com
|
|
1915
|
+
for AI-powered prompt generation. No local files or repo content are uploaded.
|
|
1916
|
+
Do not include PII, secrets, or confidential data in these flags.
|
|
1917
|
+
|
|
1440
1918
|
Options:
|
|
1441
1919
|
--goal <text> Required. The task to generate a prompt pack for.
|
|
1442
1920
|
--context <text> Extra project or stack context for the generator.
|
|
@@ -1449,13 +1927,19 @@ Options:
|
|
|
1449
1927
|
--out <dir> Output directory inside the current project. Default: .prompts-gpt
|
|
1450
1928
|
--overwrite Replace an existing generated Markdown file.
|
|
1451
1929
|
--agent <targets> Sync agent files for specific targets after generation.
|
|
1452
|
-
|
|
1930
|
+
When set, also writes agent-specific files (AGENTS.md, .cursor/rules, etc.).
|
|
1931
|
+
--sync-agents Sync all agent files after generation (same as --agent all).
|
|
1453
1932
|
--token <token> Override the saved local token for this command only.
|
|
1454
1933
|
--token-stdin Read the override token from stdin for this command only.
|
|
1455
1934
|
--token-prompt Prompt for the override token without echoing it.
|
|
1456
1935
|
--api-url <url> Override the saved API base URL for this command only.
|
|
1457
1936
|
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
1458
1937
|
--help Show this command help.
|
|
1938
|
+
|
|
1939
|
+
Examples:
|
|
1940
|
+
prompts-gpt generate --goal "Review PRs for security issues"
|
|
1941
|
+
prompts-gpt generate --goal "Write unit tests" --sync-agents
|
|
1942
|
+
prompts-gpt generate --goal "Add error handling" --agent cursor,codex
|
|
1459
1943
|
`;
|
|
1460
1944
|
}
|
|
1461
1945
|
if (command === "sync") {
|
|
@@ -1467,6 +1951,13 @@ Usage:
|
|
|
1467
1951
|
Why use it:
|
|
1468
1952
|
Gives teams a one-command path to refresh Markdown prompts, agent files, and the local manifest from the same source of truth.
|
|
1469
1953
|
|
|
1954
|
+
Data privacy:
|
|
1955
|
+
Prompts are downloaded from your prompts-gpt.com project library.
|
|
1956
|
+
When --goal is used, the text you pass is sent to prompts-gpt.com for AI generation.
|
|
1957
|
+
No local files or repo content are uploaded — only explicit flag values are transmitted.
|
|
1958
|
+
Do not include PII, secrets, or confidential data in --goal, --context, or --constraints.
|
|
1959
|
+
Use --dry-run to preview what would be synced without sending or writing anything.
|
|
1960
|
+
|
|
1470
1961
|
Options:
|
|
1471
1962
|
--goal <text> Generate one prompt pack before syncing.
|
|
1472
1963
|
--generated-only Skip library pull and sync only the generated prompt pack from --goal.
|
|
@@ -1492,19 +1983,26 @@ Options:
|
|
|
1492
1983
|
--api-url <url> Override the saved API base URL for this command only.
|
|
1493
1984
|
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
1494
1985
|
--help Show this command help.
|
|
1986
|
+
|
|
1987
|
+
Examples:
|
|
1988
|
+
prompts-gpt sync # pull all prompts + sync agent files
|
|
1989
|
+
prompts-gpt sync --goal "Add error handling" # generate + pull + sync
|
|
1990
|
+
prompts-gpt sync --dry-run # preview without writing
|
|
1991
|
+
prompts-gpt sync --agent cursor,codex # sync only specific agents
|
|
1495
1992
|
`;
|
|
1496
1993
|
}
|
|
1497
1994
|
if (command === "run") {
|
|
1498
1995
|
return `prompts-gpt run
|
|
1499
1996
|
|
|
1500
1997
|
Usage:
|
|
1501
|
-
prompts-gpt run [
|
|
1998
|
+
prompts-gpt run [-f <path>] [--agent <name>] [--model <name>] [--timeout <seconds>] [--dry-run]
|
|
1502
1999
|
|
|
1503
2000
|
Why use it:
|
|
1504
|
-
Executes one local prompt file with the built-in provider adapter runtime and writes run artifacts.
|
|
2001
|
+
Executes one local prompt file with the built-in provider adapter runtime and writes run artifacts.
|
|
2002
|
+
If \`--prompt-file\` is omitted and only one prompt exists locally, it is auto-selected.
|
|
1505
2003
|
|
|
1506
2004
|
Options:
|
|
1507
|
-
--prompt-file <path>
|
|
2005
|
+
-f, --prompt-file <path> Optional explicit prompt Markdown or text file.
|
|
1508
2006
|
--agent <name> Orchestration profile. Default from ${DEFAULT_RUN_CONFIG_PATH} or router.
|
|
1509
2007
|
--model <name> Optional model override for the selected provider.
|
|
1510
2008
|
--timeout <seconds> Execution timeout in seconds.
|
|
@@ -1514,6 +2012,8 @@ Options:
|
|
|
1514
2012
|
--no-approve-mcps Disable Cursor MCP auto-approval flag.
|
|
1515
2013
|
--background Run as a background agent (Cursor cloud agent mode).
|
|
1516
2014
|
--permission-mode <mode> Claude Code permission mode. Default: acceptEdits.
|
|
2015
|
+
--dry-run Preview the execution parameters without actually running.
|
|
2016
|
+
--non-interactive Skip all interactive prompts (same as CI mode).
|
|
1517
2017
|
--json Print machine-readable JSON output.
|
|
1518
2018
|
--cwd <path> Project directory.
|
|
1519
2019
|
--help Show this command help.
|
|
@@ -1523,7 +2023,7 @@ Options:
|
|
|
1523
2023
|
return `prompts-gpt run-batch
|
|
1524
2024
|
|
|
1525
2025
|
Usage:
|
|
1526
|
-
prompts-gpt run-batch [--manifest <path> | --prompt-files <a,b,c>] [--agent
|
|
2026
|
+
prompts-gpt run-batch [--manifest <path> | --prompt-files <a,b,c>] [--agent <name>] [--model <name>] [--timeout <seconds>]
|
|
1527
2027
|
|
|
1528
2028
|
Why use it:
|
|
1529
2029
|
Executes multiple prompt files in sequence using the configured prompt source, a manifest, or an explicit file list.
|
|
@@ -1538,25 +2038,31 @@ Options:
|
|
|
1538
2038
|
--json Print machine-readable JSON output.
|
|
1539
2039
|
--cwd <path> Project directory.
|
|
1540
2040
|
--help Show this command help.
|
|
2041
|
+
|
|
2042
|
+
Examples:
|
|
2043
|
+
prompts-gpt run-batch --manifest .prompts-gpt/manifest.json
|
|
2044
|
+
prompts-gpt run-batch --prompt-files .prompts-gpt/review.md,.prompts-gpt/tests.md
|
|
1541
2045
|
`;
|
|
1542
2046
|
}
|
|
1543
2047
|
if (command === "sweep") {
|
|
1544
2048
|
return `prompts-gpt sweep
|
|
1545
2049
|
|
|
1546
2050
|
Usage:
|
|
1547
|
-
prompts-gpt sweep [
|
|
2051
|
+
prompts-gpt sweep [-f <path>] [-n <count>] [--agent <name>] [--model <name>] [--dry-run]
|
|
1548
2052
|
|
|
1549
2053
|
Why use it:
|
|
1550
|
-
Replaces the bash sweep scripts with a generic multi-iteration execution engine.
|
|
1551
2054
|
Runs the same prompt N times, feeding each iteration's summary into the next.
|
|
1552
|
-
Includes pre-flight checks, safety guards, SIGTERM handling, progress monitoring
|
|
1553
|
-
|
|
2055
|
+
Includes pre-flight checks, safety guards, SIGTERM handling, and progress monitoring.
|
|
2056
|
+
|
|
2057
|
+
When --prompt-file is omitted and only one .prompts-gpt/sweeps/*.md file exists,
|
|
2058
|
+
it is auto-selected. The iteration count defaults to the \`iterations:\` value
|
|
2059
|
+
in the sweep file's YAML frontmatter (or 1 if not specified).
|
|
1554
2060
|
|
|
1555
2061
|
Options:
|
|
1556
|
-
--prompt-file <path>
|
|
2062
|
+
-f, --prompt-file <path> Prompt file to sweep. Auto-detects local sweeps if omitted.
|
|
2063
|
+
-n, --iterations <n> Number of iterations. Default: from frontmatter or 1.
|
|
1557
2064
|
--agent <name> Orchestration profile. Default from config or router.
|
|
1558
2065
|
--model <name> Model override for the selected provider.
|
|
1559
|
-
--iterations <n> Number of sweep iterations. Default: 1
|
|
1560
2066
|
--iteration-timeout <secs> Timeout per iteration in seconds. Default: 5400 (90 min)
|
|
1561
2067
|
--max-retries <n> Max retries per iteration on spawn/timeout. Default: 2
|
|
1562
2068
|
--phase <name> Optional phase label injected into the prompt.
|
|
@@ -1569,9 +2075,21 @@ Options:
|
|
|
1569
2075
|
--max-run-dirs <n> Max artifact directories to keep. Default: 20
|
|
1570
2076
|
--summary-lines <n> Lines of summary to extract per iteration. Default: 40
|
|
1571
2077
|
--dry-run Preview what the sweep would do without executing.
|
|
2078
|
+
--non-interactive Skip all interactive prompts (same as CI mode).
|
|
1572
2079
|
--json Print machine-readable JSON output.
|
|
1573
2080
|
--cwd <path> Project directory.
|
|
1574
2081
|
--help Show this command help.
|
|
2082
|
+
|
|
2083
|
+
Environment:
|
|
2084
|
+
PROMPTS_GPT_NON_INTERACTIVE=1 Skip interactive prompts.
|
|
2085
|
+
NO_COLOR=1 Disable colored output.
|
|
2086
|
+
|
|
2087
|
+
Examples:
|
|
2088
|
+
prompts-gpt sweep # interactive picker
|
|
2089
|
+
prompts-gpt sweep -f .prompts-gpt/sweeps/sdk-hardening.md # explicit file
|
|
2090
|
+
prompts-gpt sweep -f .prompts-gpt/sweeps/design.md -n 5 # 5 iterations
|
|
2091
|
+
prompts-gpt sweep --dry-run # preview without running
|
|
2092
|
+
prompts-gpt sweep --non-interactive # skip interactive prompts
|
|
1575
2093
|
`;
|
|
1576
2094
|
}
|
|
1577
2095
|
if (command === "list") {
|
|
@@ -1653,6 +2171,10 @@ Why use it:
|
|
|
1653
2171
|
into your local workspace. Replaces the multi-step init + sync + setup flow
|
|
1654
2172
|
for users who manage their prompt library in the Prompts Studio web app.
|
|
1655
2173
|
|
|
2174
|
+
Data privacy:
|
|
2175
|
+
Downloads prompts and project config from your prompts-gpt.com project.
|
|
2176
|
+
No local files or repo content are uploaded.
|
|
2177
|
+
|
|
1656
2178
|
Options:
|
|
1657
2179
|
--agent <targets> Comma-separated agent targets. Default: all
|
|
1658
2180
|
--out <dir> Output directory. Default: .prompts-gpt
|
|
@@ -1663,6 +2185,22 @@ Options:
|
|
|
1663
2185
|
--api-url <url> Override API URL.
|
|
1664
2186
|
--cwd <path> Project directory.
|
|
1665
2187
|
--help Show this command help.
|
|
2188
|
+
`;
|
|
2189
|
+
}
|
|
2190
|
+
if (command === "quickstart") {
|
|
2191
|
+
return `prompts-gpt quickstart
|
|
2192
|
+
|
|
2193
|
+
Usage:
|
|
2194
|
+
prompts-gpt quickstart [--json] [--cwd <path>]
|
|
2195
|
+
|
|
2196
|
+
Why use it:
|
|
2197
|
+
Walks through setup in one command — checks credentials, creates config, detects providers,
|
|
2198
|
+
and shows runnable commands. The fastest path from install to first run.
|
|
2199
|
+
|
|
2200
|
+
Options:
|
|
2201
|
+
--json Print machine-readable JSON output.
|
|
2202
|
+
--cwd <path> Project directory.
|
|
2203
|
+
--help Show this command help.
|
|
1666
2204
|
`;
|
|
1667
2205
|
}
|
|
1668
2206
|
if (command === "version") {
|
|
@@ -1684,6 +2222,233 @@ Why use it:
|
|
|
1684
2222
|
Shows focused usage for the exact command you are trying to run so shell users do not have to scan the full command list.
|
|
1685
2223
|
`;
|
|
1686
2224
|
}
|
|
2225
|
+
// ── Interactive TTY selection helpers ─────────────────────────────────────────
|
|
2226
|
+
function supportsColor() {
|
|
2227
|
+
if (process.env.NO_COLOR || process.env.TERM === "dumb")
|
|
2228
|
+
return false;
|
|
2229
|
+
if (process.env.FORCE_COLOR)
|
|
2230
|
+
return true;
|
|
2231
|
+
if (process.platform === "win32") {
|
|
2232
|
+
const osRelease = (process.env.OS_VERSION || "").toLowerCase();
|
|
2233
|
+
if (osRelease.includes("windows_nt") || process.env.WT_SESSION || process.env.TERM_PROGRAM)
|
|
2234
|
+
return true;
|
|
2235
|
+
return Boolean(process.stdout.isTTY && (process.stdout.hasColors?.() ?? false));
|
|
2236
|
+
}
|
|
2237
|
+
return Boolean(process.stdout.isTTY);
|
|
2238
|
+
}
|
|
2239
|
+
function colorize(text, code) {
|
|
2240
|
+
return supportsColor() ? `${code}${text}\x1b[0m` : text;
|
|
2241
|
+
}
|
|
2242
|
+
function isTTYInteractive(flags) {
|
|
2243
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
2244
|
+
return false;
|
|
2245
|
+
if (flags && Boolean(flags["non-interactive"]))
|
|
2246
|
+
return false;
|
|
2247
|
+
if (process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.GITHUB_ACTIONS ||
|
|
2248
|
+
process.env.GITLAB_CI || process.env.CIRCLECI || process.env.JENKINS_URL ||
|
|
2249
|
+
process.env.BUILDKITE || process.env.TRAVIS || process.env.TF_BUILD ||
|
|
2250
|
+
process.env.CODEBUILD_BUILD_ID)
|
|
2251
|
+
return false;
|
|
2252
|
+
if (process.env.PROMPTS_GPT_NON_INTERACTIVE === "1" || process.env.PROMPTS_GPT_NON_INTERACTIVE === "true")
|
|
2253
|
+
return false;
|
|
2254
|
+
return true;
|
|
2255
|
+
}
|
|
2256
|
+
function interactiveSelect(prompt, options) {
|
|
2257
|
+
if (options.length === 0) {
|
|
2258
|
+
return Promise.reject(new CliError("No options available for selection.", CLI_EXIT_CODES.usage));
|
|
2259
|
+
}
|
|
2260
|
+
if (options.length === 1) {
|
|
2261
|
+
return Promise.resolve(options[0].value);
|
|
2262
|
+
}
|
|
2263
|
+
return new Promise((resolve, reject) => {
|
|
2264
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
2265
|
+
reject(new CliError("Interactive selection requires a TTY.", CLI_EXIT_CODES.usage));
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
const stdin = process.stdin;
|
|
2269
|
+
const stdout = process.stdout;
|
|
2270
|
+
let cursor = 0;
|
|
2271
|
+
let escBuf = "";
|
|
2272
|
+
const maxVisible = Math.min(options.length, (process.stdout.rows ?? 24) - 3);
|
|
2273
|
+
const formatLine = (i, selected) => {
|
|
2274
|
+
const num = i < 9 ? `${i + 1}` : " ";
|
|
2275
|
+
const prefix = selected ? colorize("❯", "\x1b[36m") : " ";
|
|
2276
|
+
const label = selected ? colorize(options[i].label, "\x1b[1m") : options[i].label;
|
|
2277
|
+
return ` ${prefix} ${num}. ${label}`;
|
|
2278
|
+
};
|
|
2279
|
+
const writeInitial = () => {
|
|
2280
|
+
stdout.write(`${prompt}\n`);
|
|
2281
|
+
for (let i = 0; i < maxVisible; i++) {
|
|
2282
|
+
stdout.write(`${formatLine(i, i === cursor)}\n`);
|
|
2283
|
+
}
|
|
2284
|
+
if (options.length > maxVisible) {
|
|
2285
|
+
stdout.write(` ... ${options.length - maxVisible} more (scroll with arrows)\n`);
|
|
2286
|
+
}
|
|
2287
|
+
};
|
|
2288
|
+
const render = () => {
|
|
2289
|
+
const lines = maxVisible + 1 + (options.length > maxVisible ? 1 : 0);
|
|
2290
|
+
if (supportsColor()) {
|
|
2291
|
+
stdout.write(`\x1b[${lines}A\x1b[J`);
|
|
2292
|
+
}
|
|
2293
|
+
else {
|
|
2294
|
+
stdout.write("\n".repeat(2));
|
|
2295
|
+
}
|
|
2296
|
+
stdout.write(`${prompt}\n`);
|
|
2297
|
+
const scrollStart = Math.max(0, Math.min(cursor - Math.floor(maxVisible / 2), options.length - maxVisible));
|
|
2298
|
+
for (let vi = 0; vi < maxVisible; vi++) {
|
|
2299
|
+
const i = scrollStart + vi;
|
|
2300
|
+
stdout.write(`${formatLine(i, i === cursor)}\n`);
|
|
2301
|
+
}
|
|
2302
|
+
if (options.length > maxVisible) {
|
|
2303
|
+
stdout.write(` ... showing ${scrollStart + 1}-${scrollStart + maxVisible} of ${options.length}\n`);
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
writeInitial();
|
|
2307
|
+
stdin.setEncoding("utf8");
|
|
2308
|
+
try {
|
|
2309
|
+
if (typeof stdin.setRawMode === "function")
|
|
2310
|
+
stdin.setRawMode(true);
|
|
2311
|
+
}
|
|
2312
|
+
catch {
|
|
2313
|
+
reject(new CliError("Cannot enable raw mode for interactive selection. Use --non-interactive or pass flags directly.", CLI_EXIT_CODES.usage));
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
stdin.resume();
|
|
2317
|
+
const cleanup = () => {
|
|
2318
|
+
stdin.removeListener("data", onData);
|
|
2319
|
+
try {
|
|
2320
|
+
if (typeof stdin.setRawMode === "function")
|
|
2321
|
+
stdin.setRawMode(false);
|
|
2322
|
+
}
|
|
2323
|
+
catch { /* ignore */ }
|
|
2324
|
+
stdin.pause();
|
|
2325
|
+
};
|
|
2326
|
+
const onData = (data) => {
|
|
2327
|
+
for (let ci = 0; ci < data.length; ci++) {
|
|
2328
|
+
const ch = data[ci];
|
|
2329
|
+
if (escBuf.length > 0) {
|
|
2330
|
+
escBuf += ch;
|
|
2331
|
+
if (escBuf.length === 2 && ch === "[")
|
|
2332
|
+
continue;
|
|
2333
|
+
if (escBuf.length >= 3) {
|
|
2334
|
+
if (escBuf === "\x1b[A" || escBuf === "\x1b[k") {
|
|
2335
|
+
cursor = cursor > 0 ? cursor - 1 : options.length - 1;
|
|
2336
|
+
render();
|
|
2337
|
+
}
|
|
2338
|
+
else if (escBuf === "\x1b[B" || escBuf === "\x1b[j") {
|
|
2339
|
+
cursor = cursor < options.length - 1 ? cursor + 1 : 0;
|
|
2340
|
+
render();
|
|
2341
|
+
}
|
|
2342
|
+
else if (escBuf === "\x1b[H") {
|
|
2343
|
+
cursor = 0;
|
|
2344
|
+
render();
|
|
2345
|
+
}
|
|
2346
|
+
else if (escBuf === "\x1b[F") {
|
|
2347
|
+
cursor = options.length - 1;
|
|
2348
|
+
render();
|
|
2349
|
+
}
|
|
2350
|
+
escBuf = "";
|
|
2351
|
+
}
|
|
2352
|
+
continue;
|
|
2353
|
+
}
|
|
2354
|
+
if (ch === "\x1b") {
|
|
2355
|
+
escBuf = "\x1b";
|
|
2356
|
+
continue;
|
|
2357
|
+
}
|
|
2358
|
+
if (ch === "\x03") {
|
|
2359
|
+
cleanup();
|
|
2360
|
+
stdout.write("\n");
|
|
2361
|
+
process.exit(130);
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
if (ch === "\r" || ch === "\n") {
|
|
2365
|
+
cleanup();
|
|
2366
|
+
stdout.write("\n");
|
|
2367
|
+
resolve(options[cursor].value);
|
|
2368
|
+
return;
|
|
2369
|
+
}
|
|
2370
|
+
if (ch === "k") {
|
|
2371
|
+
cursor = cursor > 0 ? cursor - 1 : options.length - 1;
|
|
2372
|
+
render();
|
|
2373
|
+
}
|
|
2374
|
+
else if (ch === "j") {
|
|
2375
|
+
cursor = cursor < options.length - 1 ? cursor + 1 : 0;
|
|
2376
|
+
render();
|
|
2377
|
+
}
|
|
2378
|
+
else if (ch >= "1" && ch <= "9") {
|
|
2379
|
+
const idx = parseInt(ch, 10) - 1;
|
|
2380
|
+
if (idx < options.length) {
|
|
2381
|
+
cleanup();
|
|
2382
|
+
stdout.write("\n");
|
|
2383
|
+
resolve(options[idx].value);
|
|
2384
|
+
return;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
stdin.on("data", onData);
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
function interactiveInput(prompt, defaultValue) {
|
|
2393
|
+
return new Promise(async (resolve, reject) => {
|
|
2394
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
2395
|
+
reject(new CliError("Interactive input requires a TTY.", CLI_EXIT_CODES.usage));
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
const { createInterface } = await import("node:readline");
|
|
2399
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2400
|
+
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
2401
|
+
rl.question(`${prompt}${suffix}: `, (answer) => {
|
|
2402
|
+
rl.close();
|
|
2403
|
+
resolve(answer.trim() || defaultValue || "");
|
|
2404
|
+
});
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2407
|
+
async function readSweepFrontmatter(filePath) {
|
|
2408
|
+
try {
|
|
2409
|
+
const { readFile: fsRead } = await import("node:fs/promises");
|
|
2410
|
+
const content = await fsRead(filePath, "utf8");
|
|
2411
|
+
let iterations = null;
|
|
2412
|
+
let title = null;
|
|
2413
|
+
const iterMatch = content.match(/iterations:\s*(\d+)/i);
|
|
2414
|
+
if (iterMatch) {
|
|
2415
|
+
const val = parseInt(iterMatch[1], 10);
|
|
2416
|
+
if (val > 0 && val <= 50)
|
|
2417
|
+
iterations = val;
|
|
2418
|
+
}
|
|
2419
|
+
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
2420
|
+
if (titleMatch) {
|
|
2421
|
+
title = titleMatch[1].trim();
|
|
2422
|
+
}
|
|
2423
|
+
return { iterations, title };
|
|
2424
|
+
}
|
|
2425
|
+
catch { /* skip */ }
|
|
2426
|
+
return { iterations: null, title: null };
|
|
2427
|
+
}
|
|
2428
|
+
async function readSweepIterationsFromFrontmatter(filePath) {
|
|
2429
|
+
return (await readSweepFrontmatter(filePath)).iterations;
|
|
2430
|
+
}
|
|
2431
|
+
function buildGenerateInput(flags) {
|
|
2432
|
+
return {
|
|
2433
|
+
goal: getStringFlag(flags, "goal") || "",
|
|
2434
|
+
context: sanitizeGenerateInput(getStringFlag(flags, "context") || ""),
|
|
2435
|
+
constraints: sanitizeGenerateInput(getStringFlag(flags, "constraints") || ""),
|
|
2436
|
+
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
2437
|
+
tool: getStringFlag(flags, "tool") || "Codex",
|
|
2438
|
+
mode: getStringFlag(flags, "mode") || "implement",
|
|
2439
|
+
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
2440
|
+
includeWebSearch: Boolean(flags["web-search"]),
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2443
|
+
function sanitizeGenerateInput(value) {
|
|
2444
|
+
return value.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***").replace(/sk-[a-zA-Z0-9]{20,}/g, "sk-***").replace(/ghp_[a-zA-Z0-9]{36,}/g, "ghp_***");
|
|
2445
|
+
}
|
|
2446
|
+
function printDataTransmissionNotice(command, input) {
|
|
2447
|
+
console.log(`[notice] The --goal text${input.context ? ", --context" : ""}${input.constraints ? ", --constraints" : ""} you provided will be sent to prompts-gpt.com to generate a prompt.`);
|
|
2448
|
+
console.log("[notice] Do not include PII, secrets, or confidential data in these flags.");
|
|
2449
|
+
console.log(`[notice] No local files or repo content are uploaded. Only the explicit flag values for \`${command}\` are transmitted.`);
|
|
2450
|
+
console.log("");
|
|
2451
|
+
}
|
|
1687
2452
|
main().catch((error) => {
|
|
1688
2453
|
if (error instanceof CliError) {
|
|
1689
2454
|
console.error(error.message);
|
|
@@ -1708,6 +2473,46 @@ main().catch((error) => {
|
|
|
1708
2473
|
console.error(msg.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
|
|
1709
2474
|
process.exitCode = CLI_EXIT_CODES.general;
|
|
1710
2475
|
});
|
|
2476
|
+
async function extractRunDiagnostics(logFile, provider, model) {
|
|
2477
|
+
const diagnostics = [];
|
|
2478
|
+
try {
|
|
2479
|
+
const { readFile: fsReadFile } = await import("node:fs/promises");
|
|
2480
|
+
const log = await fsReadFile(logFile, "utf8");
|
|
2481
|
+
const errorLines = log.split("\n").filter((line) => line.startsWith("ERROR:") || line.includes('"error"'));
|
|
2482
|
+
for (const line of errorLines.slice(0, 5)) {
|
|
2483
|
+
if (line.includes("not supported")) {
|
|
2484
|
+
const modelMatch = line.match(/The '([^']+)' model is not supported/);
|
|
2485
|
+
const badModel = modelMatch?.[1] ?? model;
|
|
2486
|
+
diagnostics.push(`Model "${badModel}" is not supported by ${provider} with your account.`);
|
|
2487
|
+
diagnostics.push(`Fix: prompts-gpt run --model o4-mini`);
|
|
2488
|
+
diagnostics.push(`Or: prompts-gpt run --agent claude`);
|
|
2489
|
+
break;
|
|
2490
|
+
}
|
|
2491
|
+
if (line.includes("unauthorized") || line.includes("authentication")) {
|
|
2492
|
+
diagnostics.push(`Authentication failed for ${provider}. Check your ${provider} account login.`);
|
|
2493
|
+
diagnostics.push(`Fix: Run the ${provider} CLI directly to verify auth: ${provider} --version`);
|
|
2494
|
+
break;
|
|
2495
|
+
}
|
|
2496
|
+
if (line.includes("rate_limit") || line.includes("429")) {
|
|
2497
|
+
diagnostics.push(`Rate limited by ${provider}. Wait and try again.`);
|
|
2498
|
+
break;
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
if (diagnostics.length === 0 && errorLines.length > 0) {
|
|
2502
|
+
const firstError = errorLines[0].slice(0, 200);
|
|
2503
|
+
diagnostics.push(`Provider error: ${firstError}`);
|
|
2504
|
+
}
|
|
2505
|
+
if (diagnostics.length === 0) {
|
|
2506
|
+
diagnostics.push(`${provider} exited with code 1. Check the log for details:`);
|
|
2507
|
+
diagnostics.push(` cat ${logFile}`);
|
|
2508
|
+
diagnostics.push(`Try a different provider: prompts-gpt run --agent claude`);
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
catch {
|
|
2512
|
+
diagnostics.push(`Could not read log file. Check: ${logFile}`);
|
|
2513
|
+
}
|
|
2514
|
+
return diagnostics;
|
|
2515
|
+
}
|
|
1711
2516
|
function warnOnConfigIssues(config) {
|
|
1712
2517
|
for (const w of config.configWarnings) {
|
|
1713
2518
|
console.error(`[config warning] ${w}`);
|
|
@@ -1728,4 +2533,21 @@ function formatApiError(error) {
|
|
|
1728
2533
|
}
|
|
1729
2534
|
return lines.join("\n");
|
|
1730
2535
|
}
|
|
2536
|
+
function formatTokenUsage(usage) {
|
|
2537
|
+
const parts = [
|
|
2538
|
+
`total=${usage.totalTokens.toLocaleString()}`,
|
|
2539
|
+
`input=${usage.inputTokens.toLocaleString()}`,
|
|
2540
|
+
`output=${usage.outputTokens.toLocaleString()}`,
|
|
2541
|
+
];
|
|
2542
|
+
if (usage.reasoningTokens > 0) {
|
|
2543
|
+
parts.push(`reasoning=${usage.reasoningTokens.toLocaleString()}`);
|
|
2544
|
+
}
|
|
2545
|
+
if (usage.cacheReadTokens > 0) {
|
|
2546
|
+
parts.push(`cache-read=${usage.cacheReadTokens.toLocaleString()}`);
|
|
2547
|
+
}
|
|
2548
|
+
if (usage.cacheWriteTokens > 0) {
|
|
2549
|
+
parts.push(`cache-write=${usage.cacheWriteTokens.toLocaleString()}`);
|
|
2550
|
+
}
|
|
2551
|
+
return parts.join(" | ");
|
|
2552
|
+
}
|
|
1731
2553
|
//# sourceMappingURL=cli.js.map
|