@prompts-gpt/client 0.2.2 → 0.2.4
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/LICENSE +75 -21
- package/README.md +106 -279
- package/dist/cli.js +1513 -144
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +276 -47
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +223 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1444 -0
- package/dist/runtime.js.map +1 -0
- package/dist/sweep.d.ts +180 -0
- package/dist/sweep.d.ts.map +1 -0
- package/dist/sweep.js +606 -0
- package/dist/sweep.js.map +1 -0
- 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, PROMPTS_GPT_CREDENTIALS_FILE, PromptsGptApiError, PromptsGptClient, SUPPORTED_AGENT_TARGETS, loadLocalCredentials, saveLocalCredentials, syncPrompts, writeAgentFiles, 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 = ["init", "project", "pull", "generate", "sync", "
|
|
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,11 +27,18 @@ class CliError extends Error {
|
|
|
27
27
|
async function main() {
|
|
28
28
|
const argv = process.argv.slice(2);
|
|
29
29
|
if (argv.length === 0) {
|
|
30
|
-
|
|
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
|
+
`);
|
|
31
39
|
return;
|
|
32
40
|
}
|
|
33
|
-
const
|
|
34
|
-
const first = normalizedArgv[0];
|
|
41
|
+
const first = argv[0];
|
|
35
42
|
if (first === "--help") {
|
|
36
43
|
printHelp();
|
|
37
44
|
return;
|
|
@@ -41,11 +48,11 @@ async function main() {
|
|
|
41
48
|
return;
|
|
42
49
|
}
|
|
43
50
|
if (first === "help") {
|
|
44
|
-
handleHelpCommand(
|
|
51
|
+
handleHelpCommand(argv.slice(1));
|
|
45
52
|
return;
|
|
46
53
|
}
|
|
47
54
|
if (first === "version") {
|
|
48
|
-
if (
|
|
55
|
+
if (argv.length > 1) {
|
|
49
56
|
throw new CliError("The `version` command does not accept additional arguments.", CLI_EXIT_CODES.usage, {
|
|
50
57
|
helpCommand: "version",
|
|
51
58
|
});
|
|
@@ -62,7 +69,7 @@ async function main() {
|
|
|
62
69
|
helpCommand: "help",
|
|
63
70
|
});
|
|
64
71
|
}
|
|
65
|
-
const flags = parseCommandFlags(command,
|
|
72
|
+
const flags = parseCommandFlags(command, argv.slice(1));
|
|
66
73
|
if (Boolean(flags.help)) {
|
|
67
74
|
printHelp(command);
|
|
68
75
|
return;
|
|
@@ -70,8 +77,714 @@ async function main() {
|
|
|
70
77
|
await runCommand(command, flags);
|
|
71
78
|
}
|
|
72
79
|
async function runCommand(command, flags) {
|
|
80
|
+
if (command === "providers") {
|
|
81
|
+
const cwd = getResolvedCwd(flags);
|
|
82
|
+
const providers = await detectProviders(cwd);
|
|
83
|
+
if (Boolean(flags.json)) {
|
|
84
|
+
console.log(JSON.stringify({ cwd, providers }, null, 2));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(`Workspace: ${cwd}`);
|
|
88
|
+
for (const provider of providers) {
|
|
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
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (command === "setup") {
|
|
98
|
+
const cwd = getResolvedCwd(flags);
|
|
99
|
+
const providerOrder = getStringFlag(flags, "provider-order")
|
|
100
|
+
?.split(",")
|
|
101
|
+
.map((item) => item.trim())
|
|
102
|
+
.filter(Boolean);
|
|
103
|
+
validateProviderOrderFlag(providerOrder);
|
|
104
|
+
const promptFile = getStringFlag(flags, "prompt-file");
|
|
105
|
+
const promptFiles = getStringFlag(flags, "prompt-files")
|
|
106
|
+
?.split(",")
|
|
107
|
+
.map((item) => item.trim())
|
|
108
|
+
.filter(Boolean);
|
|
109
|
+
const result = await initRunConfig({
|
|
110
|
+
cwd,
|
|
111
|
+
promptFile,
|
|
112
|
+
manifestPath: getStringFlag(flags, "manifest"),
|
|
113
|
+
promptFiles,
|
|
114
|
+
promptDir: getStringFlag(flags, "prompt-dir"),
|
|
115
|
+
defaultAgent: resolveRunAgent(flags, "router"),
|
|
116
|
+
providerOrder,
|
|
117
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
118
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
119
|
+
retryCount: parseNonNegativeIntFlag(getStringFlag(flags, "retry-count"), "retry-count"),
|
|
120
|
+
disallowDestructiveGit: Boolean(flags["allow-destructive-git"]) ? false : true,
|
|
121
|
+
modelOverrides: {
|
|
122
|
+
codex: getStringFlag(flags, "codex-model"),
|
|
123
|
+
cursor: getStringFlag(flags, "cursor-model"),
|
|
124
|
+
claude: getStringFlag(flags, "claude-model"),
|
|
125
|
+
copilot: getStringFlag(flags, "copilot-model"),
|
|
126
|
+
},
|
|
127
|
+
overwrite: Boolean(flags.overwrite),
|
|
128
|
+
});
|
|
129
|
+
if (Boolean(flags.json)) {
|
|
130
|
+
console.log(JSON.stringify(result, null, 2));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
console.log(`Created run config: ${result.configPath}`);
|
|
134
|
+
console.log(`Config: ${result.configPath}`);
|
|
135
|
+
console.log(`Agent: ${result.config.defaultAgent ?? "router"} | Providers: ${(result.config.providerOrder ?? []).join(", ")}`);
|
|
136
|
+
if (result.sourceSummary.defaultPromptFile) {
|
|
137
|
+
console.log(`Default prompt file: ${result.sourceSummary.defaultPromptFile}`);
|
|
138
|
+
console.log(`Default prompt: ${result.sourceSummary.defaultPromptFile}`);
|
|
139
|
+
}
|
|
140
|
+
const availableCount = result.providerSummary.filter((p) => p.available).length;
|
|
141
|
+
console.log(`Providers: ${availableCount}/${result.providerSummary.length} available`);
|
|
142
|
+
if (availableCount === 0) {
|
|
143
|
+
console.log("⚠ No provider CLIs detected. Install codex, cursor agent, claude, or copilot.");
|
|
144
|
+
}
|
|
145
|
+
const setupAssets = await discoverWorkspaceAssets(cwd);
|
|
146
|
+
console.log("Next steps:");
|
|
147
|
+
console.log(` prompts-gpt run${result.sourceSummary.defaultPromptFile ? "" : " --prompt-file <path>"}`);
|
|
148
|
+
if (setupAssets.sweeps.length > 0) {
|
|
149
|
+
console.log(` prompts-gpt sweep — run a multi-iteration sweep (${setupAssets.sweeps.length} found)`);
|
|
150
|
+
}
|
|
151
|
+
console.log(" prompts-gpt list — see all runnable assets");
|
|
152
|
+
console.log(" prompts-gpt status — check workspace readiness");
|
|
153
|
+
console.log(" prompts-gpt validate — validate your config");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (command === "doctor") {
|
|
157
|
+
const cwd = getResolvedCwd(flags);
|
|
158
|
+
const report = await doctor(cwd);
|
|
159
|
+
if (Boolean(flags.json)) {
|
|
160
|
+
console.log(JSON.stringify(report, null, 2));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
console.log(`Workspace: ${report.cwd}`);
|
|
164
|
+
console.log(`Node: ${report.nodeVersion} | OS: ${report.osPlatform}/${report.osArch} | CPUs: ${report.cpuCount}`);
|
|
165
|
+
console.log(`Config: ${report.configFound ? "found" : "not found"} (${report.configPath})`);
|
|
166
|
+
for (const provider of report.providers) {
|
|
167
|
+
console.log(`${provider.provider}: ${provider.available ? "available" : "missing"} | bin=${provider.bin}${provider.version ? ` | version=${provider.version}` : ""}`);
|
|
168
|
+
if (!provider.available) {
|
|
169
|
+
console.log(` hint: ${provider.installHint}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (const note of report.notes) {
|
|
173
|
+
console.log(`note: ${note}`);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (command === "list") {
|
|
178
|
+
const cwd = getResolvedCwd(flags);
|
|
179
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
180
|
+
if (Boolean(flags.json)) {
|
|
181
|
+
console.log(JSON.stringify(assets, null, 2));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
console.log(`Workspace: ${cwd}`);
|
|
185
|
+
console.log("");
|
|
186
|
+
const providers = await detectProviders(cwd);
|
|
187
|
+
const availableProviderNames = providers.filter((p) => p.available).map((p) => p.provider);
|
|
188
|
+
if (assets.prompts.length > 0) {
|
|
189
|
+
console.log(`Prompt packs (${assets.prompts.length}):`);
|
|
190
|
+
for (const p of assets.prompts) {
|
|
191
|
+
const providerHint = availableProviderNames.length > 0
|
|
192
|
+
? ` (run with: ${availableProviderNames[0]})`
|
|
193
|
+
: "";
|
|
194
|
+
console.log(` ${p.slug} — ${p.title} [${p.source}]${providerHint}`);
|
|
195
|
+
console.log(` file: .prompts-gpt/${p.file}`);
|
|
196
|
+
console.log(` run: prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
197
|
+
}
|
|
198
|
+
console.log("");
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.log("Prompt packs: none found");
|
|
202
|
+
console.log(" Run `prompts-gpt sync` to pull prompt packs, or `prompts-gpt pull` to download them.");
|
|
203
|
+
console.log("");
|
|
204
|
+
}
|
|
205
|
+
if (assets.sweeps.length > 0) {
|
|
206
|
+
console.log(`Sweep prompts (${assets.sweeps.length}):`);
|
|
207
|
+
for (const s of assets.sweeps) {
|
|
208
|
+
const iterCount = await readSweepIterationsFromFrontmatter(path.resolve(cwd, s.file));
|
|
209
|
+
const iterHint = iterCount ? ` (${iterCount} iterations)` : "";
|
|
210
|
+
const iterFlag = iterCount ? ` --iterations ${iterCount}` : "";
|
|
211
|
+
console.log(` ${s.name}${iterHint}`);
|
|
212
|
+
console.log(` file: ${s.file}`);
|
|
213
|
+
console.log(` sweep: prompts-gpt sweep --prompt-file ${s.file}${iterFlag}`);
|
|
214
|
+
}
|
|
215
|
+
console.log("");
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.log("Sweep prompts: none found");
|
|
219
|
+
console.log(" Create .prompts-gpt/sweeps/<name>.md to add sweep prompts.");
|
|
220
|
+
console.log("");
|
|
221
|
+
}
|
|
222
|
+
if (assets.agents.length > 0) {
|
|
223
|
+
console.log(`Agent integrations (${assets.agents.length}):`);
|
|
224
|
+
for (const a of assets.agents) {
|
|
225
|
+
console.log(` ${a.target} — ${a.file}`);
|
|
226
|
+
}
|
|
227
|
+
console.log("");
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
console.log("Agent integrations: none synced");
|
|
231
|
+
console.log(" Run `prompts-gpt sync` to generate agent files.");
|
|
232
|
+
console.log("");
|
|
233
|
+
}
|
|
234
|
+
console.log(`Config: ${assets.configFound ? "found" : "not found — run `prompts-gpt setup`"}`);
|
|
235
|
+
console.log(`Manifest: ${assets.manifestFound ? "found" : "not found — run `prompts-gpt sync`"}`);
|
|
236
|
+
console.log(`Credentials: ${assets.credentialsFound ? "found" : "not found — run `prompts-gpt init --token <token>`"}`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (command === "status") {
|
|
240
|
+
const cwd = getResolvedCwd(flags);
|
|
241
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
242
|
+
const providers = await detectProviders(cwd);
|
|
243
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
244
|
+
if (Boolean(flags.json)) {
|
|
245
|
+
console.log(JSON.stringify({ cwd, assets, providers }, null, 2));
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
console.log(`Workspace: ${cwd}`);
|
|
249
|
+
console.log("");
|
|
250
|
+
console.log("Readiness:");
|
|
251
|
+
console.log(` Credentials: ${assets.credentialsFound ? "✓" : "✗ — run \`prompts-gpt init --token <token>\`"}`);
|
|
252
|
+
console.log(` Config: ${assets.configFound ? "✓" : "✗ — run \`prompts-gpt setup\`"}`);
|
|
253
|
+
console.log(` Manifest: ${assets.manifestFound ? "✓" : "✗ — run \`prompts-gpt sync\`"}`);
|
|
254
|
+
const cloudCount = assets.prompts.filter((p) => p.source === "library" || p.source === "generated").length;
|
|
255
|
+
const localCount = assets.prompts.filter((p) => p.source === "local").length;
|
|
256
|
+
const promptSummary = assets.prompts.length > 0
|
|
257
|
+
? `✓ (${assets.prompts.length}${cloudCount > 0 ? `, ${cloudCount} synced` : ""}${localCount > 0 ? `, ${localCount} local-only` : ""})`
|
|
258
|
+
: "✗ — none found";
|
|
259
|
+
console.log(` Prompts: ${promptSummary}`);
|
|
260
|
+
console.log(` Sweeps: ${assets.sweeps.length > 0 ? `✓ (${assets.sweeps.length})` : "— none found"}`);
|
|
261
|
+
console.log(` Agents: ${assets.agents.length > 0 ? `✓ (${assets.agents.length} targets)` : "✗ — run \`prompts-gpt sync\`"}`);
|
|
262
|
+
if (availableProviders.length > 0) {
|
|
263
|
+
console.log(` Providers: ✓`);
|
|
264
|
+
for (const p of availableProviders) {
|
|
265
|
+
console.log(` ${p.provider}: ${p.bin} | model: ${p.modelDefault}${p.version ? ` | ${p.version}` : ""}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
console.log(" Providers: ✗ — no CLI found");
|
|
270
|
+
}
|
|
271
|
+
console.log("");
|
|
272
|
+
if (assets.prompts.length > 0 && availableProviders.length > 0) {
|
|
273
|
+
console.log("Ready to run:");
|
|
274
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${assets.prompts[0].file}`);
|
|
275
|
+
if (assets.sweeps.length > 0) {
|
|
276
|
+
for (const s of assets.sweeps) {
|
|
277
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log("Not ready yet. Quick fix:");
|
|
283
|
+
console.log(" prompts-gpt quickstart");
|
|
284
|
+
console.log("");
|
|
285
|
+
console.log("Or step by step:");
|
|
286
|
+
let step = 1;
|
|
287
|
+
if (!assets.credentialsFound)
|
|
288
|
+
console.log(` ${step++}. prompts-gpt init --token <project-token>`);
|
|
289
|
+
if (assets.prompts.length === 0)
|
|
290
|
+
console.log(` ${step++}. prompts-gpt sync`);
|
|
291
|
+
if (availableProviders.length === 0)
|
|
292
|
+
console.log(` ${step++}. Install a provider CLI (codex, cursor agent, claude, copilot)`);
|
|
293
|
+
if (!assets.configFound)
|
|
294
|
+
console.log(` ${step++}. prompts-gpt setup`);
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (command === "validate") {
|
|
299
|
+
const cwd = getResolvedCwd(flags);
|
|
300
|
+
const result = await validateRunConfig(cwd);
|
|
301
|
+
if (Boolean(flags.json)) {
|
|
302
|
+
console.log(JSON.stringify(result, null, 2));
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
console.log(`Config: ${result.configPath}`);
|
|
306
|
+
console.log(`Valid: ${result.valid ? "yes" : "no"}`);
|
|
307
|
+
for (const e of result.errors) {
|
|
308
|
+
console.log(` error: ${e}`);
|
|
309
|
+
}
|
|
310
|
+
for (const w of result.warnings) {
|
|
311
|
+
console.log(` warning: ${w}`);
|
|
312
|
+
}
|
|
313
|
+
if (result.valid && result.errors.length === 0 && result.warnings.length === 0) {
|
|
314
|
+
console.log(" No issues found.");
|
|
315
|
+
}
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (command === "run") {
|
|
319
|
+
const cwd = getResolvedCwd(flags);
|
|
320
|
+
const promptFile = getStringFlag(flags, "prompt-file");
|
|
321
|
+
const config = await loadRunConfig(cwd);
|
|
322
|
+
warnOnConfigIssues(config);
|
|
323
|
+
if (!promptFile && !Boolean(flags.json)) {
|
|
324
|
+
if (!config.defaultPromptFile && config.batchDefaults.promptFiles.length === 0 && !config.batchDefaults.manifestPath) {
|
|
325
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
326
|
+
if (assets.prompts.length > 0 || assets.sweeps.length > 0) {
|
|
327
|
+
console.log("No default prompt configured. No default prompt file configured. Available options:\n");
|
|
328
|
+
if (assets.prompts.length > 0) {
|
|
329
|
+
console.log("Prompt packs:");
|
|
330
|
+
for (const p of assets.prompts) {
|
|
331
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
if (assets.sweeps.length > 0) {
|
|
335
|
+
console.log("\nSweep prompts (use `sweep` command):");
|
|
336
|
+
for (const s of assets.sweeps) {
|
|
337
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
console.log("\nOr set a default: prompts-gpt setup --prompt-file <path>");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
346
|
+
if (Boolean(flags["dry-run"])) {
|
|
347
|
+
const providers = await detectProviders(cwd);
|
|
348
|
+
const resolvedProvider = resolveRunProvider(agent, providers, config.providerOrder);
|
|
349
|
+
const resolvedModel = getStringFlag(flags, "model")?.trim() || config.modelOverrides[resolvedProvider]?.trim() || "";
|
|
350
|
+
let resolvedPrompt = promptFile || getStringFlag(flags, "prompt-file") || config.defaultPromptFile || null;
|
|
351
|
+
if (!resolvedPrompt) {
|
|
352
|
+
try {
|
|
353
|
+
const { resolveDefaultPromptFile: resolvePf } = await import("./index.js");
|
|
354
|
+
resolvedPrompt = await resolvePf(cwd, config);
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
resolvedPrompt = null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const agentStr = getStringFlag(flags, "agent") ? agent : `${agent} (auto-selected)`;
|
|
361
|
+
console.log("[dry-run] Would execute:");
|
|
362
|
+
console.log(` Agent: ${agentStr}`);
|
|
363
|
+
console.log(` Provider: ${resolvedProvider}`);
|
|
364
|
+
console.log(` Model: ${resolvedModel || "(default)"}`);
|
|
365
|
+
console.log(` Prompt: ${resolvedPrompt || "(none found — pass --prompt-file)"}`);
|
|
366
|
+
console.log(` Timeout: ${getStringFlag(flags, "timeout") || config.timeoutSeconds}s`);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const modelFlag = getStringFlag(flags, "model");
|
|
370
|
+
if (modelFlag && !Boolean(flags.json) && agent !== "router") {
|
|
371
|
+
const providers = await detectProviders(cwd);
|
|
372
|
+
const resolvedProvider = resolveRunProvider(agent, providers, config.providerOrder);
|
|
373
|
+
const mismatchWarning = warnModelProviderMismatch(resolvedProvider, modelFlag);
|
|
374
|
+
if (mismatchWarning) {
|
|
375
|
+
console.error(`[warning] ${mismatchWarning}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const result = await runPrompt({
|
|
379
|
+
cwd,
|
|
380
|
+
promptFile,
|
|
381
|
+
agent,
|
|
382
|
+
model: modelFlag,
|
|
383
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
384
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
385
|
+
runId: getStringFlag(flags, "run-id"),
|
|
386
|
+
approveMcps: !Boolean(flags["no-approve-mcps"]),
|
|
387
|
+
sandboxMode: getStringFlag(flags, "sandbox"),
|
|
388
|
+
background: Boolean(flags.background),
|
|
389
|
+
permissionMode: getStringFlag(flags, "permission-mode"),
|
|
390
|
+
});
|
|
391
|
+
if (Boolean(flags.json)) {
|
|
392
|
+
console.log(JSON.stringify(result, null, 2));
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const agentLabel = getStringFlag(flags, "agent") ? result.provider : `${result.provider} (auto — first available from provider order)`;
|
|
396
|
+
console.log(`Run ID: ${result.runId}`);
|
|
397
|
+
console.log(`Provider: ${agentLabel} | Model: ${result.model}`);
|
|
398
|
+
console.log(`Exit code: ${result.exitCode}`);
|
|
399
|
+
console.log(`Duration: ${formatDuration(result.durationMs)}`);
|
|
400
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
401
|
+
console.log(`Tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
402
|
+
}
|
|
403
|
+
console.log(`Run dir: ${result.runDir}`);
|
|
404
|
+
console.log(`Summary: ${result.summaryFile}`);
|
|
405
|
+
console.log(`Log: ${result.logFile}`);
|
|
406
|
+
if (result.exitCode === 0) {
|
|
407
|
+
console.log("");
|
|
408
|
+
console.log(`View results: cat ${result.summaryFile}`);
|
|
409
|
+
}
|
|
410
|
+
if (result.exitCode !== 0) {
|
|
411
|
+
const diagnostics = await extractRunDiagnostics(result.logFile, result.provider, result.model);
|
|
412
|
+
if (diagnostics.length > 0) {
|
|
413
|
+
console.log("");
|
|
414
|
+
console.log("Diagnostics:");
|
|
415
|
+
for (const d of diagnostics) {
|
|
416
|
+
console.log(` ${d}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (command === "run-batch") {
|
|
423
|
+
const cwd = getResolvedCwd(flags);
|
|
424
|
+
const promptFiles = getStringFlag(flags, "prompt-files")
|
|
425
|
+
?.split(",")
|
|
426
|
+
.map((item) => item.trim())
|
|
427
|
+
.filter(Boolean);
|
|
428
|
+
const config = await loadRunConfig(cwd);
|
|
429
|
+
warnOnConfigIssues(config);
|
|
430
|
+
if (!promptFiles && !getStringFlag(flags, "manifest") && !Boolean(flags.json)) {
|
|
431
|
+
if (!config.batchDefaults.manifestPath && config.batchDefaults.promptFiles.length === 0) {
|
|
432
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
433
|
+
if (assets.prompts.length > 0) {
|
|
434
|
+
console.log("No batch source configured. Available prompt packs:\n");
|
|
435
|
+
const fileList = assets.prompts.map((p) => `.prompts-gpt/${p.file}`).join(",");
|
|
436
|
+
console.log(` prompts-gpt run-batch --prompt-files ${fileList}`);
|
|
437
|
+
if (assets.manifestFound) {
|
|
438
|
+
console.log(` prompts-gpt run-batch --manifest .prompts-gpt/manifest.json`);
|
|
439
|
+
}
|
|
440
|
+
console.log("\nOr configure batch defaults: prompts-gpt setup");
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
446
|
+
const result = await runBatch({
|
|
447
|
+
cwd,
|
|
448
|
+
manifestPath: getStringFlag(flags, "manifest"),
|
|
449
|
+
promptFiles,
|
|
450
|
+
agent,
|
|
451
|
+
model: getStringFlag(flags, "model"),
|
|
452
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
453
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
454
|
+
});
|
|
455
|
+
if (Boolean(flags.json)) {
|
|
456
|
+
console.log(JSON.stringify(result, null, 2));
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
console.log(`Batch complete: total=${result.total} success=${result.success} failed=${result.failed}`);
|
|
460
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
461
|
+
console.log(`Batch tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
462
|
+
}
|
|
463
|
+
for (const [idx, run] of result.results.entries()) {
|
|
464
|
+
const status = run.exitCode === 0 ? "ok" : "FAIL";
|
|
465
|
+
const usageStr = hasTokenUsage(run.tokenUsage) ? `, tokens=${run.tokenUsage.totalTokens.toLocaleString()}` : "";
|
|
466
|
+
console.log(` [${idx + 1}/${result.total}] ${status} ${path.basename(run.promptFile)} -> ${run.provider} (exit=${run.exitCode}, ${formatDuration(run.durationMs)}${usageStr})`);
|
|
467
|
+
}
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
if (command === "sweep") {
|
|
471
|
+
const cwd = getResolvedCwd(flags);
|
|
472
|
+
const sweepPromptFile = getStringFlag(flags, "prompt-file");
|
|
473
|
+
const config = await loadRunConfig(cwd);
|
|
474
|
+
warnOnConfigIssues(config);
|
|
475
|
+
if (!sweepPromptFile && !Boolean(flags.json)) {
|
|
476
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
477
|
+
if (assets.sweeps.length === 1) {
|
|
478
|
+
const autoFile = assets.sweeps[0].file;
|
|
479
|
+
const iterFromFm = await readSweepIterationsFromFrontmatter(path.resolve(cwd, autoFile));
|
|
480
|
+
console.log(`Auto-selected sweep: ${autoFile}${iterFromFm ? ` (${iterFromFm} iterations from frontmatter)` : ""}`);
|
|
481
|
+
flags["prompt-file"] = autoFile;
|
|
482
|
+
if (iterFromFm && !getStringFlag(flags, "iterations")) {
|
|
483
|
+
flags.iterations = String(iterFromFm);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
else if (assets.sweeps.length > 1) {
|
|
487
|
+
console.log(`${assets.sweeps.length} sweep files found. Pick one with --prompt-file:\n`);
|
|
488
|
+
for (const s of assets.sweeps) {
|
|
489
|
+
const iterCount = await readSweepIterationsFromFrontmatter(path.resolve(cwd, s.file));
|
|
490
|
+
const iterFlag = iterCount ? ` --iterations ${iterCount}` : "";
|
|
491
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}${iterFlag}`);
|
|
492
|
+
}
|
|
493
|
+
if (assets.prompts.length > 0) {
|
|
494
|
+
console.log("\nOr run a single prompt:");
|
|
495
|
+
for (const p of assets.prompts.slice(0, 3)) {
|
|
496
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
console.log("No sweep files found.");
|
|
503
|
+
console.log(" Create .prompts-gpt/sweeps/<name>.md to add sweep prompts.");
|
|
504
|
+
console.log(" Or set a default: prompts-gpt setup --prompt-file <path>");
|
|
505
|
+
console.log(" Run `prompts-gpt list` to see what's available.");
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (!getStringFlag(flags, "iterations") && getStringFlag(flags, "prompt-file")) {
|
|
510
|
+
const iterFromFm = await readSweepIterationsFromFrontmatter(path.resolve(cwd, getStringFlag(flags, "prompt-file")));
|
|
511
|
+
if (iterFromFm) {
|
|
512
|
+
flags.iterations = String(iterFromFm);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
516
|
+
const onProgress = Boolean(flags.json)
|
|
517
|
+
? undefined
|
|
518
|
+
: (event) => {
|
|
519
|
+
if (event.type === "preflight") {
|
|
520
|
+
const report = JSON.parse(event.message);
|
|
521
|
+
console.log(`[preflight] provider=${report.provider} model=${report.model} branch=${report.gitBranch} dirty=${report.gitDirtyFiles} disk=${report.diskFreeMb}MB iterations=${report.iterations}`);
|
|
522
|
+
console.log(`[preflight] prompt=${report.promptFile}`);
|
|
523
|
+
for (const w of report.warnings)
|
|
524
|
+
console.log(`[preflight] warning: ${w}`);
|
|
525
|
+
}
|
|
526
|
+
else if (event.type === "iteration_start") {
|
|
527
|
+
console.log(`\n--- Iteration ${event.iteration}/${event.total} ---`);
|
|
528
|
+
}
|
|
529
|
+
else if (event.type === "iteration_end") {
|
|
530
|
+
const elapsed = formatDuration(event.durationMs);
|
|
531
|
+
console.log(`--- Iteration ${event.iteration} ${event.status} (${elapsed}) ---`);
|
|
532
|
+
}
|
|
533
|
+
else if (event.type === "attempt_retry") {
|
|
534
|
+
console.log(`[retry] iteration ${event.iteration}, attempt ${event.attempt}/${event.maxAttempts}, backoff ${event.backoffMs}ms`);
|
|
535
|
+
}
|
|
536
|
+
else if (event.type === "summary") {
|
|
537
|
+
const preview = event.lines.slice(0, 5).join("\n");
|
|
538
|
+
console.log(`[summary] iteration ${event.iteration}:\n${preview}${event.lines.length > 5 ? `\n ... (${event.lines.length - 5} more lines)` : ""}`);
|
|
539
|
+
}
|
|
540
|
+
else if (event.type === "sweep_end") {
|
|
541
|
+
console.log(`\nSweep complete: ${event.result.succeeded}/${event.result.totalIterations} succeeded in ${formatDuration(event.result.totalDurationMs)}`);
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
const result = await sweepPrompt({
|
|
545
|
+
cwd,
|
|
546
|
+
promptFile: getStringFlag(flags, "prompt-file"),
|
|
547
|
+
agent,
|
|
548
|
+
model: getStringFlag(flags, "model"),
|
|
549
|
+
iterations: parsePositiveIntFlag(getStringFlag(flags, "iterations"), "iterations"),
|
|
550
|
+
iterationTimeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "iteration-timeout"), "iteration-timeout"),
|
|
551
|
+
maxRetries: parseNonNegativeIntFlag(getStringFlag(flags, "max-retries"), "max-retries"),
|
|
552
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
553
|
+
runId: getStringFlag(flags, "run-id"),
|
|
554
|
+
approveMcps: !Boolean(flags["no-approve-mcps"]),
|
|
555
|
+
sandboxMode: getStringFlag(flags, "sandbox"),
|
|
556
|
+
phase: getStringFlag(flags, "phase"),
|
|
557
|
+
dryRun: Boolean(flags["dry-run"]),
|
|
558
|
+
maxRunDirs: parsePositiveIntFlag(getStringFlag(flags, "max-run-dirs"), "max-run-dirs"),
|
|
559
|
+
summaryLines: parsePositiveIntFlag(getStringFlag(flags, "summary-lines"), "summary-lines"),
|
|
560
|
+
background: Boolean(flags.background),
|
|
561
|
+
permissionMode: getStringFlag(flags, "permission-mode"),
|
|
562
|
+
onProgress,
|
|
563
|
+
});
|
|
564
|
+
if (Boolean(flags.json)) {
|
|
565
|
+
console.log(JSON.stringify(result, null, 2));
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (result.dryRun) {
|
|
569
|
+
const iterTimeout = parsePositiveIntFlag(getStringFlag(flags, "iteration-timeout"), "iteration-timeout") ?? 5400;
|
|
570
|
+
const estMaxDuration = result.totalIterations * iterTimeout;
|
|
571
|
+
console.log("[dry-run] Would execute sweep with:");
|
|
572
|
+
console.log(` Provider: ${result.provider}`);
|
|
573
|
+
console.log(` Model: ${result.model}`);
|
|
574
|
+
console.log(` Iterations: ${result.totalIterations}`);
|
|
575
|
+
console.log(` Prompt: ${result.promptFile}`);
|
|
576
|
+
console.log(` Max duration: ~${formatDuration(estMaxDuration * 1000)} (${result.totalIterations} x ${formatDuration(iterTimeout * 1000)})`);
|
|
577
|
+
try {
|
|
578
|
+
const { readFile: fsRead } = await import("node:fs/promises");
|
|
579
|
+
const previewText = await fsRead(result.promptFile, "utf8");
|
|
580
|
+
const previewLines = previewText.split("\n").slice(0, 5);
|
|
581
|
+
console.log(` Prompt preview:`);
|
|
582
|
+
for (const line of previewLines)
|
|
583
|
+
console.log(` ${line}`);
|
|
584
|
+
if (previewText.split("\n").length > 5)
|
|
585
|
+
console.log(` ... (${previewText.split("\n").length - 5} more lines)`);
|
|
586
|
+
}
|
|
587
|
+
catch { /* skip preview */ }
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
console.log(`Run ID: ${result.runId}`);
|
|
591
|
+
console.log(`Provider: ${result.provider} | Model: ${result.model}`);
|
|
592
|
+
console.log(`Prompt: ${result.promptFile}`);
|
|
593
|
+
console.log(`Iterations: ${result.succeeded}/${result.totalIterations} succeeded`);
|
|
594
|
+
console.log(`Duration: ${formatDuration(result.totalDurationMs)}`);
|
|
595
|
+
if (hasTokenUsage(result.tokenUsage)) {
|
|
596
|
+
console.log(`Tokens: ${formatTokenUsage(result.tokenUsage)}`);
|
|
597
|
+
}
|
|
598
|
+
console.log(`Run dir: ${result.runDir}`);
|
|
599
|
+
console.log(`Manifest: ${result.manifestFile}`);
|
|
600
|
+
if (result.iterations.length > 1) {
|
|
601
|
+
console.log("");
|
|
602
|
+
console.log("Per-iteration results:");
|
|
603
|
+
for (const iter of result.iterations) {
|
|
604
|
+
const tools = iter.toolCounts;
|
|
605
|
+
const toolStr = tools.total > 0 ? ` | tools: ${tools.total} (R:${tools.reads} W:${tools.writes} S:${tools.shells})` : "";
|
|
606
|
+
const usageStr = hasTokenUsage(iter.tokenUsage) ? ` | tokens: ${iter.tokenUsage.totalTokens.toLocaleString()}` : "";
|
|
607
|
+
console.log(` [${iter.iteration}/${result.totalIterations}] ${iter.status} (${formatDuration(iter.durationMs)})${toolStr}${usageStr}`);
|
|
608
|
+
}
|
|
609
|
+
const totalTools = result.iterations.reduce((acc, i) => ({
|
|
610
|
+
reads: acc.reads + i.toolCounts.reads, writes: acc.writes + i.toolCounts.writes,
|
|
611
|
+
shells: acc.shells + i.toolCounts.shells, searches: acc.searches + i.toolCounts.searches,
|
|
612
|
+
webSearches: acc.webSearches + i.toolCounts.webSearches, total: acc.total + i.toolCounts.total,
|
|
613
|
+
}), { reads: 0, writes: 0, shells: 0, searches: 0, webSearches: 0, total: 0 });
|
|
614
|
+
if (totalTools.total > 0) {
|
|
615
|
+
console.log(` Total tools: ${totalTools.total} (reads: ${totalTools.reads}, writes: ${totalTools.writes}, shells: ${totalTools.shells}, searches: ${totalTools.searches})`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
console.log("");
|
|
619
|
+
console.log("Inspect results:");
|
|
620
|
+
console.log(` cat ${result.manifestFile}`);
|
|
621
|
+
console.log(` ls ${result.runDir}`);
|
|
622
|
+
if (result.failed > 0) {
|
|
623
|
+
process.exitCode = 1;
|
|
624
|
+
}
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (command === "quickstart") {
|
|
628
|
+
const cwd = getResolvedCwd(flags);
|
|
629
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
630
|
+
const providers = await detectProviders(cwd);
|
|
631
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
632
|
+
console.log("Prompts-GPT Quickstart");
|
|
633
|
+
console.log("======================");
|
|
634
|
+
console.log("");
|
|
635
|
+
if (!assets.credentialsFound) {
|
|
636
|
+
console.log("Step 1: Save your project token");
|
|
637
|
+
console.log(" prompts-gpt init --token-prompt");
|
|
638
|
+
console.log("");
|
|
639
|
+
console.log(" Get your token from: https://prompts-gpt.com/studio/projects");
|
|
640
|
+
console.log("");
|
|
641
|
+
console.log("Run `prompts-gpt quickstart` again after saving your token.");
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
console.log("✓ Credentials found");
|
|
645
|
+
if (!assets.configFound) {
|
|
646
|
+
console.log("→ Setting up config...");
|
|
647
|
+
try {
|
|
648
|
+
await initRunConfig({ cwd, overwrite: false });
|
|
649
|
+
console.log("✓ Config created");
|
|
650
|
+
}
|
|
651
|
+
catch {
|
|
652
|
+
console.log("✓ Config already exists");
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
console.log("✓ Config found");
|
|
657
|
+
}
|
|
658
|
+
if (availableProviders.length === 0) {
|
|
659
|
+
console.log("");
|
|
660
|
+
console.log("✗ No provider CLIs found. Install at least one:");
|
|
661
|
+
console.log(" - codex: npm install -g @openai/codex");
|
|
662
|
+
console.log(" - claude: npm install -g @anthropic-ai/claude-code");
|
|
663
|
+
console.log(" - cursor: Install Cursor IDE (includes `agent` CLI)");
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
console.log(`✓ Providers: ${availableProviders.map((p) => p.provider).join(", ")}`);
|
|
667
|
+
if (assets.prompts.length === 0 && assets.sweeps.length === 0) {
|
|
668
|
+
console.log("");
|
|
669
|
+
console.log("→ No prompts found. Syncing from Prompts Studio...");
|
|
670
|
+
try {
|
|
671
|
+
const clientOpts = await resolveClientOptions("quickstart", flags).catch(() => null);
|
|
672
|
+
if (clientOpts) {
|
|
673
|
+
const qsClient = new PromptsGptClient(clientOpts);
|
|
674
|
+
const pulledPrompts = await qsClient.pullPrompts();
|
|
675
|
+
if (pulledPrompts.length > 0) {
|
|
676
|
+
const syncResult = await syncPrompts(pulledPrompts, { cwd, agent: "all" });
|
|
677
|
+
console.log(`✓ Synced ${syncResult.markdown.written.length} prompt(s) and ${syncResult.agents.written.length} agent file(s)`);
|
|
678
|
+
const refreshed = await discoverWorkspaceAssets(cwd);
|
|
679
|
+
if (refreshed.prompts.length > 0 || refreshed.sweeps.length > 0) {
|
|
680
|
+
console.log(`✓ Prompts: ${refreshed.prompts.length} prompt packs, ${refreshed.sweeps.length} sweeps`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
console.log("No prompts found in your Prompts Studio library.");
|
|
685
|
+
console.log(" Configure prompts at: https://prompts-gpt.com/studio/projects");
|
|
686
|
+
console.log(" Or run: prompts-gpt generate --goal \"Your task\"");
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
console.log("✗ Could not sync (credentials issue). Run manually:");
|
|
692
|
+
console.log(" prompts-gpt sync");
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
catch (syncErr) {
|
|
697
|
+
console.log(`✗ Sync failed: ${syncErr instanceof Error ? syncErr.message : String(syncErr)}`);
|
|
698
|
+
console.log(" Run manually: prompts-gpt sync");
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
const refreshedAssets = await discoverWorkspaceAssets(cwd);
|
|
702
|
+
if (refreshedAssets.prompts.length === 0 && refreshedAssets.sweeps.length === 0) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
console.log(`✓ Prompts: ${assets.prompts.length} prompt packs, ${assets.sweeps.length} sweeps`);
|
|
707
|
+
console.log("");
|
|
708
|
+
console.log("You're ready! Try these commands:");
|
|
709
|
+
console.log("");
|
|
710
|
+
if (assets.prompts.length > 0) {
|
|
711
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${assets.prompts[0].file}`);
|
|
712
|
+
}
|
|
713
|
+
if (assets.sweeps.length > 0) {
|
|
714
|
+
console.log(` prompts-gpt sweep --prompt-file ${assets.sweeps[0].file}`);
|
|
715
|
+
}
|
|
716
|
+
console.log(" prompts-gpt list — see all available prompts and sweeps");
|
|
717
|
+
console.log(" prompts-gpt status — check workspace readiness");
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (command === "load-config") {
|
|
721
|
+
const cwd = getResolvedCwd(flags);
|
|
722
|
+
const client = await createClientForCommand(command, flags);
|
|
723
|
+
const project = await client.getProject();
|
|
724
|
+
const prompts = await client.pullPrompts();
|
|
725
|
+
if (prompts.length === 0) {
|
|
726
|
+
console.log("No prompt packs found in the project library. Configure prompts in Prompts Studio first.");
|
|
727
|
+
console.log(` Open: https://prompts-gpt.com/studio/projects`);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const result = await syncPrompts(prompts, {
|
|
731
|
+
cwd,
|
|
732
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
733
|
+
overwrite: true,
|
|
734
|
+
agent: getStringFlag(flags, "agent") || "all",
|
|
735
|
+
});
|
|
736
|
+
const providers = await detectProviders(cwd);
|
|
737
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
738
|
+
let configError = null;
|
|
739
|
+
const configResult = await initRunConfig({
|
|
740
|
+
cwd,
|
|
741
|
+
overwrite: true,
|
|
742
|
+
}).catch((err) => {
|
|
743
|
+
configError = err.message;
|
|
744
|
+
return null;
|
|
745
|
+
});
|
|
746
|
+
if (Boolean(flags.json)) {
|
|
747
|
+
console.log(JSON.stringify({
|
|
748
|
+
project: { brandName: project.brandName, websiteUrl: project.websiteUrl },
|
|
749
|
+
synced: { prompts: result.markdown.written.length, agents: result.agents.written.length },
|
|
750
|
+
providers: availableProviders.map((p) => p.provider),
|
|
751
|
+
config: configResult ? "created" : "skipped",
|
|
752
|
+
}, null, 2));
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
console.log(`Loaded configuration from Prompts Studio for: ${project.brandName}`);
|
|
756
|
+
console.log(`Synced ${result.markdown.written.length} prompt pack(s) to ${result.markdown.outDir}`);
|
|
757
|
+
console.log(`Synced ${result.agents.written.length} agent file(s): ${result.agents.targets.join(", ")}`);
|
|
758
|
+
console.log(`Manifest: ${result.manifest.manifestPath}`);
|
|
759
|
+
if (configResult) {
|
|
760
|
+
console.log(`Config: ${configResult.configPath}`);
|
|
761
|
+
}
|
|
762
|
+
else if (configError) {
|
|
763
|
+
console.error(`[config] Skipped: ${configError}`);
|
|
764
|
+
}
|
|
765
|
+
if (availableProviders.length > 0 && result.manifest.manifest.prompts.length > 0) {
|
|
766
|
+
const firstFile = result.manifest.manifest.prompts[0]?.file;
|
|
767
|
+
if (firstFile) {
|
|
768
|
+
console.log(`\nReady to run:`);
|
|
769
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${firstFile}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
const lcAssets = await discoverWorkspaceAssets(cwd);
|
|
773
|
+
if (lcAssets.sweeps.length > 0) {
|
|
774
|
+
console.log(`\nSweep files available (${lcAssets.sweeps.length}):`);
|
|
775
|
+
for (const s of lcAssets.sweeps) {
|
|
776
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
73
781
|
if (command === "init") {
|
|
74
|
-
|
|
782
|
+
let token = await resolveTokenInput(flags, { command });
|
|
783
|
+
if (!token && process.stdin.isTTY && process.stdout.isTTY) {
|
|
784
|
+
console.log("No token flag provided — prompting interactively.");
|
|
785
|
+
console.log("Get your token from: https://prompts-gpt.com/studio/projects\n");
|
|
786
|
+
token = await readTokenFromPrompt(command);
|
|
787
|
+
}
|
|
75
788
|
if (!token) {
|
|
76
789
|
throw new CliError("Run `prompts-gpt init --token <project-token>`, `--token-stdin`, or `--token-prompt`.", CLI_EXIT_CODES.validation, {
|
|
77
790
|
helpCommand: "init",
|
|
@@ -88,13 +801,31 @@ async function runCommand(command, flags) {
|
|
|
88
801
|
});
|
|
89
802
|
}
|
|
90
803
|
const cwd = getResolvedCwd(flags);
|
|
804
|
+
const apiUrlFlag = getStringFlag(flags, "api-url");
|
|
805
|
+
if (apiUrlFlag) {
|
|
806
|
+
try {
|
|
807
|
+
const parsed = new URL(apiUrlFlag);
|
|
808
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
809
|
+
throw new CliError("--api-url must use https or http.", CLI_EXIT_CODES.validation, { helpCommand: "init" });
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
catch (e) {
|
|
813
|
+
if (e instanceof CliError)
|
|
814
|
+
throw e;
|
|
815
|
+
throw new CliError(`--api-url is not a valid URL: ${apiUrlFlag}`, CLI_EXIT_CODES.validation, { helpCommand: "init" });
|
|
816
|
+
}
|
|
817
|
+
}
|
|
91
818
|
const result = await saveLocalCredentials({
|
|
92
819
|
token,
|
|
93
|
-
apiUrl:
|
|
820
|
+
apiUrl: apiUrlFlag || DEFAULT_PROMPTS_GPT_API_URL,
|
|
94
821
|
cwd,
|
|
95
822
|
});
|
|
96
823
|
console.log(`Saved Prompts-GPT credentials to ${result.credentialsPath}`);
|
|
97
824
|
console.log("The credentials file is added to .gitignore.");
|
|
825
|
+
console.log("");
|
|
826
|
+
console.log("Next steps:");
|
|
827
|
+
console.log(" prompts-gpt quickstart — interactive setup (recommended)");
|
|
828
|
+
console.log(" prompts-gpt sync — pull prompts and sync agent files");
|
|
98
829
|
return;
|
|
99
830
|
}
|
|
100
831
|
if (command === "pull") {
|
|
@@ -114,28 +845,30 @@ async function runCommand(command, flags) {
|
|
|
114
845
|
if (result.skipped.length) {
|
|
115
846
|
console.log(`Skipped ${result.skipped.length} existing file(s). Use --overwrite to replace them.`);
|
|
116
847
|
}
|
|
848
|
+
if (result.written.length > 0) {
|
|
849
|
+
console.log("");
|
|
850
|
+
console.log("Run a pulled prompt:");
|
|
851
|
+
console.log(` prompts-gpt run --prompt-file ${result.written[0]}`);
|
|
852
|
+
console.log(" prompts-gpt list — see all available prompts");
|
|
853
|
+
}
|
|
117
854
|
return;
|
|
118
855
|
}
|
|
119
856
|
if (command === "generate") {
|
|
120
857
|
validateToolFlag(getStringFlag(flags, "tool"));
|
|
121
858
|
const goal = getStringFlag(flags, "goal");
|
|
122
859
|
if (!goal) {
|
|
123
|
-
throw new CliError("Prompt generation requires `--goal
|
|
124
|
-
|
|
125
|
-
|
|
860
|
+
throw new CliError("Prompt generation requires `--goal`.\n\n" +
|
|
861
|
+
"Example:\n" +
|
|
862
|
+
" prompts-gpt generate --goal \"Review pull requests for security issues\"\n" +
|
|
863
|
+
" prompts-gpt generate --goal \"Write unit tests\" --sync-agents\n\n" +
|
|
864
|
+
"Use --sync-agents to also write agent files (AGENTS.md, .cursor/rules, etc.).", CLI_EXIT_CODES.validation, { helpCommand: "generate" });
|
|
126
865
|
}
|
|
127
866
|
validateAgentFlag(getStringFlag(flags, "agent"));
|
|
867
|
+
if (!Boolean(flags.json)) {
|
|
868
|
+
printDataTransmissionNotice("generate", { goal, context: getStringFlag(flags, "context"), constraints: getStringFlag(flags, "constraints") });
|
|
869
|
+
}
|
|
128
870
|
const client = await createClientForCommand(command, flags);
|
|
129
|
-
const prompt = await client.generatePrompt(
|
|
130
|
-
goal,
|
|
131
|
-
context: getStringFlag(flags, "context") || "",
|
|
132
|
-
constraints: getStringFlag(flags, "constraints") || "",
|
|
133
|
-
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
134
|
-
tool: getStringFlag(flags, "tool") || "Codex",
|
|
135
|
-
mode: getStringFlag(flags, "mode") || "implement",
|
|
136
|
-
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
137
|
-
includeWebSearch: Boolean(flags["web-search"]),
|
|
138
|
-
});
|
|
871
|
+
const prompt = await client.generatePrompt(buildGenerateInput(flags));
|
|
139
872
|
const cwd = getResolvedCwd(flags);
|
|
140
873
|
const result = await writePromptMarkdownFiles([prompt], {
|
|
141
874
|
cwd,
|
|
@@ -145,12 +878,24 @@ async function runCommand(command, flags) {
|
|
|
145
878
|
const shouldSyncAgents = Boolean(flags["sync-agents"]) || typeof getStringFlag(flags, "agent") === "string";
|
|
146
879
|
if (shouldSyncAgents) {
|
|
147
880
|
const target = getStringFlag(flags, "agent") || "all";
|
|
148
|
-
const
|
|
881
|
+
const pulled = await client.pullPrompts().catch((err) => {
|
|
882
|
+
if (!Boolean(flags.json)) {
|
|
883
|
+
console.error(`[warning] Could not pull existing prompts for agent sync: ${err.message}`);
|
|
884
|
+
}
|
|
885
|
+
return [];
|
|
886
|
+
});
|
|
887
|
+
const syncedPrompts = mergePromptPacks([prompt, ...pulled]);
|
|
888
|
+
const agentResult = await writeAgentFiles(syncedPrompts, {
|
|
149
889
|
cwd,
|
|
150
890
|
agent: target,
|
|
151
891
|
overwriteAgentFiles: true,
|
|
152
892
|
});
|
|
893
|
+
const manifestResult = await writePromptManifest(syncedPrompts, {
|
|
894
|
+
cwd,
|
|
895
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
896
|
+
});
|
|
153
897
|
console.log(`Synced ${agentResult.written.length} agent file(s) for ${agentResult.targets.join(", ")}.`);
|
|
898
|
+
console.log(`Updated manifest: ${manifestResult.manifestPath}`);
|
|
154
899
|
}
|
|
155
900
|
console.log(`Generated: ${prompt.title}`);
|
|
156
901
|
console.log(`Wrote to ${result.written[0] ?? result.outDir}.`);
|
|
@@ -167,17 +912,11 @@ async function runCommand(command, flags) {
|
|
|
167
912
|
const goal = getStringFlag(flags, "goal");
|
|
168
913
|
const generatedOnly = Boolean(flags["generated-only"]);
|
|
169
914
|
const client = await createClientForCommand(command, flags);
|
|
915
|
+
if (goal && !Boolean(flags.json)) {
|
|
916
|
+
printDataTransmissionNotice("sync", { goal, context: getStringFlag(flags, "context"), constraints: getStringFlag(flags, "constraints") });
|
|
917
|
+
}
|
|
170
918
|
if (goal) {
|
|
171
|
-
prompts.push(await client.generatePrompt(
|
|
172
|
-
goal,
|
|
173
|
-
context: getStringFlag(flags, "context") || "",
|
|
174
|
-
constraints: getStringFlag(flags, "constraints") || "",
|
|
175
|
-
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
176
|
-
tool: getStringFlag(flags, "tool") || "Codex",
|
|
177
|
-
mode: getStringFlag(flags, "mode") || "implement",
|
|
178
|
-
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
179
|
-
includeWebSearch: Boolean(flags["web-search"]),
|
|
180
|
-
}));
|
|
919
|
+
prompts.push(await client.generatePrompt(buildGenerateInput(flags)));
|
|
181
920
|
}
|
|
182
921
|
if (!generatedOnly) {
|
|
183
922
|
prompts.push(...await client.pullPrompts(buildPullQuery(flags, parsedLimit)));
|
|
@@ -199,45 +938,58 @@ async function runCommand(command, flags) {
|
|
|
199
938
|
overwrite: Boolean(flags.overwrite),
|
|
200
939
|
agent: getStringFlag(flags, "agent") || "all",
|
|
201
940
|
});
|
|
202
|
-
console.log(`Synced ${result.markdown.written.length}
|
|
203
|
-
console.log(`Synced ${result.agents.written.length} agent integration file(s): ${result.agents.targets.join(", ")}.`);
|
|
204
|
-
console.log(`Updated manifest: ${result.manifest.manifestPath}`);
|
|
941
|
+
console.log(`Synced ${result.markdown.written.length} new prompt file(s) to ${result.markdown.outDir}.`);
|
|
205
942
|
if (result.markdown.skipped.length) {
|
|
206
|
-
console.log(`
|
|
943
|
+
console.log(`Kept ${result.markdown.skipped.length} existing file(s) unchanged. Use --overwrite to replace.`);
|
|
207
944
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const prompts = await client.pullPrompts(buildPullQuery(flags, parsedLimit));
|
|
215
|
-
if (prompts.length === 0) {
|
|
216
|
-
console.log("No prompts matched the query, so no agent files were written.");
|
|
217
|
-
return;
|
|
945
|
+
console.log(`Synced ${result.agents.written.length} agent file(s): ${result.agents.targets.join(", ")}.`);
|
|
946
|
+
console.log(`Manifest: ${result.manifest.manifestPath}`);
|
|
947
|
+
const syncCwd = getResolvedCwd(flags);
|
|
948
|
+
const postSyncAssets = await discoverWorkspaceAssets(syncCwd);
|
|
949
|
+
if (postSyncAssets.sweeps.length > 0) {
|
|
950
|
+
console.log(`Sweeps: ${postSyncAssets.sweeps.length} sweep file(s) available.`);
|
|
218
951
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
952
|
+
const postProviders = await detectProviders(syncCwd);
|
|
953
|
+
const postAvailable = postProviders.filter((p) => p.available);
|
|
954
|
+
if (postAvailable.length > 0 && postSyncAssets.prompts.length > 0) {
|
|
955
|
+
console.log("");
|
|
956
|
+
console.log("Next steps:");
|
|
957
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${postSyncAssets.prompts[0].file}`);
|
|
958
|
+
if (postSyncAssets.sweeps.length > 0) {
|
|
959
|
+
console.log(` prompts-gpt sweep --prompt-file ${postSyncAssets.sweeps[0].file}`);
|
|
960
|
+
}
|
|
224
961
|
}
|
|
225
|
-
const result = await writeAgentFiles(prompts, {
|
|
226
|
-
cwd: getResolvedCwd(flags),
|
|
227
|
-
agent: getStringFlag(flags, "agent") || "all",
|
|
228
|
-
overwriteAgentFiles: true,
|
|
229
|
-
});
|
|
230
|
-
console.log(`Synced ${result.written.length} agent integration file(s): ${result.targets.join(", ")}.`);
|
|
231
962
|
return;
|
|
232
963
|
}
|
|
233
964
|
if (command === "project") {
|
|
234
|
-
const
|
|
965
|
+
const clientOptions = await resolveClientOptions(command, flags);
|
|
966
|
+
const client = new PromptsGptClient(clientOptions);
|
|
235
967
|
const project = await client.getProject();
|
|
236
|
-
|
|
968
|
+
const apiUrl = clientOptions.apiUrl;
|
|
969
|
+
if (Boolean(flags.json)) {
|
|
970
|
+
console.log(JSON.stringify({
|
|
971
|
+
project,
|
|
972
|
+
apiUrl,
|
|
973
|
+
}, null, 2));
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
console.log(`Project: ${project.brandName}`);
|
|
977
|
+
console.log(`Website: ${project.websiteUrl}`);
|
|
978
|
+
console.log(`Industry: ${project.industryCategory}`);
|
|
979
|
+
console.log(`Language: ${project.targetLanguage}`);
|
|
980
|
+
console.log(`Countries: ${formatList(project.targetCountries)}`);
|
|
981
|
+
console.log(`Aliases: ${formatList(project.brandAliases)}`);
|
|
982
|
+
console.log(`Keywords: ${formatList(project.productKeywords)}`);
|
|
983
|
+
console.log(`Personas: ${formatList(project.targetPersonas)}`);
|
|
984
|
+
console.log(`Competitors: ${formatCompetitors(project.competitors)}`);
|
|
985
|
+
console.log(`API URL: ${apiUrl}`);
|
|
237
986
|
return;
|
|
238
987
|
}
|
|
239
988
|
}
|
|
240
989
|
async function createClientForCommand(command, flags) {
|
|
990
|
+
return new PromptsGptClient(await resolveClientOptions(command, flags));
|
|
991
|
+
}
|
|
992
|
+
async function resolveClientOptions(command, flags) {
|
|
241
993
|
const cwd = getResolvedCwd(flags);
|
|
242
994
|
const explicitToken = await resolveTokenInput(flags, { command });
|
|
243
995
|
const explicitApiUrl = getStringFlag(flags, "api-url");
|
|
@@ -248,14 +1000,29 @@ async function createClientForCommand(command, flags) {
|
|
|
248
1000
|
throw new CliError(`Could not read local credentials at ${credentialsPath}. Re-run \`prompts-gpt init --token <project-token>\` to replace the file.`, CLI_EXIT_CODES.auth, { helpCommand: command });
|
|
249
1001
|
}
|
|
250
1002
|
const token = explicitToken || credentials?.token || "";
|
|
1003
|
+
if (!token && !process.stdin.isTTY) {
|
|
1004
|
+
// CI fallback — never read process.env in the importable SDK, only in the CLI entrypoint
|
|
1005
|
+
const envToken = process.env.PROMPTS_GPT_TOKEN?.trim();
|
|
1006
|
+
if (envToken) {
|
|
1007
|
+
return {
|
|
1008
|
+
token: envToken,
|
|
1009
|
+
apiUrl: explicitApiUrl || credentials?.apiUrl || DEFAULT_PROMPTS_GPT_API_URL,
|
|
1010
|
+
fetch,
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
251
1014
|
if (!token) {
|
|
252
|
-
|
|
1015
|
+
const cloudCommands = new Set(["sync", "generate", "pull", "load-config", "project"]);
|
|
1016
|
+
const extra = cloudCommands.has(command)
|
|
1017
|
+
? `\n\nThis command connects to prompts-gpt.com. Set up credentials first:\n prompts-gpt init --token <project-token>\n prompts-gpt quickstart`
|
|
1018
|
+
: "";
|
|
1019
|
+
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 });
|
|
253
1020
|
}
|
|
254
|
-
return
|
|
1021
|
+
return {
|
|
255
1022
|
token,
|
|
256
1023
|
apiUrl: explicitApiUrl || credentials?.apiUrl || DEFAULT_PROMPTS_GPT_API_URL,
|
|
257
1024
|
fetch,
|
|
258
|
-
}
|
|
1025
|
+
};
|
|
259
1026
|
}
|
|
260
1027
|
function buildPullQuery(flags, limit) {
|
|
261
1028
|
return {
|
|
@@ -330,8 +1097,33 @@ function getCommandOptions(command) {
|
|
|
330
1097
|
if (command === "init") {
|
|
331
1098
|
return common;
|
|
332
1099
|
}
|
|
1100
|
+
if (command === "setup") {
|
|
1101
|
+
return {
|
|
1102
|
+
help: { type: "boolean" },
|
|
1103
|
+
cwd: { type: "string" },
|
|
1104
|
+
json: { type: "boolean" },
|
|
1105
|
+
overwrite: { type: "boolean" },
|
|
1106
|
+
"prompt-file": { type: "string" },
|
|
1107
|
+
"prompt-dir": { type: "string" },
|
|
1108
|
+
manifest: { type: "string" },
|
|
1109
|
+
"prompt-files": { type: "string" },
|
|
1110
|
+
agent: { type: "string" },
|
|
1111
|
+
"provider-order": { type: "string" },
|
|
1112
|
+
timeout: { type: "string" },
|
|
1113
|
+
"retry-count": { type: "string" },
|
|
1114
|
+
"artifacts-dir": { type: "string" },
|
|
1115
|
+
"allow-destructive-git": { type: "boolean" },
|
|
1116
|
+
"codex-model": { type: "string" },
|
|
1117
|
+
"cursor-model": { type: "string" },
|
|
1118
|
+
"claude-model": { type: "string" },
|
|
1119
|
+
"copilot-model": { type: "string" },
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
333
1122
|
if (command === "project") {
|
|
334
|
-
return
|
|
1123
|
+
return {
|
|
1124
|
+
...common,
|
|
1125
|
+
json: { type: "boolean" },
|
|
1126
|
+
};
|
|
335
1127
|
}
|
|
336
1128
|
if (command === "pull") {
|
|
337
1129
|
return {
|
|
@@ -386,54 +1178,135 @@ function getCommandOptions(command) {
|
|
|
386
1178
|
"dry-run": { type: "boolean" },
|
|
387
1179
|
};
|
|
388
1180
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
1181
|
+
if (command === "run") {
|
|
1182
|
+
return {
|
|
1183
|
+
help: { type: "boolean" },
|
|
1184
|
+
cwd: { type: "string" },
|
|
1185
|
+
json: { type: "boolean" },
|
|
1186
|
+
"prompt-file": { type: "string", short: "f" },
|
|
1187
|
+
agent: { type: "string" },
|
|
1188
|
+
model: { type: "string" },
|
|
1189
|
+
timeout: { type: "string" },
|
|
1190
|
+
"artifacts-dir": { type: "string" },
|
|
1191
|
+
"run-id": { type: "string" },
|
|
1192
|
+
sandbox: { type: "string" },
|
|
1193
|
+
"no-approve-mcps": { type: "boolean" },
|
|
1194
|
+
background: { type: "boolean" },
|
|
1195
|
+
"permission-mode": { type: "string" },
|
|
1196
|
+
"dry-run": { type: "boolean" },
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
if (command === "sweep") {
|
|
1200
|
+
return {
|
|
1201
|
+
help: { type: "boolean" },
|
|
1202
|
+
cwd: { type: "string" },
|
|
1203
|
+
json: { type: "boolean" },
|
|
1204
|
+
"prompt-file": { type: "string", short: "f" },
|
|
1205
|
+
agent: { type: "string" },
|
|
1206
|
+
model: { type: "string" },
|
|
1207
|
+
iterations: { type: "string", short: "n" },
|
|
1208
|
+
"iteration-timeout": { type: "string" },
|
|
1209
|
+
"max-retries": { type: "string" },
|
|
1210
|
+
"artifacts-dir": { type: "string" },
|
|
1211
|
+
"run-id": { type: "string" },
|
|
1212
|
+
sandbox: { type: "string" },
|
|
1213
|
+
"no-approve-mcps": { type: "boolean" },
|
|
1214
|
+
phase: { type: "string" },
|
|
1215
|
+
"dry-run": { type: "boolean" },
|
|
1216
|
+
"max-run-dirs": { type: "string" },
|
|
1217
|
+
"summary-lines": { type: "string" },
|
|
1218
|
+
background: { type: "boolean" },
|
|
1219
|
+
"permission-mode": { type: "string" },
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
if (command === "run-batch") {
|
|
1223
|
+
return {
|
|
1224
|
+
help: { type: "boolean" },
|
|
1225
|
+
cwd: { type: "string" },
|
|
1226
|
+
json: { type: "boolean" },
|
|
1227
|
+
manifest: { type: "string" },
|
|
1228
|
+
"prompt-files": { type: "string" },
|
|
1229
|
+
agent: { type: "string" },
|
|
1230
|
+
model: { type: "string" },
|
|
1231
|
+
timeout: { type: "string" },
|
|
1232
|
+
"artifacts-dir": { type: "string" },
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
if (command === "load-config") {
|
|
1236
|
+
return {
|
|
1237
|
+
...common,
|
|
1238
|
+
json: { type: "boolean" },
|
|
1239
|
+
out: { type: "string" },
|
|
1240
|
+
agent: { type: "string" },
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
if (command === "quickstart" || command === "list" || command === "status" || command === "validate" || command === "providers" || command === "doctor") {
|
|
1244
|
+
return {
|
|
1245
|
+
help: { type: "boolean" },
|
|
1246
|
+
cwd: { type: "string" },
|
|
1247
|
+
json: { type: "boolean" },
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
throw new CliError(`Unsupported command: ${command}.`, CLI_EXIT_CODES.usage, {
|
|
1251
|
+
helpCommand: "help",
|
|
422
1252
|
});
|
|
423
1253
|
}
|
|
424
1254
|
function toCliParseError(error, command) {
|
|
425
|
-
const
|
|
1255
|
+
const runnableCmd = isRunnableCommand(command) ? command : undefined;
|
|
1256
|
+
const message = normalizeParseErrorMessage(error instanceof Error ? error.message : String(error), runnableCmd);
|
|
426
1257
|
return new CliError(message, CLI_EXIT_CODES.usage, {
|
|
427
1258
|
helpCommand: command,
|
|
428
1259
|
});
|
|
429
1260
|
}
|
|
430
|
-
function normalizeParseErrorMessage(message) {
|
|
1261
|
+
function normalizeParseErrorMessage(message, command) {
|
|
431
1262
|
const trimmed = message.trim();
|
|
432
1263
|
if (trimmed.startsWith("Unknown option")) {
|
|
433
|
-
|
|
1264
|
+
const match = trimmed.match(/Unknown option '(--[^']+)'/);
|
|
1265
|
+
const unknownFlag = match?.[1];
|
|
1266
|
+
const base = trimmed.endsWith(".") ? trimmed : `${trimmed}.`;
|
|
1267
|
+
if (unknownFlag && command) {
|
|
1268
|
+
const suggestion = suggestClosestFlag(unknownFlag, command);
|
|
1269
|
+
if (suggestion) {
|
|
1270
|
+
return `${base} Did you mean ${suggestion}?`;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
return base;
|
|
434
1274
|
}
|
|
435
1275
|
return trimmed;
|
|
436
1276
|
}
|
|
1277
|
+
function suggestClosestFlag(unknown, command) {
|
|
1278
|
+
const options = getCommandOptions(command);
|
|
1279
|
+
const flagName = unknown.replace(/^--/, "");
|
|
1280
|
+
const candidates = Object.keys(options);
|
|
1281
|
+
let best = null;
|
|
1282
|
+
let bestScore = 0;
|
|
1283
|
+
for (const candidate of candidates) {
|
|
1284
|
+
const score = computeFlagSimilarity(flagName, candidate);
|
|
1285
|
+
if (score > bestScore && score >= 0.4) {
|
|
1286
|
+
bestScore = score;
|
|
1287
|
+
best = candidate;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return best ? `--${best}` : null;
|
|
1291
|
+
}
|
|
1292
|
+
function computeFlagSimilarity(a, b) {
|
|
1293
|
+
if (a === b)
|
|
1294
|
+
return 1;
|
|
1295
|
+
const shorter = a.length < b.length ? a : b;
|
|
1296
|
+
const longer = a.length < b.length ? b : a;
|
|
1297
|
+
if (longer.startsWith(shorter) || longer.endsWith(shorter))
|
|
1298
|
+
return 0.8;
|
|
1299
|
+
if (longer.includes(shorter) && shorter.length >= 3)
|
|
1300
|
+
return 0.6;
|
|
1301
|
+
if (shorter.length === 0)
|
|
1302
|
+
return 0;
|
|
1303
|
+
let matches = 0;
|
|
1304
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
|
1305
|
+
if (a[i] === b[i])
|
|
1306
|
+
matches++;
|
|
1307
|
+
}
|
|
1308
|
+
return matches / Math.max(a.length, b.length);
|
|
1309
|
+
}
|
|
437
1310
|
function validateFlagConflicts(command, flags) {
|
|
438
1311
|
const tokenSourceCount = [Boolean(flags.token), Boolean(flags["token-stdin"]), Boolean(flags["token-prompt"])].filter(Boolean).length;
|
|
439
1312
|
if (tokenSourceCount > 1) {
|
|
@@ -446,6 +1319,22 @@ function validateFlagConflicts(command, flags) {
|
|
|
446
1319
|
helpCommand: command,
|
|
447
1320
|
});
|
|
448
1321
|
}
|
|
1322
|
+
const promptSourceCount = [
|
|
1323
|
+
Boolean(flags["prompt-file"]),
|
|
1324
|
+
Boolean(flags["prompt-files"]),
|
|
1325
|
+
Boolean(flags.manifest),
|
|
1326
|
+
Boolean(flags["prompt-dir"]),
|
|
1327
|
+
].filter(Boolean).length;
|
|
1328
|
+
if (command === "setup" && promptSourceCount > 1) {
|
|
1329
|
+
throw new CliError("Use only one prompt source for `setup`: `--prompt-file`, `--prompt-files`, `--manifest`, or `--prompt-dir`.", CLI_EXIT_CODES.usage, {
|
|
1330
|
+
helpCommand: command,
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
if (command === "run-batch" && Boolean(flags["prompt-files"]) && Boolean(flags.manifest)) {
|
|
1334
|
+
throw new CliError("Use either `--prompt-files` or `--manifest`, not both.", CLI_EXIT_CODES.usage, {
|
|
1335
|
+
helpCommand: command,
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
449
1338
|
}
|
|
450
1339
|
async function resolveTokenInput(flags, options) {
|
|
451
1340
|
const explicitToken = getStringFlag(flags, "token")?.trim();
|
|
@@ -491,26 +1380,48 @@ function readTokenFromPrompt(command) {
|
|
|
491
1380
|
return new Promise((resolve, reject) => {
|
|
492
1381
|
const stdin = process.stdin;
|
|
493
1382
|
const stdout = process.stdout;
|
|
494
|
-
|
|
1383
|
+
const buf = Buffer.alloc(MAX_STDIN_TOKEN_LENGTH);
|
|
1384
|
+
let bufLen = 0;
|
|
495
1385
|
const cleanup = () => {
|
|
496
1386
|
stdin.removeListener("data", onData);
|
|
1387
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
1388
|
+
process.removeListener("SIGINT", onSigint);
|
|
497
1389
|
stdin.setRawMode?.(false);
|
|
498
1390
|
stdin.pause();
|
|
499
1391
|
};
|
|
1392
|
+
const extractAndWipe = () => {
|
|
1393
|
+
const result = buf.toString("utf8", 0, bufLen).trim();
|
|
1394
|
+
buf.fill(0, 0, bufLen);
|
|
1395
|
+
bufLen = 0;
|
|
1396
|
+
return result;
|
|
1397
|
+
};
|
|
500
1398
|
const finish = (callback) => {
|
|
501
1399
|
stdout.write("\n");
|
|
502
1400
|
cleanup();
|
|
503
1401
|
callback();
|
|
504
1402
|
};
|
|
1403
|
+
const onSigterm = () => {
|
|
1404
|
+
buf.fill(0, 0, bufLen);
|
|
1405
|
+
cleanup();
|
|
1406
|
+
process.exit(130);
|
|
1407
|
+
};
|
|
1408
|
+
const onSigint = () => {
|
|
1409
|
+
buf.fill(0, 0, bufLen);
|
|
1410
|
+
cleanup();
|
|
1411
|
+
process.exit(130);
|
|
1412
|
+
};
|
|
1413
|
+
process.on("SIGTERM", onSigterm);
|
|
1414
|
+
process.on("SIGINT", onSigint);
|
|
505
1415
|
const onData = (chunk) => {
|
|
506
1416
|
const value = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
507
1417
|
for (const char of value) {
|
|
508
1418
|
if (char === "\u0003") {
|
|
1419
|
+
buf.fill(0, 0, bufLen);
|
|
509
1420
|
finish(() => reject(new CliError("Token entry cancelled.", CLI_EXIT_CODES.general, { helpCommand: command })));
|
|
510
1421
|
return;
|
|
511
1422
|
}
|
|
512
1423
|
if (char === "\r" || char === "\n") {
|
|
513
|
-
const trimmed =
|
|
1424
|
+
const trimmed = extractAndWipe();
|
|
514
1425
|
if (!trimmed) {
|
|
515
1426
|
finish(() => reject(new CliError("Project token is required.", CLI_EXIT_CODES.validation, { helpCommand: command })));
|
|
516
1427
|
return;
|
|
@@ -519,21 +1430,33 @@ function readTokenFromPrompt(command) {
|
|
|
519
1430
|
return;
|
|
520
1431
|
}
|
|
521
1432
|
if (char === "\u007f" || char === "\b") {
|
|
522
|
-
|
|
1433
|
+
if (bufLen > 0) {
|
|
1434
|
+
bufLen--;
|
|
1435
|
+
buf[bufLen] = 0;
|
|
1436
|
+
}
|
|
523
1437
|
continue;
|
|
524
1438
|
}
|
|
525
1439
|
if (char >= " ") {
|
|
526
|
-
|
|
527
|
-
if (
|
|
1440
|
+
const charBytes = Buffer.byteLength(char, "utf8");
|
|
1441
|
+
if (bufLen + charBytes > MAX_STDIN_TOKEN_LENGTH) {
|
|
1442
|
+
buf.fill(0, 0, bufLen);
|
|
528
1443
|
finish(() => reject(new CliError("Token input is too long.", CLI_EXIT_CODES.validation, { helpCommand: command })));
|
|
529
1444
|
return;
|
|
530
1445
|
}
|
|
1446
|
+
buf.write(char, bufLen, "utf8");
|
|
1447
|
+
bufLen += charBytes;
|
|
531
1448
|
}
|
|
532
1449
|
}
|
|
533
1450
|
};
|
|
534
1451
|
stdout.write("Project token: ");
|
|
535
1452
|
stdin.setEncoding("utf8");
|
|
536
|
-
|
|
1453
|
+
try {
|
|
1454
|
+
stdin.setRawMode?.(true);
|
|
1455
|
+
}
|
|
1456
|
+
catch {
|
|
1457
|
+
reject(new CliError("Cannot enable raw mode for token prompt. Use --token-stdin instead.", CLI_EXIT_CODES.usage, { helpCommand: command }));
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
537
1460
|
stdin.resume();
|
|
538
1461
|
stdin.on("data", onData);
|
|
539
1462
|
});
|
|
@@ -542,11 +1465,11 @@ function parseLimitFlag(raw) {
|
|
|
542
1465
|
if (raw === undefined)
|
|
543
1466
|
return undefined;
|
|
544
1467
|
if (!/^\d+$/.test(raw)) {
|
|
545
|
-
throw new CliError("`--limit` must be a positive integer.", CLI_EXIT_CODES.validation);
|
|
1468
|
+
throw new CliError("`--limit` must be a positive integer between 1 and 100.", CLI_EXIT_CODES.validation);
|
|
546
1469
|
}
|
|
547
1470
|
const value = Number.parseInt(raw, 10);
|
|
548
|
-
if (!Number.isSafeInteger(value) || value < 1) {
|
|
549
|
-
throw new CliError("`--limit` must be a positive integer.", CLI_EXIT_CODES.validation);
|
|
1471
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 100) {
|
|
1472
|
+
throw new CliError("`--limit` must be a positive integer between 1 and 100.", CLI_EXIT_CODES.validation);
|
|
550
1473
|
}
|
|
551
1474
|
return value;
|
|
552
1475
|
}
|
|
@@ -568,6 +1491,18 @@ function validateAgentFlag(agent) {
|
|
|
568
1491
|
throw new CliError(`Invalid --agent target: ${invalid.join(", ")}. Use ${SUPPORTED_AGENT_TARGETS.join(", ")}, or all.`, CLI_EXIT_CODES.validation);
|
|
569
1492
|
}
|
|
570
1493
|
}
|
|
1494
|
+
function validateProviderOrderFlag(values) {
|
|
1495
|
+
if (!values?.length)
|
|
1496
|
+
return;
|
|
1497
|
+
const invalid = values.filter((value) => {
|
|
1498
|
+
const raw = value.trim().toLowerCase();
|
|
1499
|
+
const normalized = normalizeOrchestrationAgent(raw);
|
|
1500
|
+
return !raw || normalized === "router";
|
|
1501
|
+
});
|
|
1502
|
+
if (invalid.length > 0) {
|
|
1503
|
+
throw new CliError(`Invalid --provider-order value: ${invalid.join(", ")}. Use codex, cursor, claude, or copilot.`, CLI_EXIT_CODES.validation);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
571
1506
|
function getResolvedCwd(flags) {
|
|
572
1507
|
return path.resolve(getStringFlag(flags, "cwd") || process.cwd());
|
|
573
1508
|
}
|
|
@@ -575,6 +1510,44 @@ function getStringFlag(flags, name) {
|
|
|
575
1510
|
const value = flags[name];
|
|
576
1511
|
return typeof value === "string" ? value : undefined;
|
|
577
1512
|
}
|
|
1513
|
+
function formatDuration(ms) {
|
|
1514
|
+
if (ms < 1000)
|
|
1515
|
+
return `${ms}ms`;
|
|
1516
|
+
const totalSeconds = Math.round(ms / 1000);
|
|
1517
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
1518
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
1519
|
+
const seconds = totalSeconds % 60;
|
|
1520
|
+
if (hours > 0)
|
|
1521
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
1522
|
+
if (minutes > 0)
|
|
1523
|
+
return `${minutes}m ${seconds}s`;
|
|
1524
|
+
return `${seconds}s`;
|
|
1525
|
+
}
|
|
1526
|
+
function formatList(values) {
|
|
1527
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
1528
|
+
return "None";
|
|
1529
|
+
return values.join(", ");
|
|
1530
|
+
}
|
|
1531
|
+
function formatCompetitors(values) {
|
|
1532
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
1533
|
+
return "None";
|
|
1534
|
+
return values.map((competitor) => {
|
|
1535
|
+
const aliases = competitor.aliases?.length ? ` [aliases: ${competitor.aliases.join(", ")}]` : "";
|
|
1536
|
+
return competitor.websiteUrl ? `${competitor.name} (${competitor.websiteUrl})${aliases}` : `${competitor.name}${aliases}`;
|
|
1537
|
+
}).join("; ");
|
|
1538
|
+
}
|
|
1539
|
+
function mergePromptPacks(prompts) {
|
|
1540
|
+
const deduped = new Map();
|
|
1541
|
+
for (const prompt of prompts) {
|
|
1542
|
+
deduped.set(normalizePromptKey(prompt), prompt);
|
|
1543
|
+
}
|
|
1544
|
+
return [...deduped.values()];
|
|
1545
|
+
}
|
|
1546
|
+
function normalizePromptKey(prompt) {
|
|
1547
|
+
const raw = String(prompt.slug || prompt.title || "prompt").trim().toLowerCase();
|
|
1548
|
+
const normalized = raw.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1549
|
+
return normalized || "prompt";
|
|
1550
|
+
}
|
|
578
1551
|
function asCommandName(value) {
|
|
579
1552
|
if (!value)
|
|
580
1553
|
return undefined;
|
|
@@ -609,53 +1582,144 @@ Usage:
|
|
|
609
1582
|
prompts-gpt help [command]
|
|
610
1583
|
prompts-gpt version
|
|
611
1584
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
1585
|
+
Setup:
|
|
1586
|
+
quickstart Interactive setup — credentials, config, and first run
|
|
1587
|
+
init Save a project token
|
|
1588
|
+
setup Scaffold local orchestration config
|
|
1589
|
+
status Show workspace readiness and next steps
|
|
1590
|
+
doctor Validate prerequisites and config
|
|
1591
|
+
|
|
1592
|
+
Sync & Generate:
|
|
1593
|
+
sync Pull prompt packs and sync agent files
|
|
615
1594
|
pull Download prompt packs as Markdown files
|
|
616
|
-
generate Generate
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
1595
|
+
generate Generate a prompt pack from a goal
|
|
1596
|
+
load-config Pull config and prompts from Prompts Studio
|
|
1597
|
+
|
|
1598
|
+
Run:
|
|
1599
|
+
run Execute one prompt with a local agent (-f <file>)
|
|
1600
|
+
run-batch Execute multiple prompts
|
|
1601
|
+
sweep Multi-iteration execution (-f <file> -n <count>)
|
|
1602
|
+
|
|
1603
|
+
Inspect:
|
|
1604
|
+
list Show prompts, sweeps, and agent integrations
|
|
1605
|
+
validate Check config for errors
|
|
1606
|
+
providers Show detected provider CLIs
|
|
1607
|
+
project Show project linked to the token
|
|
621
1608
|
|
|
622
1609
|
Global options:
|
|
623
1610
|
--help Show help
|
|
624
1611
|
--version Show the current CLI version
|
|
625
1612
|
|
|
626
|
-
|
|
627
|
-
|
|
1613
|
+
Providers: ${ORCHESTRATION_AGENT_PROFILES.filter((p) => p !== "router").join(", ")} (or router for auto-select)
|
|
1614
|
+
Agent targets: ${SUPPORTED_AGENT_TARGETS.join(", ")}
|
|
628
1615
|
`);
|
|
629
1616
|
}
|
|
1617
|
+
function parsePositiveIntFlag(raw, flagName) {
|
|
1618
|
+
if (raw === undefined)
|
|
1619
|
+
return undefined;
|
|
1620
|
+
const label = flagName ? `--${flagName}` : "Value";
|
|
1621
|
+
if (!/^\d+$/.test(raw)) {
|
|
1622
|
+
throw new CliError(`${label} must be a positive integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1623
|
+
}
|
|
1624
|
+
const value = Number.parseInt(raw, 10);
|
|
1625
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
1626
|
+
throw new CliError(`${label} must be a positive integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1627
|
+
}
|
|
1628
|
+
return value;
|
|
1629
|
+
}
|
|
1630
|
+
function parseNonNegativeIntFlag(raw, flagName) {
|
|
1631
|
+
if (raw === undefined)
|
|
1632
|
+
return undefined;
|
|
1633
|
+
const label = flagName ? `--${flagName}` : "Value";
|
|
1634
|
+
if (!/^\d+$/.test(raw)) {
|
|
1635
|
+
throw new CliError(`${label} must be a non-negative integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1636
|
+
}
|
|
1637
|
+
const value = Number.parseInt(raw, 10);
|
|
1638
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
1639
|
+
throw new CliError(`${label} must be a non-negative integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1640
|
+
}
|
|
1641
|
+
return value;
|
|
1642
|
+
}
|
|
1643
|
+
function resolveRunAgent(flags, fallback) {
|
|
1644
|
+
const raw = getStringFlag(flags, "agent");
|
|
1645
|
+
if (!raw)
|
|
1646
|
+
return fallback;
|
|
1647
|
+
const normalizedRaw = raw.trim().toLowerCase();
|
|
1648
|
+
const normalized = normalizeOrchestrationAgent(raw);
|
|
1649
|
+
if (normalized === "router" && normalizedRaw !== "router") {
|
|
1650
|
+
const profiles = ORCHESTRATION_AGENT_PROFILES.join(", ");
|
|
1651
|
+
const hint = ORCHESTRATION_AGENT_PROFILES.find((p) => p.startsWith(normalizedRaw.slice(0, 3)));
|
|
1652
|
+
const suggestion = hint ? ` Did you mean "${hint}"?` : "";
|
|
1653
|
+
throw new CliError(`Invalid --agent target: ${raw}. Use ${profiles}.${suggestion}`, CLI_EXIT_CODES.validation);
|
|
1654
|
+
}
|
|
1655
|
+
return normalized;
|
|
1656
|
+
}
|
|
630
1657
|
function getCommandHelp(command) {
|
|
631
1658
|
if (command === "init") {
|
|
632
1659
|
return `prompts-gpt init
|
|
633
1660
|
|
|
634
1661
|
Usage:
|
|
635
|
-
prompts-gpt init
|
|
1662
|
+
prompts-gpt init [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
636
1663
|
|
|
637
1664
|
Why use it:
|
|
638
|
-
Stores a project token
|
|
1665
|
+
Stores a project token locally so you don't have to pass it on every command.
|
|
1666
|
+
If run without flags in an interactive terminal, it will prompt for the token.
|
|
639
1667
|
|
|
640
1668
|
Options:
|
|
641
1669
|
--token <token> Project API token. Must start with pgpt_.
|
|
642
|
-
--token-stdin Read the project token from stdin
|
|
1670
|
+
--token-stdin Read the project token from stdin (for CI/CD pipelines).
|
|
643
1671
|
--token-prompt Prompt for the project token without echoing it.
|
|
644
1672
|
--api-url <url> Custom API base URL for self-hosted instances.
|
|
645
|
-
--cwd <path> Target project directory
|
|
1673
|
+
--cwd <path> Target project directory.
|
|
646
1674
|
--help Show this command help.
|
|
1675
|
+
|
|
1676
|
+
Examples:
|
|
1677
|
+
prompts-gpt init # interactive prompt
|
|
1678
|
+
prompts-gpt init --token pgpt_abc123 # direct token
|
|
1679
|
+
printf '%s' "$TOKEN" | prompts-gpt init --token-stdin # CI/CD
|
|
1680
|
+
`;
|
|
1681
|
+
}
|
|
1682
|
+
if (command === "setup") {
|
|
1683
|
+
return `prompts-gpt setup
|
|
1684
|
+
|
|
1685
|
+
Usage:
|
|
1686
|
+
prompts-gpt setup [--prompt-file <path> | --prompt-files <a,b,c> | --manifest <path> | --prompt-dir <path>] [--agent codex|cursor|claude|copilot|router] [--provider-order <a,b,c>] [--timeout <seconds>] [--retry-count <n>] [--artifacts-dir <path>] [--codex-model <name>] [--cursor-model <name>] [--claude-model <name>] [--copilot-model <name>] [--allow-destructive-git] [--overwrite] [--json] [--cwd <path>]
|
|
1687
|
+
|
|
1688
|
+
Why use it:
|
|
1689
|
+
Scaffolds a generic local orchestration config so a repo can run prompts through Codex, Cursor, Claude Code, or Copilot with minimal repeated CLI flags.
|
|
1690
|
+
|
|
1691
|
+
Options:
|
|
1692
|
+
--prompt-file <path> Default single prompt file for \`prompts-gpt run\`.
|
|
1693
|
+
--prompt-files <list> Default batch prompt files for \`prompts-gpt run-batch\`.
|
|
1694
|
+
--manifest <path> Use this manifest as the batch source. Default: auto-detect .prompts-gpt/manifest.json
|
|
1695
|
+
--prompt-dir <path> Scan a prompt directory when you do not use .prompts-gpt.
|
|
1696
|
+
--agent <name> Default orchestration profile. Default: router
|
|
1697
|
+
--provider-order <list> Comma-separated router order such as codex,cursor,claude,copilot
|
|
1698
|
+
--timeout <seconds> Default timeout in seconds. Default: 900
|
|
1699
|
+
--retry-count <n> Retry count for spawn and timeout failures. Default: 0
|
|
1700
|
+
--artifacts-dir <path> Run artifact directory. Default: .scripts/runs
|
|
1701
|
+
--codex-model <name> Default model override for codex.
|
|
1702
|
+
--cursor-model <name> Default model override for cursor.
|
|
1703
|
+
--claude-model <name> Default model override for claude.
|
|
1704
|
+
--copilot-model <name> Default model override for copilot.
|
|
1705
|
+
--allow-destructive-git Write config with destructive git protection disabled.
|
|
1706
|
+
--overwrite Replace an existing config file.
|
|
1707
|
+
--json Print the generated config payload as JSON.
|
|
1708
|
+
--cwd <path> Project directory.
|
|
1709
|
+
--help Show this command help.
|
|
647
1710
|
`;
|
|
648
1711
|
}
|
|
649
1712
|
if (command === "project") {
|
|
650
1713
|
return `prompts-gpt project
|
|
651
1714
|
|
|
652
1715
|
Usage:
|
|
653
|
-
prompts-gpt project [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1716
|
+
prompts-gpt project [--json] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
654
1717
|
|
|
655
1718
|
Why use it:
|
|
656
1719
|
Verifies that the current local token resolves to the expected Prompts-GPT project before syncing files.
|
|
657
1720
|
|
|
658
1721
|
Options:
|
|
1722
|
+
--json Print the full project payload as JSON.
|
|
659
1723
|
--token <token> Override the saved local token for this command only.
|
|
660
1724
|
--token-stdin Read the override token from stdin for this command only.
|
|
661
1725
|
--token-prompt Prompt for the override token without echoing it.
|
|
@@ -673,6 +1737,10 @@ Usage:
|
|
|
673
1737
|
Why use it:
|
|
674
1738
|
Pulls prompt packs into local Markdown files so teams can review and use the same prompt assets inside their repository.
|
|
675
1739
|
|
|
1740
|
+
Data privacy:
|
|
1741
|
+
Downloads prompts from your prompts-gpt.com project library.
|
|
1742
|
+
No local files or repo content are uploaded.
|
|
1743
|
+
|
|
676
1744
|
Options:
|
|
677
1745
|
--query <text> Search query for the project prompt library.
|
|
678
1746
|
--q <text> Short alias for --query.
|
|
@@ -699,6 +1767,11 @@ Usage:
|
|
|
699
1767
|
Why use it:
|
|
700
1768
|
Creates a new reusable prompt pack from a concrete developer goal, then optionally installs agent-readable files immediately.
|
|
701
1769
|
|
|
1770
|
+
Data privacy:
|
|
1771
|
+
The text you pass via --goal, --context, and --constraints is sent to prompts-gpt.com
|
|
1772
|
+
for AI-powered prompt generation. No local files or repo content are uploaded.
|
|
1773
|
+
Do not include PII, secrets, or confidential data in these flags.
|
|
1774
|
+
|
|
702
1775
|
Options:
|
|
703
1776
|
--goal <text> Required. The task to generate a prompt pack for.
|
|
704
1777
|
--context <text> Extra project or stack context for the generator.
|
|
@@ -711,13 +1784,19 @@ Options:
|
|
|
711
1784
|
--out <dir> Output directory inside the current project. Default: .prompts-gpt
|
|
712
1785
|
--overwrite Replace an existing generated Markdown file.
|
|
713
1786
|
--agent <targets> Sync agent files for specific targets after generation.
|
|
714
|
-
|
|
1787
|
+
When set, also writes agent-specific files (AGENTS.md, .cursor/rules, etc.).
|
|
1788
|
+
--sync-agents Sync all agent files after generation (same as --agent all).
|
|
715
1789
|
--token <token> Override the saved local token for this command only.
|
|
716
1790
|
--token-stdin Read the override token from stdin for this command only.
|
|
717
1791
|
--token-prompt Prompt for the override token without echoing it.
|
|
718
1792
|
--api-url <url> Override the saved API base URL for this command only.
|
|
719
1793
|
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
720
1794
|
--help Show this command help.
|
|
1795
|
+
|
|
1796
|
+
Examples:
|
|
1797
|
+
prompts-gpt generate --goal "Review PRs for security issues"
|
|
1798
|
+
prompts-gpt generate --goal "Write unit tests" --sync-agents
|
|
1799
|
+
prompts-gpt generate --goal "Add error handling" --agent cursor,codex
|
|
721
1800
|
`;
|
|
722
1801
|
}
|
|
723
1802
|
if (command === "sync") {
|
|
@@ -729,6 +1808,13 @@ Usage:
|
|
|
729
1808
|
Why use it:
|
|
730
1809
|
Gives teams a one-command path to refresh Markdown prompts, agent files, and the local manifest from the same source of truth.
|
|
731
1810
|
|
|
1811
|
+
Data privacy:
|
|
1812
|
+
Prompts are downloaded from your prompts-gpt.com project library.
|
|
1813
|
+
When --goal is used, the text you pass is sent to prompts-gpt.com for AI generation.
|
|
1814
|
+
No local files or repo content are uploaded — only explicit flag values are transmitted.
|
|
1815
|
+
Do not include PII, secrets, or confidential data in --goal, --context, or --constraints.
|
|
1816
|
+
Use --dry-run to preview what would be synced without sending or writing anything.
|
|
1817
|
+
|
|
732
1818
|
Options:
|
|
733
1819
|
--goal <text> Generate one prompt pack before syncing.
|
|
734
1820
|
--generated-only Skip library pull and sync only the generated prompt pack from --goal.
|
|
@@ -754,31 +1840,216 @@ Options:
|
|
|
754
1840
|
--api-url <url> Override the saved API base URL for this command only.
|
|
755
1841
|
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
756
1842
|
--help Show this command help.
|
|
1843
|
+
|
|
1844
|
+
Examples:
|
|
1845
|
+
prompts-gpt sync # pull all prompts + sync agent files
|
|
1846
|
+
prompts-gpt sync --goal "Add error handling" # generate + pull + sync
|
|
1847
|
+
prompts-gpt sync --dry-run # preview without writing
|
|
1848
|
+
prompts-gpt sync --agent cursor,codex # sync only specific agents
|
|
757
1849
|
`;
|
|
758
1850
|
}
|
|
759
|
-
if (command === "
|
|
760
|
-
return `prompts-gpt
|
|
1851
|
+
if (command === "run") {
|
|
1852
|
+
return `prompts-gpt run
|
|
761
1853
|
|
|
762
1854
|
Usage:
|
|
763
|
-
prompts-gpt
|
|
1855
|
+
prompts-gpt run [-f <path>] [--agent <name>] [--model <name>] [--timeout <seconds>] [--dry-run]
|
|
764
1856
|
|
|
765
1857
|
Why use it:
|
|
766
|
-
|
|
1858
|
+
Executes one local prompt file with the built-in provider adapter runtime and writes run artifacts.
|
|
1859
|
+
If \`--prompt-file\` is omitted and only one prompt exists locally, it is auto-selected.
|
|
767
1860
|
|
|
768
1861
|
Options:
|
|
769
|
-
--
|
|
770
|
-
--
|
|
771
|
-
--
|
|
772
|
-
--
|
|
773
|
-
--
|
|
774
|
-
--
|
|
775
|
-
--
|
|
776
|
-
--
|
|
777
|
-
--
|
|
778
|
-
--
|
|
779
|
-
--
|
|
780
|
-
--
|
|
781
|
-
--cwd <path>
|
|
1862
|
+
-f, --prompt-file <path> Optional explicit prompt Markdown or text file.
|
|
1863
|
+
--agent <name> Orchestration profile. Default from ${DEFAULT_RUN_CONFIG_PATH} or router.
|
|
1864
|
+
--model <name> Optional model override for the selected provider.
|
|
1865
|
+
--timeout <seconds> Execution timeout in seconds.
|
|
1866
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1867
|
+
--run-id <id> Explicit run ID for artifact folder naming.
|
|
1868
|
+
--sandbox <mode> Codex sandbox mode. Default: workspace-write.
|
|
1869
|
+
--no-approve-mcps Disable Cursor MCP auto-approval flag.
|
|
1870
|
+
--background Run as a background agent (Cursor cloud agent mode).
|
|
1871
|
+
--permission-mode <mode> Claude Code permission mode. Default: acceptEdits.
|
|
1872
|
+
--dry-run Preview the execution parameters without actually running.
|
|
1873
|
+
--json Print machine-readable JSON output.
|
|
1874
|
+
--cwd <path> Project directory.
|
|
1875
|
+
--help Show this command help.
|
|
1876
|
+
`;
|
|
1877
|
+
}
|
|
1878
|
+
if (command === "run-batch") {
|
|
1879
|
+
return `prompts-gpt run-batch
|
|
1880
|
+
|
|
1881
|
+
Usage:
|
|
1882
|
+
prompts-gpt run-batch [--manifest <path> | --prompt-files <a,b,c>] [--agent <name>] [--model <name>] [--timeout <seconds>]
|
|
1883
|
+
|
|
1884
|
+
Why use it:
|
|
1885
|
+
Executes multiple prompt files in sequence using the configured prompt source, a manifest, or an explicit file list.
|
|
1886
|
+
|
|
1887
|
+
Options:
|
|
1888
|
+
--manifest <path> Prompt manifest path. Overrides config batch defaults.
|
|
1889
|
+
--prompt-files <list> Comma-separated prompt files to run.
|
|
1890
|
+
--agent <name> Orchestration profile. Default from ${DEFAULT_RUN_CONFIG_PATH} or router.
|
|
1891
|
+
--model <name> Optional model override for all runs.
|
|
1892
|
+
--timeout <seconds> Execution timeout in seconds per prompt.
|
|
1893
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1894
|
+
--json Print machine-readable JSON output.
|
|
1895
|
+
--cwd <path> Project directory.
|
|
1896
|
+
--help Show this command help.
|
|
1897
|
+
|
|
1898
|
+
Examples:
|
|
1899
|
+
prompts-gpt run-batch --manifest .prompts-gpt/manifest.json
|
|
1900
|
+
prompts-gpt run-batch --prompt-files .prompts-gpt/review.md,.prompts-gpt/tests.md
|
|
1901
|
+
`;
|
|
1902
|
+
}
|
|
1903
|
+
if (command === "sweep") {
|
|
1904
|
+
return `prompts-gpt sweep
|
|
1905
|
+
|
|
1906
|
+
Usage:
|
|
1907
|
+
prompts-gpt sweep [-f <path>] [-n <count>] [--agent <name>] [--model <name>] [--dry-run]
|
|
1908
|
+
|
|
1909
|
+
Why use it:
|
|
1910
|
+
Runs the same prompt N times, feeding each iteration's summary into the next.
|
|
1911
|
+
Includes pre-flight checks, safety guards, SIGTERM handling, and progress monitoring.
|
|
1912
|
+
|
|
1913
|
+
When --prompt-file is omitted and only one .prompts-gpt/sweeps/*.md file exists,
|
|
1914
|
+
it is auto-selected. The iteration count defaults to the \`iterations:\` value
|
|
1915
|
+
in the sweep file's YAML frontmatter (or 1 if not specified).
|
|
1916
|
+
|
|
1917
|
+
Options:
|
|
1918
|
+
-f, --prompt-file <path> Prompt file to sweep. Auto-detects local sweeps if omitted.
|
|
1919
|
+
-n, --iterations <n> Number of iterations. Default: from frontmatter or 1.
|
|
1920
|
+
--agent <name> Orchestration profile. Default from config or router.
|
|
1921
|
+
--model <name> Model override for the selected provider.
|
|
1922
|
+
--iteration-timeout <secs> Timeout per iteration in seconds. Default: 5400 (90 min)
|
|
1923
|
+
--max-retries <n> Max retries per iteration on spawn/timeout. Default: 2
|
|
1924
|
+
--phase <name> Optional phase label injected into the prompt.
|
|
1925
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1926
|
+
--run-id <id> Explicit run ID for artifact folder naming.
|
|
1927
|
+
--sandbox <mode> Codex sandbox mode. Default: workspace-write
|
|
1928
|
+
--no-approve-mcps Disable Cursor MCP auto-approval flag.
|
|
1929
|
+
--background Run as a background agent (Cursor cloud agent mode).
|
|
1930
|
+
--permission-mode <mode> Claude Code permission mode. Default: acceptEdits
|
|
1931
|
+
--max-run-dirs <n> Max artifact directories to keep. Default: 20
|
|
1932
|
+
--summary-lines <n> Lines of summary to extract per iteration. Default: 40
|
|
1933
|
+
--dry-run Preview what the sweep would do without executing.
|
|
1934
|
+
--json Print machine-readable JSON output.
|
|
1935
|
+
--cwd <path> Project directory.
|
|
1936
|
+
--help Show this command help.
|
|
1937
|
+
|
|
1938
|
+
Examples:
|
|
1939
|
+
prompts-gpt sweep # auto-pick local sweep
|
|
1940
|
+
prompts-gpt sweep -f .prompts-gpt/sweeps/sdk-hardening.md # explicit file
|
|
1941
|
+
prompts-gpt sweep -f .prompts-gpt/sweeps/design.md -n 5 # 5 iterations
|
|
1942
|
+
prompts-gpt sweep --dry-run # preview without running
|
|
1943
|
+
`;
|
|
1944
|
+
}
|
|
1945
|
+
if (command === "list") {
|
|
1946
|
+
return `prompts-gpt list
|
|
1947
|
+
|
|
1948
|
+
Usage:
|
|
1949
|
+
prompts-gpt list [--json] [--cwd <path>]
|
|
1950
|
+
|
|
1951
|
+
Why use it:
|
|
1952
|
+
Shows all prompt packs, sweep files, and agent integrations available in the workspace.
|
|
1953
|
+
Gives runnable commands for each entry so you can copy-paste them directly.
|
|
1954
|
+
|
|
1955
|
+
Options:
|
|
1956
|
+
--json Print as JSON.
|
|
1957
|
+
--cwd <path> Project directory.
|
|
1958
|
+
--help Show this command help.
|
|
1959
|
+
`;
|
|
1960
|
+
}
|
|
1961
|
+
if (command === "status") {
|
|
1962
|
+
return `prompts-gpt status
|
|
1963
|
+
|
|
1964
|
+
Usage:
|
|
1965
|
+
prompts-gpt status [--json] [--cwd <path>]
|
|
1966
|
+
|
|
1967
|
+
Why use it:
|
|
1968
|
+
Shows workspace readiness at a glance: credentials, config, manifest,
|
|
1969
|
+
prompts, sweeps, agent integrations, and available providers.
|
|
1970
|
+
|
|
1971
|
+
Options:
|
|
1972
|
+
--json Print as JSON.
|
|
1973
|
+
--cwd <path> Project directory.
|
|
1974
|
+
--help Show this command help.
|
|
1975
|
+
`;
|
|
1976
|
+
}
|
|
1977
|
+
if (command === "validate") {
|
|
1978
|
+
return `prompts-gpt validate
|
|
1979
|
+
|
|
1980
|
+
Usage:
|
|
1981
|
+
prompts-gpt validate [--json] [--cwd <path>]
|
|
1982
|
+
|
|
1983
|
+
Why use it:
|
|
1984
|
+
Validates the .prompts-gpt/config.json file and reports errors and
|
|
1985
|
+
warnings without running any commands.
|
|
1986
|
+
|
|
1987
|
+
Options:
|
|
1988
|
+
--json Print as JSON.
|
|
1989
|
+
--cwd <path> Project directory.
|
|
1990
|
+
--help Show this command help.
|
|
1991
|
+
`;
|
|
1992
|
+
}
|
|
1993
|
+
if (command === "providers") {
|
|
1994
|
+
return `prompts-gpt providers
|
|
1995
|
+
|
|
1996
|
+
Usage:
|
|
1997
|
+
prompts-gpt providers [--json] [--cwd <path>]
|
|
1998
|
+
|
|
1999
|
+
Why use it:
|
|
2000
|
+
Shows provider CLI detection details for codex, cursor, claude, and copilot so you can decide the best router order before running setup.
|
|
2001
|
+
`;
|
|
2002
|
+
}
|
|
2003
|
+
if (command === "doctor") {
|
|
2004
|
+
return `prompts-gpt doctor
|
|
2005
|
+
|
|
2006
|
+
Usage:
|
|
2007
|
+
prompts-gpt doctor [--json] [--cwd <path>]
|
|
2008
|
+
|
|
2009
|
+
Why use it:
|
|
2010
|
+
Checks runtime prerequisites, provider availability, prompt-source readiness, and run config health.
|
|
2011
|
+
`;
|
|
2012
|
+
}
|
|
2013
|
+
if (command === "load-config") {
|
|
2014
|
+
return `prompts-gpt load-config
|
|
2015
|
+
|
|
2016
|
+
Usage:
|
|
2017
|
+
prompts-gpt load-config [--agent <targets>] [--out <dir>] [--json] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
2018
|
+
|
|
2019
|
+
Why use it:
|
|
2020
|
+
One command to pull all prompts, agent files, and config from Prompts Studio
|
|
2021
|
+
into your local workspace. Replaces the multi-step init + sync + setup flow
|
|
2022
|
+
for users who manage their prompt library in the Prompts Studio web app.
|
|
2023
|
+
|
|
2024
|
+
Data privacy:
|
|
2025
|
+
Downloads prompts and project config from your prompts-gpt.com project.
|
|
2026
|
+
No local files or repo content are uploaded.
|
|
2027
|
+
|
|
2028
|
+
Options:
|
|
2029
|
+
--agent <targets> Comma-separated agent targets. Default: all
|
|
2030
|
+
--out <dir> Output directory. Default: .prompts-gpt
|
|
2031
|
+
--json Print machine-readable JSON output.
|
|
2032
|
+
--token <token> Override saved token.
|
|
2033
|
+
--token-stdin Read token from stdin.
|
|
2034
|
+
--token-prompt Prompt for token.
|
|
2035
|
+
--api-url <url> Override API URL.
|
|
2036
|
+
--cwd <path> Project directory.
|
|
2037
|
+
--help Show this command help.
|
|
2038
|
+
`;
|
|
2039
|
+
}
|
|
2040
|
+
if (command === "quickstart") {
|
|
2041
|
+
return `prompts-gpt quickstart
|
|
2042
|
+
|
|
2043
|
+
Usage:
|
|
2044
|
+
prompts-gpt quickstart [--json] [--cwd <path>]
|
|
2045
|
+
|
|
2046
|
+
Why use it:
|
|
2047
|
+
Walks through setup in one command — checks credentials, creates config, detects providers,
|
|
2048
|
+
and shows runnable commands. The fastest path from install to first run.
|
|
2049
|
+
|
|
2050
|
+
Options:
|
|
2051
|
+
--json Print machine-readable JSON output.
|
|
2052
|
+
--cwd <path> Project directory.
|
|
782
2053
|
--help Show this command help.
|
|
783
2054
|
`;
|
|
784
2055
|
}
|
|
@@ -801,6 +2072,41 @@ Why use it:
|
|
|
801
2072
|
Shows focused usage for the exact command you are trying to run so shell users do not have to scan the full command list.
|
|
802
2073
|
`;
|
|
803
2074
|
}
|
|
2075
|
+
async function readSweepIterationsFromFrontmatter(filePath) {
|
|
2076
|
+
try {
|
|
2077
|
+
const { readFile: fsRead } = await import("node:fs/promises");
|
|
2078
|
+
const content = await fsRead(filePath, "utf8");
|
|
2079
|
+
const match = content.match(/iterations:\s*(\d+)/i);
|
|
2080
|
+
if (match) {
|
|
2081
|
+
const val = parseInt(match[1], 10);
|
|
2082
|
+
if (val > 0 && val <= 50)
|
|
2083
|
+
return val;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
catch { /* skip */ }
|
|
2087
|
+
return null;
|
|
2088
|
+
}
|
|
2089
|
+
function buildGenerateInput(flags) {
|
|
2090
|
+
return {
|
|
2091
|
+
goal: getStringFlag(flags, "goal") || "",
|
|
2092
|
+
context: sanitizeGenerateInput(getStringFlag(flags, "context") || ""),
|
|
2093
|
+
constraints: sanitizeGenerateInput(getStringFlag(flags, "constraints") || ""),
|
|
2094
|
+
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
2095
|
+
tool: getStringFlag(flags, "tool") || "Codex",
|
|
2096
|
+
mode: getStringFlag(flags, "mode") || "implement",
|
|
2097
|
+
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
2098
|
+
includeWebSearch: Boolean(flags["web-search"]),
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
function sanitizeGenerateInput(value) {
|
|
2102
|
+
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_***");
|
|
2103
|
+
}
|
|
2104
|
+
function printDataTransmissionNotice(command, input) {
|
|
2105
|
+
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.`);
|
|
2106
|
+
console.log("[notice] Do not include PII, secrets, or confidential data in these flags.");
|
|
2107
|
+
console.log(`[notice] No local files or repo content are uploaded. Only the explicit flag values for \`${command}\` are transmitted.`);
|
|
2108
|
+
console.log("");
|
|
2109
|
+
}
|
|
804
2110
|
main().catch((error) => {
|
|
805
2111
|
if (error instanceof CliError) {
|
|
806
2112
|
console.error(error.message);
|
|
@@ -821,9 +2127,55 @@ main().catch((error) => {
|
|
|
821
2127
|
: CLI_EXIT_CODES.general;
|
|
822
2128
|
return;
|
|
823
2129
|
}
|
|
824
|
-
|
|
2130
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2131
|
+
console.error(msg.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
|
|
825
2132
|
process.exitCode = CLI_EXIT_CODES.general;
|
|
826
2133
|
});
|
|
2134
|
+
async function extractRunDiagnostics(logFile, provider, model) {
|
|
2135
|
+
const diagnostics = [];
|
|
2136
|
+
try {
|
|
2137
|
+
const { readFile: fsReadFile } = await import("node:fs/promises");
|
|
2138
|
+
const log = await fsReadFile(logFile, "utf8");
|
|
2139
|
+
const errorLines = log.split("\n").filter((line) => line.startsWith("ERROR:") || line.includes('"error"'));
|
|
2140
|
+
for (const line of errorLines.slice(0, 5)) {
|
|
2141
|
+
if (line.includes("not supported")) {
|
|
2142
|
+
const modelMatch = line.match(/The '([^']+)' model is not supported/);
|
|
2143
|
+
const badModel = modelMatch?.[1] ?? model;
|
|
2144
|
+
diagnostics.push(`Model "${badModel}" is not supported by ${provider} with your account.`);
|
|
2145
|
+
diagnostics.push(`Fix: prompts-gpt run --model o4-mini`);
|
|
2146
|
+
diagnostics.push(`Or: prompts-gpt run --agent claude`);
|
|
2147
|
+
break;
|
|
2148
|
+
}
|
|
2149
|
+
if (line.includes("unauthorized") || line.includes("authentication")) {
|
|
2150
|
+
diagnostics.push(`Authentication failed for ${provider}. Check your ${provider} account login.`);
|
|
2151
|
+
diagnostics.push(`Fix: Run the ${provider} CLI directly to verify auth: ${provider} --version`);
|
|
2152
|
+
break;
|
|
2153
|
+
}
|
|
2154
|
+
if (line.includes("rate_limit") || line.includes("429")) {
|
|
2155
|
+
diagnostics.push(`Rate limited by ${provider}. Wait and try again.`);
|
|
2156
|
+
break;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
if (diagnostics.length === 0 && errorLines.length > 0) {
|
|
2160
|
+
const firstError = errorLines[0].slice(0, 200);
|
|
2161
|
+
diagnostics.push(`Provider error: ${firstError}`);
|
|
2162
|
+
}
|
|
2163
|
+
if (diagnostics.length === 0) {
|
|
2164
|
+
diagnostics.push(`${provider} exited with code 1. Check the log for details:`);
|
|
2165
|
+
diagnostics.push(` cat ${logFile}`);
|
|
2166
|
+
diagnostics.push(`Try a different provider: prompts-gpt run --agent claude`);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
catch {
|
|
2170
|
+
diagnostics.push(`Could not read log file. Check: ${logFile}`);
|
|
2171
|
+
}
|
|
2172
|
+
return diagnostics;
|
|
2173
|
+
}
|
|
2174
|
+
function warnOnConfigIssues(config) {
|
|
2175
|
+
for (const w of config.configWarnings) {
|
|
2176
|
+
console.error(`[config warning] ${w}`);
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
827
2179
|
function formatApiError(error) {
|
|
828
2180
|
const lines = [error.message];
|
|
829
2181
|
for (const [field, messages] of Object.entries(error.fieldErrors ?? {})) {
|
|
@@ -839,4 +2191,21 @@ function formatApiError(error) {
|
|
|
839
2191
|
}
|
|
840
2192
|
return lines.join("\n");
|
|
841
2193
|
}
|
|
2194
|
+
function formatTokenUsage(usage) {
|
|
2195
|
+
const parts = [
|
|
2196
|
+
`total=${usage.totalTokens.toLocaleString()}`,
|
|
2197
|
+
`input=${usage.inputTokens.toLocaleString()}`,
|
|
2198
|
+
`output=${usage.outputTokens.toLocaleString()}`,
|
|
2199
|
+
];
|
|
2200
|
+
if (usage.reasoningTokens > 0) {
|
|
2201
|
+
parts.push(`reasoning=${usage.reasoningTokens.toLocaleString()}`);
|
|
2202
|
+
}
|
|
2203
|
+
if (usage.cacheReadTokens > 0) {
|
|
2204
|
+
parts.push(`cache-read=${usage.cacheReadTokens.toLocaleString()}`);
|
|
2205
|
+
}
|
|
2206
|
+
if (usage.cacheWriteTokens > 0) {
|
|
2207
|
+
parts.push(`cache-write=${usage.cacheWriteTokens.toLocaleString()}`);
|
|
2208
|
+
}
|
|
2209
|
+
return parts.join(" | ");
|
|
2210
|
+
}
|
|
842
2211
|
//# sourceMappingURL=cli.js.map
|