@prompts-gpt/client 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -1
- package/LICENSE +75 -21
- package/README.md +82 -227
- package/dist/cli.js +1635 -142
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +82 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +745 -120
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +205 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1173 -0
- package/dist/runtime.js.map +1 -0
- package/dist/sweep.d.ts +174 -0
- package/dist/sweep.d.ts.map +1 -0
- package/dist/sweep.js +594 -0
- package/dist/sweep.js.map +1 -0
- package/package.json +9 -8
package/dist/cli.js
CHANGED
|
@@ -1,186 +1,1248 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
import { DEFAULT_PROMPTS_GPT_API_URL, DEFAULT_PROMPTS_GPT_OUT_DIR, DEFAULT_RUN_CONFIG_PATH, PROMPTS_GPT_CREDENTIALS_FILE, PromptsGptApiError, PromptsGptClient, doctor, initRunConfig, loadRunConfig, normalizeOrchestrationAgent, ORCHESTRATION_AGENT_PROFILES, runBatch, runPrompt, sweepPrompt, validateRunConfig, discoverWorkspaceAssets, SUPPORTED_AGENT_TARGETS, detectProviders, loadLocalCredentials, saveLocalCredentials, syncPrompts, writeAgentFiles, writePromptManifest, writePromptMarkdownFiles, } from "./index.js";
|
|
6
|
+
const CLI_EXIT_CODES = {
|
|
7
|
+
success: 0,
|
|
8
|
+
general: 1,
|
|
9
|
+
auth: 2,
|
|
10
|
+
validation: 3,
|
|
11
|
+
rateLimit: 4,
|
|
12
|
+
usage: 64,
|
|
13
|
+
};
|
|
4
14
|
const VALID_TOOLS = ["Codex", "Claude Code", "Cursor", "GitHub Copilot", "ChatGPT", "Gemini", "Perplexity", "Grok", "DeepSeek", "Claude"];
|
|
15
|
+
const COMMANDS = ["setup", "init", "project", "pull", "generate", "sync", "run", "run-batch", "sweep", "list", "status", "validate", "providers", "doctor", "load-config", "version", "help"];
|
|
16
|
+
const MAX_STDIN_TOKEN_LENGTH = 4_096;
|
|
17
|
+
class CliError extends Error {
|
|
18
|
+
exitCode;
|
|
19
|
+
helpCommand;
|
|
20
|
+
constructor(message, exitCode, options) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "CliError";
|
|
23
|
+
this.exitCode = exitCode;
|
|
24
|
+
this.helpCommand = options?.helpCommand;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
5
27
|
async function main() {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
28
|
+
const argv = process.argv.slice(2);
|
|
29
|
+
if (argv.length === 0) {
|
|
30
|
+
printHelp();
|
|
31
|
+
console.log("Quick start:");
|
|
32
|
+
console.log(" prompts-gpt status — check workspace readiness");
|
|
33
|
+
console.log(" prompts-gpt list — see available prompts, sweeps, agents");
|
|
34
|
+
console.log(" prompts-gpt help <cmd> — detailed help for a command");
|
|
35
|
+
console.log("");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const first = argv[0];
|
|
39
|
+
if (first === "--help") {
|
|
9
40
|
printHelp();
|
|
10
41
|
return;
|
|
11
42
|
}
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
|
|
43
|
+
if (first === "--version") {
|
|
44
|
+
await printVersion();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (first === "help") {
|
|
48
|
+
handleHelpCommand(argv.slice(1));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (first === "version") {
|
|
52
|
+
if (argv.length > 1) {
|
|
53
|
+
throw new CliError("The `version` command does not accept additional arguments.", CLI_EXIT_CODES.usage, {
|
|
54
|
+
helpCommand: "version",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
await printVersion();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const command = asCommandName(first);
|
|
61
|
+
if (!command) {
|
|
62
|
+
throw new CliError(`Unknown command: ${first}.`, CLI_EXIT_CODES.usage);
|
|
63
|
+
}
|
|
64
|
+
if (!isRunnableCommand(command)) {
|
|
65
|
+
throw new CliError(`Unknown command: ${first}.`, CLI_EXIT_CODES.usage, {
|
|
66
|
+
helpCommand: "help",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const flags = parseCommandFlags(command, argv.slice(1));
|
|
70
|
+
if (Boolean(flags.help)) {
|
|
71
|
+
printHelp(command);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await runCommand(command, flags);
|
|
75
|
+
}
|
|
76
|
+
async function runCommand(command, flags) {
|
|
77
|
+
if (command === "providers") {
|
|
78
|
+
const cwd = getResolvedCwd(flags);
|
|
79
|
+
const providers = await detectProviders(cwd);
|
|
80
|
+
if (Boolean(flags.json)) {
|
|
81
|
+
console.log(JSON.stringify({ cwd, providers }, null, 2));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`Workspace: ${cwd}`);
|
|
85
|
+
for (const provider of providers) {
|
|
86
|
+
console.log(`${provider.provider}: ${provider.available ? "available" : "missing"} | bin=${provider.bin} | model=${provider.modelDefault}${provider.version ? ` | version=${provider.version}` : ""}`);
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (command === "setup") {
|
|
91
|
+
const cwd = getResolvedCwd(flags);
|
|
92
|
+
const providerOrder = getStringFlag(flags, "provider-order")
|
|
93
|
+
?.split(",")
|
|
94
|
+
.map((item) => item.trim())
|
|
95
|
+
.filter(Boolean);
|
|
96
|
+
validateProviderOrderFlag(providerOrder);
|
|
97
|
+
const promptFile = getStringFlag(flags, "prompt-file");
|
|
98
|
+
const promptFiles = getStringFlag(flags, "prompt-files")
|
|
99
|
+
?.split(",")
|
|
100
|
+
.map((item) => item.trim())
|
|
101
|
+
.filter(Boolean);
|
|
102
|
+
const result = await initRunConfig({
|
|
103
|
+
cwd,
|
|
104
|
+
promptFile,
|
|
105
|
+
manifestPath: getStringFlag(flags, "manifest"),
|
|
106
|
+
promptFiles,
|
|
107
|
+
promptDir: getStringFlag(flags, "prompt-dir"),
|
|
108
|
+
defaultAgent: resolveRunAgent(flags, "router"),
|
|
109
|
+
providerOrder,
|
|
110
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
111
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
112
|
+
retryCount: parseNonNegativeIntFlag(getStringFlag(flags, "retry-count"), "retry-count"),
|
|
113
|
+
disallowDestructiveGit: Boolean(flags["allow-destructive-git"]) ? false : true,
|
|
114
|
+
modelOverrides: {
|
|
115
|
+
codex: getStringFlag(flags, "codex-model"),
|
|
116
|
+
cursor: getStringFlag(flags, "cursor-model"),
|
|
117
|
+
claude: getStringFlag(flags, "claude-model"),
|
|
118
|
+
copilot: getStringFlag(flags, "copilot-model"),
|
|
119
|
+
},
|
|
120
|
+
overwrite: Boolean(flags.overwrite),
|
|
121
|
+
});
|
|
122
|
+
if (Boolean(flags.json)) {
|
|
123
|
+
console.log(JSON.stringify(result, null, 2));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log(`Created run config: ${result.configPath}`);
|
|
127
|
+
console.log(`Default agent: ${result.config.defaultAgent ?? "router"}`);
|
|
128
|
+
console.log(`Provider order: ${(result.config.providerOrder ?? []).join(", ")}`);
|
|
129
|
+
if (result.sourceSummary.defaultPromptFile) {
|
|
130
|
+
console.log(`Default prompt file: ${result.sourceSummary.defaultPromptFile}`);
|
|
131
|
+
}
|
|
132
|
+
if (result.sourceSummary.manifestPath) {
|
|
133
|
+
console.log(`Batch default manifest: ${result.sourceSummary.manifestPath}`);
|
|
134
|
+
}
|
|
135
|
+
else if (result.sourceSummary.promptFiles.length > 0) {
|
|
136
|
+
console.log(`Batch default prompt files: ${result.sourceSummary.promptFiles.length}`);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log("Batch default prompt sources: none detected");
|
|
140
|
+
}
|
|
141
|
+
console.log("Detected providers:");
|
|
142
|
+
for (const provider of result.providerSummary) {
|
|
143
|
+
console.log(`- ${provider.provider}: ${provider.available ? "available" : "missing"} | bin=${provider.bin}`);
|
|
144
|
+
}
|
|
145
|
+
console.log("Next steps:");
|
|
146
|
+
console.log(` prompts-gpt run${result.sourceSummary.defaultPromptFile ? "" : " --prompt-file <path>"}`);
|
|
147
|
+
console.log(" prompts-gpt run-batch");
|
|
148
|
+
console.log(" prompts-gpt list — see all runnable assets");
|
|
149
|
+
console.log(" prompts-gpt status — check workspace readiness");
|
|
150
|
+
console.log(" prompts-gpt validate — validate your config");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (command === "doctor") {
|
|
154
|
+
const cwd = getResolvedCwd(flags);
|
|
155
|
+
const report = await doctor(cwd);
|
|
156
|
+
if (Boolean(flags.json)) {
|
|
157
|
+
console.log(JSON.stringify(report, null, 2));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
console.log(`Workspace: ${report.cwd}`);
|
|
161
|
+
console.log(`Node: ${report.nodeVersion} | OS: ${report.osPlatform}/${report.osArch} | CPUs: ${report.cpuCount}`);
|
|
162
|
+
console.log(`Config: ${report.configFound ? "found" : "not found"} (${report.configPath})`);
|
|
163
|
+
for (const provider of report.providers) {
|
|
164
|
+
console.log(`${provider.provider}: ${provider.available ? "available" : "missing"} | bin=${provider.bin}${provider.version ? ` | version=${provider.version}` : ""}`);
|
|
165
|
+
if (!provider.available) {
|
|
166
|
+
console.log(` hint: ${provider.installHint}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const note of report.notes) {
|
|
170
|
+
console.log(`note: ${note}`);
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (command === "list") {
|
|
175
|
+
const cwd = getResolvedCwd(flags);
|
|
176
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
177
|
+
if (Boolean(flags.json)) {
|
|
178
|
+
console.log(JSON.stringify(assets, null, 2));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
console.log(`Workspace: ${cwd}`);
|
|
182
|
+
console.log("");
|
|
183
|
+
if (assets.prompts.length > 0) {
|
|
184
|
+
console.log(`Prompt packs (${assets.prompts.length}):`);
|
|
185
|
+
for (const p of assets.prompts) {
|
|
186
|
+
console.log(` ${p.slug} — ${p.title} [${p.source}]`);
|
|
187
|
+
console.log(` file: .prompts-gpt/${p.file}`);
|
|
188
|
+
console.log(` run: prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
189
|
+
}
|
|
190
|
+
console.log("");
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
console.log("Prompt packs: none found");
|
|
194
|
+
console.log(" Run `prompts-gpt sync` to pull prompt packs, or `prompts-gpt pull` to download them.");
|
|
195
|
+
console.log("");
|
|
196
|
+
}
|
|
197
|
+
if (assets.sweeps.length > 0) {
|
|
198
|
+
console.log(`Sweep prompts (${assets.sweeps.length}):`);
|
|
199
|
+
for (const s of assets.sweeps) {
|
|
200
|
+
console.log(` ${s.name}`);
|
|
201
|
+
console.log(` file: ${s.file}`);
|
|
202
|
+
console.log(` sweep: prompts-gpt sweep --prompt-file ${s.file}`);
|
|
203
|
+
}
|
|
204
|
+
console.log("");
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
console.log("Sweep prompts: none found");
|
|
208
|
+
console.log(" Create .prompts-gpt/sweeps/<name>.md to add sweep prompts.");
|
|
209
|
+
console.log("");
|
|
210
|
+
}
|
|
211
|
+
if (assets.agents.length > 0) {
|
|
212
|
+
console.log(`Agent integrations (${assets.agents.length}):`);
|
|
213
|
+
for (const a of assets.agents) {
|
|
214
|
+
console.log(` ${a.target} — ${a.file}`);
|
|
215
|
+
}
|
|
216
|
+
console.log("");
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
console.log("Agent integrations: none synced");
|
|
220
|
+
console.log(" Run `prompts-gpt sync` to generate agent files.");
|
|
221
|
+
console.log("");
|
|
222
|
+
}
|
|
223
|
+
console.log(`Config: ${assets.configFound ? "found" : "not found — run `prompts-gpt setup`"}`);
|
|
224
|
+
console.log(`Manifest: ${assets.manifestFound ? "found" : "not found — run `prompts-gpt sync`"}`);
|
|
225
|
+
console.log(`Credentials: ${assets.credentialsFound ? "found" : "not found — run `prompts-gpt init --token <token>`"}`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (command === "status") {
|
|
229
|
+
const cwd = getResolvedCwd(flags);
|
|
230
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
231
|
+
const providers = await detectProviders(cwd);
|
|
232
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
233
|
+
if (Boolean(flags.json)) {
|
|
234
|
+
console.log(JSON.stringify({ cwd, assets, providers }, null, 2));
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
console.log(`Workspace: ${cwd}`);
|
|
238
|
+
console.log("");
|
|
239
|
+
console.log("Readiness:");
|
|
240
|
+
console.log(` Credentials: ${assets.credentialsFound ? "✓" : "✗ — run \`prompts-gpt init --token <token>\`"}`);
|
|
241
|
+
console.log(` Config: ${assets.configFound ? "✓" : "✗ — run \`prompts-gpt setup\`"}`);
|
|
242
|
+
console.log(` Manifest: ${assets.manifestFound ? "✓" : "✗ — run \`prompts-gpt sync\`"}`);
|
|
243
|
+
console.log(` Prompts: ${assets.prompts.length > 0 ? `✓ (${assets.prompts.length})` : "✗ — none found"}`);
|
|
244
|
+
console.log(` Sweeps: ${assets.sweeps.length > 0 ? `✓ (${assets.sweeps.length})` : "— none found"}`);
|
|
245
|
+
console.log(` Agents: ${assets.agents.length > 0 ? `✓ (${assets.agents.length} targets)` : "✗ — run \`prompts-gpt sync\`"}`);
|
|
246
|
+
console.log(` Providers: ${availableProviders.length > 0 ? `✓ (${availableProviders.map((p) => p.provider).join(", ")})` : "✗ — no CLI found"}`);
|
|
247
|
+
console.log("");
|
|
248
|
+
if (assets.prompts.length > 0 && availableProviders.length > 0) {
|
|
249
|
+
console.log("Ready to run:");
|
|
250
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${assets.prompts[0].file}`);
|
|
251
|
+
if (assets.sweeps.length > 0) {
|
|
252
|
+
console.log(` prompts-gpt sweep --prompt-file ${assets.sweeps[0].file}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
console.log("Next steps:");
|
|
257
|
+
let step = 1;
|
|
258
|
+
if (!assets.credentialsFound)
|
|
259
|
+
console.log(` ${step++}. prompts-gpt init --token <project-token>`);
|
|
260
|
+
if (assets.prompts.length === 0)
|
|
261
|
+
console.log(` ${step++}. prompts-gpt sync`);
|
|
262
|
+
if (availableProviders.length === 0)
|
|
263
|
+
console.log(` ${step++}. Install a provider CLI (codex, cursor agent, claude, copilot)`);
|
|
264
|
+
if (!assets.configFound)
|
|
265
|
+
console.log(` ${step++}. prompts-gpt setup`);
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (command === "validate") {
|
|
270
|
+
const cwd = getResolvedCwd(flags);
|
|
271
|
+
const result = await validateRunConfig(cwd);
|
|
272
|
+
if (Boolean(flags.json)) {
|
|
273
|
+
console.log(JSON.stringify(result, null, 2));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
console.log(`Config: ${result.configPath}`);
|
|
277
|
+
console.log(`Valid: ${result.valid ? "yes" : "no"}`);
|
|
278
|
+
for (const e of result.errors) {
|
|
279
|
+
console.log(` error: ${e}`);
|
|
280
|
+
}
|
|
281
|
+
for (const w of result.warnings) {
|
|
282
|
+
console.log(` warning: ${w}`);
|
|
283
|
+
}
|
|
284
|
+
if (result.valid && result.errors.length === 0 && result.warnings.length === 0) {
|
|
285
|
+
console.log(" No issues found.");
|
|
286
|
+
}
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (command === "run") {
|
|
290
|
+
const cwd = getResolvedCwd(flags);
|
|
291
|
+
const promptFile = getStringFlag(flags, "prompt-file");
|
|
292
|
+
const config = await loadRunConfig(cwd);
|
|
293
|
+
warnOnConfigIssues(config);
|
|
294
|
+
if (!promptFile && !Boolean(flags.json)) {
|
|
295
|
+
if (!config.defaultPromptFile && config.batchDefaults.promptFiles.length === 0 && !config.batchDefaults.manifestPath) {
|
|
296
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
297
|
+
if (assets.prompts.length > 0 || assets.sweeps.length > 0) {
|
|
298
|
+
console.log("No default prompt file configured. Available options:\n");
|
|
299
|
+
if (assets.prompts.length > 0) {
|
|
300
|
+
console.log("Prompt packs:");
|
|
301
|
+
for (const p of assets.prompts) {
|
|
302
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (assets.sweeps.length > 0) {
|
|
306
|
+
console.log("\nSweep prompts:");
|
|
307
|
+
for (const s of assets.sweeps) {
|
|
308
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
console.log("\nOr set a default: prompts-gpt setup --prompt-file <path>");
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
317
|
+
const result = await runPrompt({
|
|
318
|
+
cwd,
|
|
319
|
+
promptFile,
|
|
320
|
+
agent,
|
|
321
|
+
model: getStringFlag(flags, "model"),
|
|
322
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
323
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
324
|
+
runId: getStringFlag(flags, "run-id"),
|
|
325
|
+
approveMcps: !Boolean(flags["no-approve-mcps"]),
|
|
326
|
+
sandboxMode: getStringFlag(flags, "sandbox"),
|
|
327
|
+
background: Boolean(flags.background),
|
|
328
|
+
permissionMode: getStringFlag(flags, "permission-mode"),
|
|
329
|
+
});
|
|
330
|
+
if (Boolean(flags.json)) {
|
|
331
|
+
console.log(JSON.stringify(result, null, 2));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const agentLabel = getStringFlag(flags, "agent") ? result.provider : `${result.provider} (auto-selected)`;
|
|
335
|
+
console.log(`Run ID: ${result.runId}`);
|
|
336
|
+
console.log(`Provider: ${agentLabel} | Model: ${result.model}`);
|
|
337
|
+
console.log(`Exit code: ${result.exitCode}`);
|
|
338
|
+
console.log(`Duration: ${formatDuration(result.durationMs)}`);
|
|
339
|
+
console.log(`Run dir: ${result.runDir}`);
|
|
340
|
+
console.log(`Summary: ${result.summaryFile}`);
|
|
341
|
+
console.log(`Log: ${result.logFile}`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (command === "run-batch") {
|
|
345
|
+
const cwd = getResolvedCwd(flags);
|
|
346
|
+
const promptFiles = getStringFlag(flags, "prompt-files")
|
|
347
|
+
?.split(",")
|
|
348
|
+
.map((item) => item.trim())
|
|
349
|
+
.filter(Boolean);
|
|
350
|
+
const config = await loadRunConfig(cwd);
|
|
351
|
+
warnOnConfigIssues(config);
|
|
352
|
+
if (!promptFiles && !getStringFlag(flags, "manifest") && !Boolean(flags.json)) {
|
|
353
|
+
if (!config.batchDefaults.manifestPath && config.batchDefaults.promptFiles.length === 0) {
|
|
354
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
355
|
+
if (assets.prompts.length > 0) {
|
|
356
|
+
console.log("No batch source configured. Available prompt packs:\n");
|
|
357
|
+
const fileList = assets.prompts.map((p) => `.prompts-gpt/${p.file}`).join(",");
|
|
358
|
+
console.log(` prompts-gpt run-batch --prompt-files ${fileList}`);
|
|
359
|
+
if (assets.manifestFound) {
|
|
360
|
+
console.log(` prompts-gpt run-batch --manifest .prompts-gpt/manifest.json`);
|
|
361
|
+
}
|
|
362
|
+
console.log("\nOr configure batch defaults: prompts-gpt setup");
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
368
|
+
const result = await runBatch({
|
|
369
|
+
cwd,
|
|
370
|
+
manifestPath: getStringFlag(flags, "manifest"),
|
|
371
|
+
promptFiles,
|
|
372
|
+
agent,
|
|
373
|
+
model: getStringFlag(flags, "model"),
|
|
374
|
+
timeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "timeout"), "timeout"),
|
|
375
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
376
|
+
});
|
|
377
|
+
if (Boolean(flags.json)) {
|
|
378
|
+
console.log(JSON.stringify(result, null, 2));
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
console.log(`Batch complete: total=${result.total} success=${result.success} failed=${result.failed}`);
|
|
382
|
+
for (const [idx, run] of result.results.entries()) {
|
|
383
|
+
const status = run.exitCode === 0 ? "ok" : "FAIL";
|
|
384
|
+
console.log(` [${idx + 1}/${result.total}] ${status} ${path.basename(run.promptFile)} -> ${run.provider} (exit=${run.exitCode}, ${formatDuration(run.durationMs)})`);
|
|
385
|
+
}
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (command === "sweep") {
|
|
389
|
+
const cwd = getResolvedCwd(flags);
|
|
390
|
+
const sweepPromptFile = getStringFlag(flags, "prompt-file");
|
|
391
|
+
const config = await loadRunConfig(cwd);
|
|
392
|
+
warnOnConfigIssues(config);
|
|
393
|
+
if (!sweepPromptFile && !Boolean(flags.json)) {
|
|
394
|
+
if (!config.defaultPromptFile) {
|
|
395
|
+
const assets = await discoverWorkspaceAssets(cwd);
|
|
396
|
+
if (assets.sweeps.length > 0) {
|
|
397
|
+
console.log("No default prompt file configured. Available sweep prompts:\n");
|
|
398
|
+
for (const s of assets.sweeps) {
|
|
399
|
+
console.log(` prompts-gpt sweep --prompt-file ${s.file}`);
|
|
400
|
+
}
|
|
401
|
+
if (assets.prompts.length > 0) {
|
|
402
|
+
console.log("\nOr run a prompt pack instead:");
|
|
403
|
+
for (const p of assets.prompts.slice(0, 3)) {
|
|
404
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${p.file}`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
console.log("\nOr set a default: prompts-gpt setup --prompt-file <path>");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
const agent = resolveRunAgent(flags, config.defaultAgent);
|
|
413
|
+
const onProgress = Boolean(flags.json)
|
|
414
|
+
? undefined
|
|
415
|
+
: (event) => {
|
|
416
|
+
if (event.type === "preflight") {
|
|
417
|
+
const report = JSON.parse(event.message);
|
|
418
|
+
console.log(`[preflight] provider=${report.provider} model=${report.model} branch=${report.gitBranch} dirty=${report.gitDirtyFiles} disk=${report.diskFreeMb}MB iterations=${report.iterations}`);
|
|
419
|
+
console.log(`[preflight] prompt=${report.promptFile}`);
|
|
420
|
+
for (const w of report.warnings)
|
|
421
|
+
console.log(`[preflight] warning: ${w}`);
|
|
422
|
+
}
|
|
423
|
+
else if (event.type === "iteration_start") {
|
|
424
|
+
console.log(`\n--- Iteration ${event.iteration}/${event.total} ---`);
|
|
425
|
+
}
|
|
426
|
+
else if (event.type === "iteration_end") {
|
|
427
|
+
const elapsed = formatDuration(event.durationMs);
|
|
428
|
+
console.log(`--- Iteration ${event.iteration} ${event.status} (${elapsed}) ---`);
|
|
429
|
+
}
|
|
430
|
+
else if (event.type === "attempt_retry") {
|
|
431
|
+
console.log(`[retry] iteration ${event.iteration}, attempt ${event.attempt}/${event.maxAttempts}, backoff ${event.backoffMs}ms`);
|
|
432
|
+
}
|
|
433
|
+
else if (event.type === "summary") {
|
|
434
|
+
const preview = event.lines.slice(0, 5).join("\n");
|
|
435
|
+
console.log(`[summary] iteration ${event.iteration}:\n${preview}${event.lines.length > 5 ? `\n ... (${event.lines.length - 5} more lines)` : ""}`);
|
|
436
|
+
}
|
|
437
|
+
else if (event.type === "sweep_end") {
|
|
438
|
+
console.log(`\nSweep complete: ${event.result.succeeded}/${event.result.totalIterations} succeeded in ${formatDuration(event.result.totalDurationMs)}`);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
const result = await sweepPrompt({
|
|
442
|
+
cwd,
|
|
443
|
+
promptFile: getStringFlag(flags, "prompt-file"),
|
|
444
|
+
agent,
|
|
445
|
+
model: getStringFlag(flags, "model"),
|
|
446
|
+
iterations: parsePositiveIntFlag(getStringFlag(flags, "iterations"), "iterations"),
|
|
447
|
+
iterationTimeoutSeconds: parsePositiveIntFlag(getStringFlag(flags, "iteration-timeout"), "iteration-timeout"),
|
|
448
|
+
maxRetries: parseNonNegativeIntFlag(getStringFlag(flags, "max-retries"), "max-retries"),
|
|
449
|
+
artifactsDir: getStringFlag(flags, "artifacts-dir"),
|
|
450
|
+
runId: getStringFlag(flags, "run-id"),
|
|
451
|
+
approveMcps: !Boolean(flags["no-approve-mcps"]),
|
|
452
|
+
sandboxMode: getStringFlag(flags, "sandbox"),
|
|
453
|
+
phase: getStringFlag(flags, "phase"),
|
|
454
|
+
dryRun: Boolean(flags["dry-run"]),
|
|
455
|
+
maxRunDirs: parsePositiveIntFlag(getStringFlag(flags, "max-run-dirs"), "max-run-dirs"),
|
|
456
|
+
summaryLines: parsePositiveIntFlag(getStringFlag(flags, "summary-lines"), "summary-lines"),
|
|
457
|
+
onProgress,
|
|
458
|
+
});
|
|
459
|
+
if (Boolean(flags.json)) {
|
|
460
|
+
console.log(JSON.stringify(result, null, 2));
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (result.dryRun) {
|
|
464
|
+
console.log("[dry-run] Would execute sweep with:");
|
|
465
|
+
console.log(` Provider: ${result.provider}`);
|
|
466
|
+
console.log(` Model: ${result.model}`);
|
|
467
|
+
console.log(` Iterations: ${result.totalIterations}`);
|
|
468
|
+
console.log(` Prompt: ${result.promptFile}`);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
console.log(`Run ID: ${result.runId}`);
|
|
472
|
+
console.log(`Provider: ${result.provider} | Model: ${result.model}`);
|
|
473
|
+
console.log(`Prompt: ${result.promptFile}`);
|
|
474
|
+
console.log(`Iterations: ${result.succeeded}/${result.totalIterations} succeeded`);
|
|
475
|
+
console.log(`Duration: ${formatDuration(result.totalDurationMs)}`);
|
|
476
|
+
console.log(`Run dir: ${result.runDir}`);
|
|
477
|
+
console.log(`Manifest: ${result.manifestFile}`);
|
|
478
|
+
if (result.failed > 0) {
|
|
479
|
+
process.exitCode = 1;
|
|
480
|
+
}
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
if (command === "load-config") {
|
|
484
|
+
const cwd = getResolvedCwd(flags);
|
|
485
|
+
const client = await createClientForCommand(command, flags);
|
|
486
|
+
const project = await client.getProject();
|
|
487
|
+
const prompts = await client.pullPrompts();
|
|
488
|
+
if (prompts.length === 0) {
|
|
489
|
+
console.log("No prompt packs found in the project library. Configure prompts in Prompts Studio first.");
|
|
490
|
+
console.log(` Open: https://prompts-gpt.com/studio/projects`);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
const result = await syncPrompts(prompts, {
|
|
494
|
+
cwd,
|
|
495
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
496
|
+
overwrite: true,
|
|
497
|
+
agent: getStringFlag(flags, "agent") || "all",
|
|
498
|
+
});
|
|
499
|
+
const providers = await detectProviders(cwd);
|
|
500
|
+
const availableProviders = providers.filter((p) => p.available);
|
|
501
|
+
let configError = null;
|
|
502
|
+
const configResult = await initRunConfig({
|
|
503
|
+
cwd,
|
|
504
|
+
overwrite: true,
|
|
505
|
+
}).catch((err) => {
|
|
506
|
+
configError = err.message;
|
|
507
|
+
return null;
|
|
508
|
+
});
|
|
509
|
+
if (Boolean(flags.json)) {
|
|
510
|
+
console.log(JSON.stringify({
|
|
511
|
+
project: { brandName: project.brandName, websiteUrl: project.websiteUrl },
|
|
512
|
+
synced: { prompts: result.markdown.written.length, agents: result.agents.written.length },
|
|
513
|
+
providers: availableProviders.map((p) => p.provider),
|
|
514
|
+
config: configResult ? "created" : "skipped",
|
|
515
|
+
}, null, 2));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
console.log(`Loaded configuration from Prompts Studio for: ${project.brandName}`);
|
|
519
|
+
console.log(`Synced ${result.markdown.written.length} prompt pack(s) to ${result.markdown.outDir}`);
|
|
520
|
+
console.log(`Synced ${result.agents.written.length} agent file(s): ${result.agents.targets.join(", ")}`);
|
|
521
|
+
console.log(`Manifest: ${result.manifest.manifestPath}`);
|
|
522
|
+
if (configResult) {
|
|
523
|
+
console.log(`Config: ${configResult.configPath}`);
|
|
524
|
+
}
|
|
525
|
+
else if (configError) {
|
|
526
|
+
console.error(`[config] Skipped: ${configError}`);
|
|
527
|
+
}
|
|
528
|
+
if (availableProviders.length > 0 && result.manifest.manifest.prompts.length > 0) {
|
|
529
|
+
const firstFile = result.manifest.manifest.prompts[0]?.file;
|
|
530
|
+
if (firstFile) {
|
|
531
|
+
console.log(`\nReady to run:`);
|
|
532
|
+
console.log(` prompts-gpt run --prompt-file .prompts-gpt/${firstFile}`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
15
535
|
return;
|
|
16
536
|
}
|
|
17
537
|
if (command === "init") {
|
|
18
|
-
const token = flags
|
|
19
|
-
if (!token)
|
|
20
|
-
throw new
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
538
|
+
const token = await resolveTokenInput(flags, { command });
|
|
539
|
+
if (!token) {
|
|
540
|
+
throw new CliError("Run `prompts-gpt init --token <project-token>`, `--token-stdin`, or `--token-prompt`.", CLI_EXIT_CODES.validation, {
|
|
541
|
+
helpCommand: "init",
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
if (token.length > 256) {
|
|
545
|
+
throw new CliError("Token value is invalid or too long.", CLI_EXIT_CODES.validation, {
|
|
546
|
+
helpCommand: "init",
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
if (!token.startsWith("pgpt_")) {
|
|
550
|
+
throw new CliError("Token must start with `pgpt_`. Copy the full token from the Prompts-GPT dashboard.", CLI_EXIT_CODES.validation, {
|
|
551
|
+
helpCommand: "init",
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
const cwd = getResolvedCwd(flags);
|
|
555
|
+
const apiUrlFlag = getStringFlag(flags, "api-url");
|
|
556
|
+
if (apiUrlFlag) {
|
|
557
|
+
try {
|
|
558
|
+
const parsed = new URL(apiUrlFlag);
|
|
559
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
560
|
+
throw new CliError("--api-url must use https or http.", CLI_EXIT_CODES.validation, { helpCommand: "init" });
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
catch (e) {
|
|
564
|
+
if (e instanceof CliError)
|
|
565
|
+
throw e;
|
|
566
|
+
throw new CliError(`--api-url is not a valid URL: ${apiUrlFlag}`, CLI_EXIT_CODES.validation, { helpCommand: "init" });
|
|
567
|
+
}
|
|
568
|
+
}
|
|
25
569
|
const result = await saveLocalCredentials({
|
|
26
570
|
token,
|
|
27
|
-
apiUrl:
|
|
28
|
-
cwd
|
|
571
|
+
apiUrl: apiUrlFlag || DEFAULT_PROMPTS_GPT_API_URL,
|
|
572
|
+
cwd,
|
|
29
573
|
});
|
|
30
574
|
console.log(`Saved Prompts-GPT credentials to ${result.credentialsPath}`);
|
|
31
575
|
console.log("The credentials file is added to .gitignore.");
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
const cwd = flags.cwd || process.cwd();
|
|
35
|
-
const credentials = await loadLocalCredentials(cwd);
|
|
36
|
-
const client = new PromptsGptClient({
|
|
37
|
-
token: flags.token || credentials?.token || "",
|
|
38
|
-
apiUrl: flags.apiUrl || credentials?.apiUrl || DEFAULT_PROMPTS_GPT_API_URL,
|
|
39
|
-
fetch,
|
|
40
|
-
});
|
|
41
|
-
if (command === "project") {
|
|
42
|
-
const project = await client.getProject();
|
|
43
|
-
console.log(`${project.brandName} (${project.websiteUrl})`);
|
|
576
|
+
console.log("Next: prompts-gpt sync");
|
|
44
577
|
return;
|
|
45
578
|
}
|
|
46
579
|
if (command === "pull") {
|
|
47
|
-
const
|
|
580
|
+
const parsedLimit = parseLimitFlag(getStringFlag(flags, "limit"));
|
|
581
|
+
const client = await createClientForCommand(command, flags);
|
|
582
|
+
const prompts = await client.pullPrompts(buildPullQuery(flags, parsedLimit));
|
|
48
583
|
if (prompts.length === 0) {
|
|
49
584
|
console.log("No prompts matched the query. Try different filters or check the project prompt library.");
|
|
50
585
|
return;
|
|
51
586
|
}
|
|
52
587
|
const result = await writePromptMarkdownFiles(prompts, {
|
|
53
|
-
cwd,
|
|
54
|
-
outDir: flags
|
|
588
|
+
cwd: getResolvedCwd(flags),
|
|
589
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
55
590
|
overwrite: Boolean(flags.overwrite),
|
|
56
591
|
});
|
|
57
592
|
console.log(`Wrote ${result.written.length} prompt file(s) to ${result.outDir}.`);
|
|
58
|
-
if (result.skipped.length)
|
|
593
|
+
if (result.skipped.length) {
|
|
59
594
|
console.log(`Skipped ${result.skipped.length} existing file(s). Use --overwrite to replace them.`);
|
|
595
|
+
}
|
|
60
596
|
return;
|
|
61
597
|
}
|
|
62
598
|
if (command === "generate") {
|
|
63
|
-
validateToolFlag(flags
|
|
64
|
-
const
|
|
599
|
+
validateToolFlag(getStringFlag(flags, "tool"));
|
|
600
|
+
const goal = getStringFlag(flags, "goal");
|
|
601
|
+
if (!goal) {
|
|
602
|
+
throw new CliError("Prompt generation requires `--goal`.", CLI_EXIT_CODES.validation, {
|
|
603
|
+
helpCommand: "generate",
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
validateAgentFlag(getStringFlag(flags, "agent"));
|
|
607
|
+
const client = await createClientForCommand(command, flags);
|
|
608
|
+
const prompt = await client.generatePrompt({
|
|
609
|
+
goal,
|
|
610
|
+
context: getStringFlag(flags, "context") || "",
|
|
611
|
+
constraints: getStringFlag(flags, "constraints") || "",
|
|
612
|
+
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
613
|
+
tool: getStringFlag(flags, "tool") || "Codex",
|
|
614
|
+
mode: getStringFlag(flags, "mode") || "implement",
|
|
615
|
+
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
616
|
+
includeWebSearch: Boolean(flags["web-search"]),
|
|
617
|
+
});
|
|
618
|
+
const cwd = getResolvedCwd(flags);
|
|
65
619
|
const result = await writePromptMarkdownFiles([prompt], {
|
|
66
620
|
cwd,
|
|
67
|
-
outDir: flags
|
|
621
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
68
622
|
overwrite: Boolean(flags.overwrite),
|
|
69
623
|
});
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
const
|
|
624
|
+
const shouldSyncAgents = Boolean(flags["sync-agents"]) || typeof getStringFlag(flags, "agent") === "string";
|
|
625
|
+
if (shouldSyncAgents) {
|
|
626
|
+
const target = getStringFlag(flags, "agent") || "all";
|
|
627
|
+
const pulled = await client.pullPrompts().catch(() => []);
|
|
628
|
+
const syncedPrompts = mergePromptPacks([prompt, ...pulled]);
|
|
629
|
+
const agentResult = await writeAgentFiles(syncedPrompts, {
|
|
73
630
|
cwd,
|
|
74
|
-
agent:
|
|
631
|
+
agent: target,
|
|
75
632
|
overwriteAgentFiles: true,
|
|
76
633
|
});
|
|
634
|
+
const manifestResult = await writePromptManifest(syncedPrompts, {
|
|
635
|
+
cwd,
|
|
636
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
637
|
+
});
|
|
77
638
|
console.log(`Synced ${agentResult.written.length} agent file(s) for ${agentResult.targets.join(", ")}.`);
|
|
639
|
+
console.log(`Updated manifest: ${manifestResult.manifestPath}`);
|
|
78
640
|
}
|
|
79
641
|
console.log(`Generated: ${prompt.title}`);
|
|
80
642
|
console.log(`Wrote to ${result.written[0] ?? result.outDir}.`);
|
|
81
|
-
if (result.skipped.length)
|
|
643
|
+
if (result.skipped.length) {
|
|
82
644
|
console.log("Skipped existing generated prompt. Use --overwrite to replace it.");
|
|
645
|
+
}
|
|
83
646
|
return;
|
|
84
647
|
}
|
|
85
648
|
if (command === "sync") {
|
|
86
|
-
validateToolFlag(flags
|
|
649
|
+
validateToolFlag(getStringFlag(flags, "tool"));
|
|
650
|
+
validateAgentFlag(getStringFlag(flags, "agent"));
|
|
651
|
+
const parsedLimit = parseLimitFlag(getStringFlag(flags, "limit"));
|
|
87
652
|
const prompts = [];
|
|
88
|
-
|
|
89
|
-
|
|
653
|
+
const goal = getStringFlag(flags, "goal");
|
|
654
|
+
const generatedOnly = Boolean(flags["generated-only"]);
|
|
655
|
+
const client = await createClientForCommand(command, flags);
|
|
656
|
+
if (goal) {
|
|
657
|
+
prompts.push(await client.generatePrompt({
|
|
658
|
+
goal,
|
|
659
|
+
context: getStringFlag(flags, "context") || "",
|
|
660
|
+
constraints: getStringFlag(flags, "constraints") || "",
|
|
661
|
+
desiredOutput: getStringFlag(flags, "desired-output") || "A reusable prompt pack saved as Markdown.",
|
|
662
|
+
tool: getStringFlag(flags, "tool") || "Codex",
|
|
663
|
+
mode: getStringFlag(flags, "mode") || "implement",
|
|
664
|
+
artifactType: getStringFlag(flags, "artifact-type") || "prompt-file",
|
|
665
|
+
includeWebSearch: Boolean(flags["web-search"]),
|
|
666
|
+
}));
|
|
90
667
|
}
|
|
91
|
-
if (!
|
|
92
|
-
prompts.push(...await client.pullPrompts(buildPullQuery(flags)));
|
|
668
|
+
if (!generatedOnly) {
|
|
669
|
+
prompts.push(...await client.pullPrompts(buildPullQuery(flags, parsedLimit)));
|
|
670
|
+
}
|
|
671
|
+
if (prompts.length === 0) {
|
|
672
|
+
throw new CliError("No prompts to sync. Provide `--goal` or remove `--generated-only`.", CLI_EXIT_CODES.validation, {
|
|
673
|
+
helpCommand: "sync",
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
if (Boolean(flags["dry-run"])) {
|
|
677
|
+
console.log(`[dry-run] Would sync ${prompts.length} prompt(s) for agent target: ${getStringFlag(flags, "agent") || "all"}.`);
|
|
678
|
+
for (const p of prompts)
|
|
679
|
+
console.log(` - ${p.title} (${p.source})`);
|
|
680
|
+
return;
|
|
93
681
|
}
|
|
94
|
-
if (prompts.length === 0)
|
|
95
|
-
throw new Error("No prompts to sync. Provide --goal or remove --generated-only.");
|
|
96
682
|
const result = await syncPrompts(prompts, {
|
|
97
|
-
cwd,
|
|
98
|
-
outDir: flags
|
|
683
|
+
cwd: getResolvedCwd(flags),
|
|
684
|
+
outDir: getStringFlag(flags, "out") || DEFAULT_PROMPTS_GPT_OUT_DIR,
|
|
99
685
|
overwrite: Boolean(flags.overwrite),
|
|
100
|
-
agent: flags
|
|
686
|
+
agent: getStringFlag(flags, "agent") || "all",
|
|
101
687
|
});
|
|
102
|
-
console.log(`Synced ${result.markdown.written.length}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
688
|
+
console.log(`Synced ${result.markdown.written.length} new prompt file(s) to ${result.markdown.outDir}.`);
|
|
689
|
+
if (result.markdown.skipped.length) {
|
|
690
|
+
console.log(`Kept ${result.markdown.skipped.length} existing file(s) unchanged. Use --overwrite to replace.`);
|
|
691
|
+
}
|
|
692
|
+
console.log(`Synced ${result.agents.written.length} agent file(s): ${result.agents.targets.join(", ")}.`);
|
|
693
|
+
console.log(`Manifest: ${result.manifest.manifestPath}`);
|
|
107
694
|
return;
|
|
108
695
|
}
|
|
109
|
-
if (command === "
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
696
|
+
if (command === "project") {
|
|
697
|
+
const clientOptions = await resolveClientOptions(command, flags);
|
|
698
|
+
const client = new PromptsGptClient(clientOptions);
|
|
699
|
+
const project = await client.getProject();
|
|
700
|
+
const apiUrl = clientOptions.apiUrl;
|
|
701
|
+
if (Boolean(flags.json)) {
|
|
702
|
+
console.log(JSON.stringify({
|
|
703
|
+
project,
|
|
704
|
+
apiUrl,
|
|
705
|
+
}, null, 2));
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
console.log(`Project: ${project.brandName}`);
|
|
709
|
+
console.log(`Website: ${project.websiteUrl}`);
|
|
710
|
+
console.log(`Industry: ${project.industryCategory}`);
|
|
711
|
+
console.log(`Language: ${project.targetLanguage}`);
|
|
712
|
+
console.log(`Countries: ${formatList(project.targetCountries)}`);
|
|
713
|
+
console.log(`Aliases: ${formatList(project.brandAliases)}`);
|
|
714
|
+
console.log(`Keywords: ${formatList(project.productKeywords)}`);
|
|
715
|
+
console.log(`Personas: ${formatList(project.targetPersonas)}`);
|
|
716
|
+
console.log(`Competitors: ${formatCompetitors(project.competitors)}`);
|
|
717
|
+
console.log(`API URL: ${apiUrl}`);
|
|
117
718
|
return;
|
|
118
719
|
}
|
|
119
|
-
throw new Error(`Unknown command: ${command}. Run \`prompts-gpt help\` for usage.`);
|
|
120
720
|
}
|
|
121
|
-
function
|
|
721
|
+
async function createClientForCommand(command, flags) {
|
|
722
|
+
return new PromptsGptClient(await resolveClientOptions(command, flags));
|
|
723
|
+
}
|
|
724
|
+
async function resolveClientOptions(command, flags) {
|
|
725
|
+
const cwd = getResolvedCwd(flags);
|
|
726
|
+
const explicitToken = await resolveTokenInput(flags, { command });
|
|
727
|
+
const explicitApiUrl = getStringFlag(flags, "api-url");
|
|
728
|
+
const credentialsPath = path.resolve(cwd, DEFAULT_PROMPTS_GPT_OUT_DIR, PROMPTS_GPT_CREDENTIALS_FILE);
|
|
729
|
+
const hasCredentialsFile = existsSync(credentialsPath);
|
|
730
|
+
const credentials = await loadLocalCredentials(cwd);
|
|
731
|
+
if (hasCredentialsFile && !credentials && !explicitToken) {
|
|
732
|
+
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 });
|
|
733
|
+
}
|
|
734
|
+
const token = explicitToken || credentials?.token || "";
|
|
735
|
+
if (!token && !process.stdin.isTTY) {
|
|
736
|
+
// CI fallback — never read process.env in the importable SDK, only in the CLI entrypoint
|
|
737
|
+
const envToken = process.env.PROMPTS_GPT_TOKEN?.trim();
|
|
738
|
+
if (envToken) {
|
|
739
|
+
return {
|
|
740
|
+
token: envToken,
|
|
741
|
+
apiUrl: explicitApiUrl || credentials?.apiUrl || DEFAULT_PROMPTS_GPT_API_URL,
|
|
742
|
+
fetch,
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (!token) {
|
|
747
|
+
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.", CLI_EXIT_CODES.auth, { helpCommand: command });
|
|
748
|
+
}
|
|
122
749
|
return {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
750
|
+
token,
|
|
751
|
+
apiUrl: explicitApiUrl || credentials?.apiUrl || DEFAULT_PROMPTS_GPT_API_URL,
|
|
752
|
+
fetch,
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
function buildPullQuery(flags, limit) {
|
|
756
|
+
return {
|
|
757
|
+
q: getStringFlag(flags, "query") || getStringFlag(flags, "q"),
|
|
758
|
+
category: getStringFlag(flags, "category"),
|
|
759
|
+
tool: getStringFlag(flags, "tool"),
|
|
760
|
+
outputType: getStringFlag(flags, "output-type"),
|
|
761
|
+
limit,
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
function parseCommandFlags(command, argv) {
|
|
765
|
+
const options = getCommandOptions(command);
|
|
766
|
+
try {
|
|
767
|
+
const result = parseArgs({
|
|
768
|
+
args: argv,
|
|
769
|
+
options,
|
|
770
|
+
allowPositionals: false,
|
|
771
|
+
strict: true,
|
|
772
|
+
});
|
|
773
|
+
const values = result.values;
|
|
774
|
+
validateFlagConflicts(command, values);
|
|
775
|
+
return values;
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
throw toCliParseError(error, command);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function handleHelpCommand(argv) {
|
|
782
|
+
try {
|
|
783
|
+
const { positionals, values } = parseArgs({
|
|
784
|
+
args: argv,
|
|
785
|
+
options: { help: { type: "boolean" } },
|
|
786
|
+
allowPositionals: true,
|
|
787
|
+
strict: true,
|
|
788
|
+
});
|
|
789
|
+
if (values.help) {
|
|
790
|
+
printHelp();
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (positionals.length > 1) {
|
|
794
|
+
throw new CliError("The `help` command accepts at most one command name.", CLI_EXIT_CODES.usage, {
|
|
795
|
+
helpCommand: "help",
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
if (positionals.length === 0) {
|
|
799
|
+
printHelp();
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const topic = asCommandName(positionals[0]);
|
|
803
|
+
if (!topic) {
|
|
804
|
+
throw new CliError(`Unknown help topic: ${positionals[0]}.`, CLI_EXIT_CODES.usage, {
|
|
805
|
+
helpCommand: "help",
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
printHelp(topic);
|
|
809
|
+
}
|
|
810
|
+
catch (error) {
|
|
811
|
+
if (error instanceof CliError)
|
|
812
|
+
throw error;
|
|
813
|
+
throw toCliParseError(error, "help");
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function getCommandOptions(command) {
|
|
817
|
+
const common = {
|
|
818
|
+
help: { type: "boolean" },
|
|
819
|
+
token: { type: "string" },
|
|
820
|
+
"token-stdin": { type: "boolean" },
|
|
821
|
+
"token-prompt": { type: "boolean" },
|
|
822
|
+
"api-url": { type: "string" },
|
|
823
|
+
cwd: { type: "string" },
|
|
128
824
|
};
|
|
825
|
+
if (command === "init") {
|
|
826
|
+
return common;
|
|
827
|
+
}
|
|
828
|
+
if (command === "setup") {
|
|
829
|
+
return {
|
|
830
|
+
help: { type: "boolean" },
|
|
831
|
+
cwd: { type: "string" },
|
|
832
|
+
json: { type: "boolean" },
|
|
833
|
+
overwrite: { type: "boolean" },
|
|
834
|
+
"prompt-file": { type: "string" },
|
|
835
|
+
"prompt-dir": { type: "string" },
|
|
836
|
+
manifest: { type: "string" },
|
|
837
|
+
"prompt-files": { type: "string" },
|
|
838
|
+
agent: { type: "string" },
|
|
839
|
+
"provider-order": { type: "string" },
|
|
840
|
+
timeout: { type: "string" },
|
|
841
|
+
"retry-count": { type: "string" },
|
|
842
|
+
"artifacts-dir": { type: "string" },
|
|
843
|
+
"allow-destructive-git": { type: "boolean" },
|
|
844
|
+
"codex-model": { type: "string" },
|
|
845
|
+
"cursor-model": { type: "string" },
|
|
846
|
+
"claude-model": { type: "string" },
|
|
847
|
+
"copilot-model": { type: "string" },
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
if (command === "project") {
|
|
851
|
+
return {
|
|
852
|
+
...common,
|
|
853
|
+
json: { type: "boolean" },
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
if (command === "pull") {
|
|
857
|
+
return {
|
|
858
|
+
...common,
|
|
859
|
+
query: { type: "string" },
|
|
860
|
+
q: { type: "string" },
|
|
861
|
+
category: { type: "string" },
|
|
862
|
+
tool: { type: "string" },
|
|
863
|
+
"output-type": { type: "string" },
|
|
864
|
+
limit: { type: "string" },
|
|
865
|
+
out: { type: "string" },
|
|
866
|
+
overwrite: { type: "boolean" },
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
if (command === "generate") {
|
|
870
|
+
return {
|
|
871
|
+
...common,
|
|
872
|
+
goal: { type: "string" },
|
|
873
|
+
context: { type: "string" },
|
|
874
|
+
constraints: { type: "string" },
|
|
875
|
+
"desired-output": { type: "string" },
|
|
876
|
+
tool: { type: "string" },
|
|
877
|
+
mode: { type: "string" },
|
|
878
|
+
"artifact-type": { type: "string" },
|
|
879
|
+
"web-search": { type: "boolean" },
|
|
880
|
+
out: { type: "string" },
|
|
881
|
+
overwrite: { type: "boolean" },
|
|
882
|
+
agent: { type: "string" },
|
|
883
|
+
"sync-agents": { type: "boolean" },
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
if (command === "sync") {
|
|
887
|
+
return {
|
|
888
|
+
...common,
|
|
889
|
+
goal: { type: "string" },
|
|
890
|
+
context: { type: "string" },
|
|
891
|
+
constraints: { type: "string" },
|
|
892
|
+
"desired-output": { type: "string" },
|
|
893
|
+
tool: { type: "string" },
|
|
894
|
+
mode: { type: "string" },
|
|
895
|
+
"artifact-type": { type: "string" },
|
|
896
|
+
"web-search": { type: "boolean" },
|
|
897
|
+
query: { type: "string" },
|
|
898
|
+
q: { type: "string" },
|
|
899
|
+
category: { type: "string" },
|
|
900
|
+
"output-type": { type: "string" },
|
|
901
|
+
limit: { type: "string" },
|
|
902
|
+
out: { type: "string" },
|
|
903
|
+
overwrite: { type: "boolean" },
|
|
904
|
+
agent: { type: "string" },
|
|
905
|
+
"generated-only": { type: "boolean" },
|
|
906
|
+
"dry-run": { type: "boolean" },
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
if (command === "run") {
|
|
910
|
+
return {
|
|
911
|
+
help: { type: "boolean" },
|
|
912
|
+
cwd: { type: "string" },
|
|
913
|
+
json: { type: "boolean" },
|
|
914
|
+
"prompt-file": { type: "string" },
|
|
915
|
+
agent: { type: "string" },
|
|
916
|
+
model: { type: "string" },
|
|
917
|
+
timeout: { type: "string" },
|
|
918
|
+
"artifacts-dir": { type: "string" },
|
|
919
|
+
"run-id": { type: "string" },
|
|
920
|
+
sandbox: { type: "string" },
|
|
921
|
+
"no-approve-mcps": { type: "boolean" },
|
|
922
|
+
background: { type: "boolean" },
|
|
923
|
+
"permission-mode": { type: "string" },
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
if (command === "sweep") {
|
|
927
|
+
return {
|
|
928
|
+
help: { type: "boolean" },
|
|
929
|
+
cwd: { type: "string" },
|
|
930
|
+
json: { type: "boolean" },
|
|
931
|
+
"prompt-file": { type: "string" },
|
|
932
|
+
agent: { type: "string" },
|
|
933
|
+
model: { type: "string" },
|
|
934
|
+
iterations: { type: "string" },
|
|
935
|
+
"iteration-timeout": { type: "string" },
|
|
936
|
+
"max-retries": { type: "string" },
|
|
937
|
+
"artifacts-dir": { type: "string" },
|
|
938
|
+
"run-id": { type: "string" },
|
|
939
|
+
sandbox: { type: "string" },
|
|
940
|
+
"no-approve-mcps": { type: "boolean" },
|
|
941
|
+
phase: { type: "string" },
|
|
942
|
+
"dry-run": { type: "boolean" },
|
|
943
|
+
"max-run-dirs": { type: "string" },
|
|
944
|
+
"summary-lines": { type: "string" },
|
|
945
|
+
background: { type: "boolean" },
|
|
946
|
+
"permission-mode": { type: "string" },
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
if (command === "run-batch") {
|
|
950
|
+
return {
|
|
951
|
+
help: { type: "boolean" },
|
|
952
|
+
cwd: { type: "string" },
|
|
953
|
+
json: { type: "boolean" },
|
|
954
|
+
manifest: { type: "string" },
|
|
955
|
+
"prompt-files": { type: "string" },
|
|
956
|
+
agent: { type: "string" },
|
|
957
|
+
model: { type: "string" },
|
|
958
|
+
timeout: { type: "string" },
|
|
959
|
+
"artifacts-dir": { type: "string" },
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
if (command === "load-config") {
|
|
963
|
+
return {
|
|
964
|
+
...common,
|
|
965
|
+
json: { type: "boolean" },
|
|
966
|
+
out: { type: "string" },
|
|
967
|
+
agent: { type: "string" },
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
if (command === "list" || command === "status" || command === "validate" || command === "providers" || command === "doctor") {
|
|
971
|
+
return {
|
|
972
|
+
help: { type: "boolean" },
|
|
973
|
+
cwd: { type: "string" },
|
|
974
|
+
json: { type: "boolean" },
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
throw new CliError(`Unsupported command: ${command}.`, CLI_EXIT_CODES.usage, {
|
|
978
|
+
helpCommand: "help",
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
function toCliParseError(error, command) {
|
|
982
|
+
const message = normalizeParseErrorMessage(error instanceof Error ? error.message : String(error));
|
|
983
|
+
return new CliError(message, CLI_EXIT_CODES.usage, {
|
|
984
|
+
helpCommand: command,
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
function normalizeParseErrorMessage(message) {
|
|
988
|
+
const trimmed = message.trim();
|
|
989
|
+
if (trimmed.startsWith("Unknown option")) {
|
|
990
|
+
return `${trimmed}.`;
|
|
991
|
+
}
|
|
992
|
+
return trimmed;
|
|
993
|
+
}
|
|
994
|
+
function validateFlagConflicts(command, flags) {
|
|
995
|
+
const tokenSourceCount = [Boolean(flags.token), Boolean(flags["token-stdin"]), Boolean(flags["token-prompt"])].filter(Boolean).length;
|
|
996
|
+
if (tokenSourceCount > 1) {
|
|
997
|
+
throw new CliError("Use only one token source: `--token`, `--token-stdin`, or `--token-prompt`.", CLI_EXIT_CODES.usage, {
|
|
998
|
+
helpCommand: command,
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
if (flags.query && flags.q) {
|
|
1002
|
+
throw new CliError("Use either `--query` or `--q`, not both.", CLI_EXIT_CODES.usage, {
|
|
1003
|
+
helpCommand: command,
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
const promptSourceCount = [
|
|
1007
|
+
Boolean(flags["prompt-file"]),
|
|
1008
|
+
Boolean(flags["prompt-files"]),
|
|
1009
|
+
Boolean(flags.manifest),
|
|
1010
|
+
Boolean(flags["prompt-dir"]),
|
|
1011
|
+
].filter(Boolean).length;
|
|
1012
|
+
if (command === "setup" && promptSourceCount > 1) {
|
|
1013
|
+
throw new CliError("Use only one prompt source for `setup`: `--prompt-file`, `--prompt-files`, `--manifest`, or `--prompt-dir`.", CLI_EXIT_CODES.usage, {
|
|
1014
|
+
helpCommand: command,
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
if (command === "run-batch" && Boolean(flags["prompt-files"]) && Boolean(flags.manifest)) {
|
|
1018
|
+
throw new CliError("Use either `--prompt-files` or `--manifest`, not both.", CLI_EXIT_CODES.usage, {
|
|
1019
|
+
helpCommand: command,
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
async function resolveTokenInput(flags, options) {
|
|
1024
|
+
const explicitToken = getStringFlag(flags, "token")?.trim();
|
|
1025
|
+
if (explicitToken) {
|
|
1026
|
+
return explicitToken;
|
|
1027
|
+
}
|
|
1028
|
+
if (flags["token-stdin"]) {
|
|
1029
|
+
const token = await readTokenFromStdin();
|
|
1030
|
+
if (!token) {
|
|
1031
|
+
throw new CliError("No token was received on stdin. Pipe a project token into `--token-stdin`.", CLI_EXIT_CODES.validation, {
|
|
1032
|
+
helpCommand: options.command,
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
return token;
|
|
1036
|
+
}
|
|
1037
|
+
if (flags["token-prompt"]) {
|
|
1038
|
+
return readTokenFromPrompt(options.command);
|
|
1039
|
+
}
|
|
1040
|
+
return undefined;
|
|
1041
|
+
}
|
|
1042
|
+
async function readTokenFromStdin() {
|
|
1043
|
+
if (process.stdin.isTTY) {
|
|
1044
|
+
throw new CliError("`--token-stdin` expects piped input. Use `--token-prompt` for an interactive terminal.", CLI_EXIT_CODES.usage);
|
|
1045
|
+
}
|
|
1046
|
+
const chunks = [];
|
|
1047
|
+
let totalLength = 0;
|
|
1048
|
+
for await (const chunk of process.stdin) {
|
|
1049
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
1050
|
+
totalLength += buffer.length;
|
|
1051
|
+
if (totalLength > MAX_STDIN_TOKEN_LENGTH) {
|
|
1052
|
+
throw new CliError("Token input from stdin is too long.", CLI_EXIT_CODES.validation);
|
|
1053
|
+
}
|
|
1054
|
+
chunks.push(buffer);
|
|
1055
|
+
}
|
|
1056
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
1057
|
+
}
|
|
1058
|
+
function readTokenFromPrompt(command) {
|
|
1059
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1060
|
+
throw new CliError("`--token-prompt` requires an interactive terminal. Use `--token-stdin` for CI or piped input.", CLI_EXIT_CODES.usage, {
|
|
1061
|
+
helpCommand: command,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
return new Promise((resolve, reject) => {
|
|
1065
|
+
const stdin = process.stdin;
|
|
1066
|
+
const stdout = process.stdout;
|
|
1067
|
+
const buf = Buffer.alloc(MAX_STDIN_TOKEN_LENGTH);
|
|
1068
|
+
let bufLen = 0;
|
|
1069
|
+
const cleanup = () => {
|
|
1070
|
+
stdin.removeListener("data", onData);
|
|
1071
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
1072
|
+
process.removeListener("SIGINT", onSigint);
|
|
1073
|
+
stdin.setRawMode?.(false);
|
|
1074
|
+
stdin.pause();
|
|
1075
|
+
};
|
|
1076
|
+
const extractAndWipe = () => {
|
|
1077
|
+
const result = buf.toString("utf8", 0, bufLen).trim();
|
|
1078
|
+
buf.fill(0, 0, bufLen);
|
|
1079
|
+
bufLen = 0;
|
|
1080
|
+
return result;
|
|
1081
|
+
};
|
|
1082
|
+
const finish = (callback) => {
|
|
1083
|
+
stdout.write("\n");
|
|
1084
|
+
cleanup();
|
|
1085
|
+
callback();
|
|
1086
|
+
};
|
|
1087
|
+
const onSigterm = () => {
|
|
1088
|
+
buf.fill(0, 0, bufLen);
|
|
1089
|
+
cleanup();
|
|
1090
|
+
process.exit(130);
|
|
1091
|
+
};
|
|
1092
|
+
const onSigint = () => {
|
|
1093
|
+
buf.fill(0, 0, bufLen);
|
|
1094
|
+
cleanup();
|
|
1095
|
+
process.exit(130);
|
|
1096
|
+
};
|
|
1097
|
+
process.on("SIGTERM", onSigterm);
|
|
1098
|
+
process.on("SIGINT", onSigint);
|
|
1099
|
+
const onData = (chunk) => {
|
|
1100
|
+
const value = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
1101
|
+
for (const char of value) {
|
|
1102
|
+
if (char === "\u0003") {
|
|
1103
|
+
buf.fill(0, 0, bufLen);
|
|
1104
|
+
finish(() => reject(new CliError("Token entry cancelled.", CLI_EXIT_CODES.general, { helpCommand: command })));
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
if (char === "\r" || char === "\n") {
|
|
1108
|
+
const trimmed = extractAndWipe();
|
|
1109
|
+
if (!trimmed) {
|
|
1110
|
+
finish(() => reject(new CliError("Project token is required.", CLI_EXIT_CODES.validation, { helpCommand: command })));
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
finish(() => resolve(trimmed));
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
if (char === "\u007f" || char === "\b") {
|
|
1117
|
+
if (bufLen > 0) {
|
|
1118
|
+
bufLen--;
|
|
1119
|
+
buf[bufLen] = 0;
|
|
1120
|
+
}
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
if (char >= " ") {
|
|
1124
|
+
const charBytes = Buffer.byteLength(char, "utf8");
|
|
1125
|
+
if (bufLen + charBytes > MAX_STDIN_TOKEN_LENGTH) {
|
|
1126
|
+
buf.fill(0, 0, bufLen);
|
|
1127
|
+
finish(() => reject(new CliError("Token input is too long.", CLI_EXIT_CODES.validation, { helpCommand: command })));
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
buf.write(char, bufLen, "utf8");
|
|
1131
|
+
bufLen += charBytes;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
stdout.write("Project token: ");
|
|
1136
|
+
stdin.setEncoding("utf8");
|
|
1137
|
+
try {
|
|
1138
|
+
stdin.setRawMode?.(true);
|
|
1139
|
+
}
|
|
1140
|
+
catch {
|
|
1141
|
+
reject(new CliError("Cannot enable raw mode for token prompt. Use --token-stdin instead.", CLI_EXIT_CODES.usage, { helpCommand: command }));
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
stdin.resume();
|
|
1145
|
+
stdin.on("data", onData);
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
function parseLimitFlag(raw) {
|
|
1149
|
+
if (raw === undefined)
|
|
1150
|
+
return undefined;
|
|
1151
|
+
if (!/^\d+$/.test(raw)) {
|
|
1152
|
+
throw new CliError("`--limit` must be a positive integer between 1 and 100.", CLI_EXIT_CODES.validation);
|
|
1153
|
+
}
|
|
1154
|
+
const value = Number.parseInt(raw, 10);
|
|
1155
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 100) {
|
|
1156
|
+
throw new CliError("`--limit` must be a positive integer between 1 and 100.", CLI_EXIT_CODES.validation);
|
|
1157
|
+
}
|
|
1158
|
+
return value;
|
|
129
1159
|
}
|
|
130
1160
|
function validateToolFlag(tool) {
|
|
131
1161
|
if (!tool)
|
|
132
1162
|
return;
|
|
133
1163
|
const validSet = new Set(VALID_TOOLS);
|
|
134
1164
|
if (!validSet.has(tool)) {
|
|
135
|
-
throw new
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
1165
|
+
throw new CliError(`Invalid --tool "${tool}". Valid tools: ${VALID_TOOLS.join(", ")}.`, CLI_EXIT_CODES.validation);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
function validateAgentFlag(agent) {
|
|
1169
|
+
if (!agent)
|
|
1170
|
+
return;
|
|
1171
|
+
const targets = agent.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean);
|
|
1172
|
+
const validSet = new Set([...SUPPORTED_AGENT_TARGETS, "all"]);
|
|
1173
|
+
const invalid = [...new Set(targets.filter((target) => !validSet.has(target)))];
|
|
1174
|
+
if (invalid.length) {
|
|
1175
|
+
throw new CliError(`Invalid --agent target: ${invalid.join(", ")}. Use ${SUPPORTED_AGENT_TARGETS.join(", ")}, or all.`, CLI_EXIT_CODES.validation);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
function validateProviderOrderFlag(values) {
|
|
1179
|
+
if (!values?.length)
|
|
1180
|
+
return;
|
|
1181
|
+
const invalid = values.filter((value) => {
|
|
1182
|
+
const raw = value.trim().toLowerCase();
|
|
1183
|
+
const normalized = normalizeOrchestrationAgent(raw);
|
|
1184
|
+
return !raw || normalized === "router";
|
|
151
1185
|
});
|
|
1186
|
+
if (invalid.length > 0) {
|
|
1187
|
+
throw new CliError(`Invalid --provider-order value: ${invalid.join(", ")}. Use codex, cursor, claude, or copilot.`, CLI_EXIT_CODES.validation);
|
|
1188
|
+
}
|
|
152
1189
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
1190
|
+
function getResolvedCwd(flags) {
|
|
1191
|
+
return path.resolve(getStringFlag(flags, "cwd") || process.cwd());
|
|
1192
|
+
}
|
|
1193
|
+
function getStringFlag(flags, name) {
|
|
1194
|
+
const value = flags[name];
|
|
1195
|
+
return typeof value === "string" ? value : undefined;
|
|
1196
|
+
}
|
|
1197
|
+
function formatDuration(ms) {
|
|
1198
|
+
if (ms < 1000)
|
|
1199
|
+
return `${ms}ms`;
|
|
1200
|
+
const totalSeconds = Math.round(ms / 1000);
|
|
1201
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
1202
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
1203
|
+
const seconds = totalSeconds % 60;
|
|
1204
|
+
if (hours > 0)
|
|
1205
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
1206
|
+
if (minutes > 0)
|
|
1207
|
+
return `${minutes}m ${seconds}s`;
|
|
1208
|
+
return `${seconds}s`;
|
|
1209
|
+
}
|
|
1210
|
+
function formatList(values) {
|
|
1211
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
1212
|
+
return "None";
|
|
1213
|
+
return values.join(", ");
|
|
1214
|
+
}
|
|
1215
|
+
function formatCompetitors(values) {
|
|
1216
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
1217
|
+
return "None";
|
|
1218
|
+
return values.map((competitor) => {
|
|
1219
|
+
const aliases = competitor.aliases?.length ? ` [aliases: ${competitor.aliases.join(", ")}]` : "";
|
|
1220
|
+
return competitor.websiteUrl ? `${competitor.name} (${competitor.websiteUrl})${aliases}` : `${competitor.name}${aliases}`;
|
|
1221
|
+
}).join("; ");
|
|
1222
|
+
}
|
|
1223
|
+
function mergePromptPacks(prompts) {
|
|
1224
|
+
const deduped = new Map();
|
|
1225
|
+
for (const prompt of prompts) {
|
|
1226
|
+
deduped.set(normalizePromptKey(prompt), prompt);
|
|
179
1227
|
}
|
|
180
|
-
return
|
|
1228
|
+
return [...deduped.values()];
|
|
1229
|
+
}
|
|
1230
|
+
function normalizePromptKey(prompt) {
|
|
1231
|
+
const raw = String(prompt.slug || prompt.title || "prompt").trim().toLowerCase();
|
|
1232
|
+
const normalized = raw.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1233
|
+
return normalized || "prompt";
|
|
181
1234
|
}
|
|
182
|
-
function
|
|
183
|
-
|
|
1235
|
+
function asCommandName(value) {
|
|
1236
|
+
if (!value)
|
|
1237
|
+
return undefined;
|
|
1238
|
+
return COMMANDS.find((command) => command === value);
|
|
1239
|
+
}
|
|
1240
|
+
function isRunnableCommand(command) {
|
|
1241
|
+
return command !== "help" && command !== "version";
|
|
1242
|
+
}
|
|
1243
|
+
async function printVersion() {
|
|
1244
|
+
const version = await getCliVersion();
|
|
1245
|
+
console.log(`@prompts-gpt/client v${version}`);
|
|
184
1246
|
}
|
|
185
1247
|
async function getCliVersion() {
|
|
186
1248
|
try {
|
|
@@ -192,47 +1254,478 @@ async function getCliVersion() {
|
|
|
192
1254
|
return "0.0.0";
|
|
193
1255
|
}
|
|
194
1256
|
}
|
|
195
|
-
function printHelp() {
|
|
1257
|
+
function printHelp(command) {
|
|
1258
|
+
if (command) {
|
|
1259
|
+
console.log(getCommandHelp(command));
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
196
1262
|
console.log(`Prompts-GPT CLI
|
|
197
1263
|
|
|
198
|
-
|
|
199
|
-
prompts-gpt
|
|
1264
|
+
Usage:
|
|
1265
|
+
prompts-gpt <command> [options]
|
|
1266
|
+
prompts-gpt help [command]
|
|
200
1267
|
prompts-gpt version
|
|
201
|
-
prompts-gpt project
|
|
202
|
-
prompts-gpt pull [--query "repo audit"] [--category coding] [--tool Codex] [--limit 25] [--out .prompts-gpt] [--overwrite]
|
|
203
|
-
prompts-gpt generate --goal "Review this diff" [--context "Next.js app"] [--agent codex,cursor,vscode]
|
|
204
|
-
prompts-gpt sync [--goal "Review this diff"] [--limit 25] [--agent all] [--out .prompts-gpt] [--cwd /path/to/repo]
|
|
205
|
-
prompts-gpt install-agents [--agent codex,cursor,vscode,copilot]
|
|
206
1268
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
1269
|
+
Commands:
|
|
1270
|
+
init Save a project token in .prompts-gpt/.credentials.json
|
|
1271
|
+
setup Scaffold .prompts-gpt/config.json for local orchestration
|
|
1272
|
+
load-config Pull configuration and prompts directly from Prompts Studio
|
|
1273
|
+
pull Download prompt packs as Markdown files
|
|
1274
|
+
generate Generate one prompt pack from a goal
|
|
1275
|
+
sync Generate and/or pull prompt packs, then sync agent files
|
|
1276
|
+
list Show available prompts, sweeps, and agent integrations
|
|
1277
|
+
status Show workspace readiness and next steps
|
|
1278
|
+
validate Validate .prompts-gpt/config.json and report issues
|
|
1279
|
+
run Execute a prompt file with local agent orchestration
|
|
1280
|
+
run-batch Execute multiple prompt files from config, manifest, or list
|
|
1281
|
+
sweep Multi-iteration prompt execution with progress and summaries
|
|
1282
|
+
providers Show detected local provider CLIs
|
|
1283
|
+
doctor Validate local run prerequisites and config
|
|
1284
|
+
project Show the current project linked to the token
|
|
1285
|
+
version Show the current CLI version
|
|
1286
|
+
help Show global or command-specific help
|
|
1287
|
+
|
|
1288
|
+
Global options:
|
|
1289
|
+
--help Show help
|
|
1290
|
+
--version Show the current CLI version
|
|
220
1291
|
|
|
221
1292
|
Supported tools: ${VALID_TOOLS.join(", ")}
|
|
222
1293
|
Supported agent targets: ${SUPPORTED_AGENT_TARGETS.join(", ")}
|
|
1294
|
+
Run agent profiles: ${ORCHESTRATION_AGENT_PROFILES.join(", ")}
|
|
223
1295
|
`);
|
|
224
1296
|
}
|
|
1297
|
+
function parsePositiveIntFlag(raw, flagName) {
|
|
1298
|
+
if (raw === undefined)
|
|
1299
|
+
return undefined;
|
|
1300
|
+
const label = flagName ? `--${flagName}` : "Value";
|
|
1301
|
+
if (!/^\d+$/.test(raw)) {
|
|
1302
|
+
throw new CliError(`${label} must be a positive integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1303
|
+
}
|
|
1304
|
+
const value = Number.parseInt(raw, 10);
|
|
1305
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
1306
|
+
throw new CliError(`${label} must be a positive integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1307
|
+
}
|
|
1308
|
+
return value;
|
|
1309
|
+
}
|
|
1310
|
+
function parseNonNegativeIntFlag(raw, flagName) {
|
|
1311
|
+
if (raw === undefined)
|
|
1312
|
+
return undefined;
|
|
1313
|
+
const label = flagName ? `--${flagName}` : "Value";
|
|
1314
|
+
if (!/^\d+$/.test(raw)) {
|
|
1315
|
+
throw new CliError(`${label} must be a non-negative integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1316
|
+
}
|
|
1317
|
+
const value = Number.parseInt(raw, 10);
|
|
1318
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
1319
|
+
throw new CliError(`${label} must be a non-negative integer, got "${raw}".`, CLI_EXIT_CODES.validation);
|
|
1320
|
+
}
|
|
1321
|
+
return value;
|
|
1322
|
+
}
|
|
1323
|
+
function resolveRunAgent(flags, fallback) {
|
|
1324
|
+
const raw = getStringFlag(flags, "agent");
|
|
1325
|
+
if (!raw)
|
|
1326
|
+
return fallback;
|
|
1327
|
+
const normalizedRaw = raw.trim().toLowerCase();
|
|
1328
|
+
const normalized = normalizeOrchestrationAgent(raw);
|
|
1329
|
+
if (normalized === "router" && normalizedRaw !== "router") {
|
|
1330
|
+
const profiles = ORCHESTRATION_AGENT_PROFILES.join(", ");
|
|
1331
|
+
const hint = ORCHESTRATION_AGENT_PROFILES.find((p) => p.startsWith(normalizedRaw.slice(0, 3)));
|
|
1332
|
+
const suggestion = hint ? ` Did you mean "${hint}"?` : "";
|
|
1333
|
+
throw new CliError(`Invalid --agent target: ${raw}. Use ${profiles}.${suggestion}`, CLI_EXIT_CODES.validation);
|
|
1334
|
+
}
|
|
1335
|
+
return normalized;
|
|
1336
|
+
}
|
|
1337
|
+
function getCommandHelp(command) {
|
|
1338
|
+
if (command === "init") {
|
|
1339
|
+
return `prompts-gpt init
|
|
1340
|
+
|
|
1341
|
+
Usage:
|
|
1342
|
+
prompts-gpt init (--token <project-token> | --token-stdin | --token-prompt) [--api-url <url>] [--cwd <path>]
|
|
1343
|
+
|
|
1344
|
+
Why use it:
|
|
1345
|
+
Stores a project token in a local credentials file so day-one CLI usage does not require re-pasting secrets on every command.
|
|
1346
|
+
|
|
1347
|
+
Options:
|
|
1348
|
+
--token <token> Project API token. Must start with pgpt_.
|
|
1349
|
+
--token-stdin Read the project token from stdin so it does not end up in shell history.
|
|
1350
|
+
--token-prompt Prompt for the project token without echoing it.
|
|
1351
|
+
--api-url <url> Custom API base URL for self-hosted instances.
|
|
1352
|
+
--cwd <path> Target project directory that will receive .prompts-gpt/.credentials.json.
|
|
1353
|
+
--help Show this command help.
|
|
1354
|
+
`;
|
|
1355
|
+
}
|
|
1356
|
+
if (command === "setup") {
|
|
1357
|
+
return `prompts-gpt setup
|
|
1358
|
+
|
|
1359
|
+
Usage:
|
|
1360
|
+
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>]
|
|
1361
|
+
|
|
1362
|
+
Why use it:
|
|
1363
|
+
Scaffolds a generic local orchestration config so a repo can run prompts through Codex, Cursor, Claude Code, or Copilot with minimal repeated CLI flags.
|
|
1364
|
+
|
|
1365
|
+
Options:
|
|
1366
|
+
--prompt-file <path> Default single prompt file for \`prompts-gpt run\`.
|
|
1367
|
+
--prompt-files <list> Default batch prompt files for \`prompts-gpt run-batch\`.
|
|
1368
|
+
--manifest <path> Use this manifest as the batch source. Default: auto-detect .prompts-gpt/manifest.json
|
|
1369
|
+
--prompt-dir <path> Scan a prompt directory when you do not use .prompts-gpt.
|
|
1370
|
+
--agent <name> Default orchestration profile. Default: router
|
|
1371
|
+
--provider-order <list> Comma-separated router order such as codex,cursor,claude,copilot
|
|
1372
|
+
--timeout <seconds> Default timeout in seconds. Default: 900
|
|
1373
|
+
--retry-count <n> Retry count for spawn and timeout failures. Default: 0
|
|
1374
|
+
--artifacts-dir <path> Run artifact directory. Default: .scripts/runs
|
|
1375
|
+
--codex-model <name> Default model override for codex.
|
|
1376
|
+
--cursor-model <name> Default model override for cursor.
|
|
1377
|
+
--claude-model <name> Default model override for claude.
|
|
1378
|
+
--copilot-model <name> Default model override for copilot.
|
|
1379
|
+
--allow-destructive-git Write config with destructive git protection disabled.
|
|
1380
|
+
--overwrite Replace an existing config file.
|
|
1381
|
+
--json Print the generated config payload as JSON.
|
|
1382
|
+
--cwd <path> Project directory.
|
|
1383
|
+
--help Show this command help.
|
|
1384
|
+
`;
|
|
1385
|
+
}
|
|
1386
|
+
if (command === "project") {
|
|
1387
|
+
return `prompts-gpt project
|
|
1388
|
+
|
|
1389
|
+
Usage:
|
|
1390
|
+
prompts-gpt project [--json] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1391
|
+
|
|
1392
|
+
Why use it:
|
|
1393
|
+
Verifies that the current local token resolves to the expected Prompts-GPT project before syncing files.
|
|
1394
|
+
|
|
1395
|
+
Options:
|
|
1396
|
+
--json Print the full project payload as JSON.
|
|
1397
|
+
--token <token> Override the saved local token for this command only.
|
|
1398
|
+
--token-stdin Read the override token from stdin for this command only.
|
|
1399
|
+
--token-prompt Prompt for the override token without echoing it.
|
|
1400
|
+
--api-url <url> Override the saved API base URL for this command only.
|
|
1401
|
+
--cwd <path> Project directory to inspect for local credentials.
|
|
1402
|
+
--help Show this command help.
|
|
1403
|
+
`;
|
|
1404
|
+
}
|
|
1405
|
+
if (command === "pull") {
|
|
1406
|
+
return `prompts-gpt pull
|
|
1407
|
+
|
|
1408
|
+
Usage:
|
|
1409
|
+
prompts-gpt pull [--query <text> | --q <text>] [--category <name>] [--tool <name>] [--output-type <name>] [--limit <n>] [--out <dir>] [--overwrite] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1410
|
+
|
|
1411
|
+
Why use it:
|
|
1412
|
+
Pulls prompt packs into local Markdown files so teams can review and use the same prompt assets inside their repository.
|
|
1413
|
+
|
|
1414
|
+
Options:
|
|
1415
|
+
--query <text> Search query for the project prompt library.
|
|
1416
|
+
--q <text> Short alias for --query.
|
|
1417
|
+
--category <name> Filter prompts by category.
|
|
1418
|
+
--tool <name> Filter prompts by supported tool.
|
|
1419
|
+
--output-type <name> Filter prompts by output type.
|
|
1420
|
+
--limit <n> Positive integer limit for returned prompts.
|
|
1421
|
+
--out <dir> Output directory inside the current project. Default: .prompts-gpt
|
|
1422
|
+
--overwrite Replace existing Markdown files instead of skipping them.
|
|
1423
|
+
--token <token> Override the saved local token for this command only.
|
|
1424
|
+
--token-stdin Read the override token from stdin for this command only.
|
|
1425
|
+
--token-prompt Prompt for the override token without echoing it.
|
|
1426
|
+
--api-url <url> Override the saved API base URL for this command only.
|
|
1427
|
+
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
1428
|
+
--help Show this command help.
|
|
1429
|
+
`;
|
|
1430
|
+
}
|
|
1431
|
+
if (command === "generate") {
|
|
1432
|
+
return `prompts-gpt generate
|
|
1433
|
+
|
|
1434
|
+
Usage:
|
|
1435
|
+
prompts-gpt generate --goal <text> [--context <text>] [--constraints <text>] [--desired-output <text>] [--tool <name>] [--mode <name>] [--artifact-type <name>] [--web-search] [--out <dir>] [--overwrite] [--agent <targets>] [--sync-agents] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1436
|
+
|
|
1437
|
+
Why use it:
|
|
1438
|
+
Creates a new reusable prompt pack from a concrete developer goal, then optionally installs agent-readable files immediately.
|
|
1439
|
+
|
|
1440
|
+
Options:
|
|
1441
|
+
--goal <text> Required. The task to generate a prompt pack for.
|
|
1442
|
+
--context <text> Extra project or stack context for the generator.
|
|
1443
|
+
--constraints <text> Constraints that the generated prompt must honor.
|
|
1444
|
+
--desired-output <text> Preferred output shape for the generated prompt pack.
|
|
1445
|
+
--tool <name> Target tool. Default: Codex
|
|
1446
|
+
--mode <name> Prompt generation mode. Default: implement
|
|
1447
|
+
--artifact-type <name> Artifact type. Default: prompt-file
|
|
1448
|
+
--web-search Allow server-side web research when generating the prompt.
|
|
1449
|
+
--out <dir> Output directory inside the current project. Default: .prompts-gpt
|
|
1450
|
+
--overwrite Replace an existing generated Markdown file.
|
|
1451
|
+
--agent <targets> Sync agent files for specific targets after generation.
|
|
1452
|
+
--sync-agents Sync all agent files after generation.
|
|
1453
|
+
--token <token> Override the saved local token for this command only.
|
|
1454
|
+
--token-stdin Read the override token from stdin for this command only.
|
|
1455
|
+
--token-prompt Prompt for the override token without echoing it.
|
|
1456
|
+
--api-url <url> Override the saved API base URL for this command only.
|
|
1457
|
+
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
1458
|
+
--help Show this command help.
|
|
1459
|
+
`;
|
|
1460
|
+
}
|
|
1461
|
+
if (command === "sync") {
|
|
1462
|
+
return `prompts-gpt sync
|
|
1463
|
+
|
|
1464
|
+
Usage:
|
|
1465
|
+
prompts-gpt sync [--goal <text>] [--generated-only] [--query <text> | --q <text>] [--category <name>] [--tool <name>] [--output-type <name>] [--limit <n>] [--context <text>] [--constraints <text>] [--desired-output <text>] [--mode <name>] [--artifact-type <name>] [--web-search] [--agent <targets>] [--out <dir>] [--overwrite] [--dry-run] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1466
|
+
|
|
1467
|
+
Why use it:
|
|
1468
|
+
Gives teams a one-command path to refresh Markdown prompts, agent files, and the local manifest from the same source of truth.
|
|
1469
|
+
|
|
1470
|
+
Options:
|
|
1471
|
+
--goal <text> Generate one prompt pack before syncing.
|
|
1472
|
+
--generated-only Skip library pull and sync only the generated prompt pack from --goal.
|
|
1473
|
+
--query <text> Search query for pulled prompt packs.
|
|
1474
|
+
--q <text> Short alias for --query.
|
|
1475
|
+
--category <name> Filter pulled prompt packs by category.
|
|
1476
|
+
--tool <name> Filter pulled prompt packs and generated output by tool.
|
|
1477
|
+
--output-type <name> Filter pulled prompt packs by output type.
|
|
1478
|
+
--limit <n> Positive integer limit for pulled prompt packs.
|
|
1479
|
+
--context <text> Extra project or stack context for generated prompt packs.
|
|
1480
|
+
--constraints <text> Constraints for generated prompt packs.
|
|
1481
|
+
--desired-output <text> Preferred output shape for generated prompt packs.
|
|
1482
|
+
--mode <name> Prompt generation mode. Default: implement
|
|
1483
|
+
--artifact-type <name> Artifact type. Default: prompt-file
|
|
1484
|
+
--web-search Allow server-side web research when generating a prompt pack.
|
|
1485
|
+
--agent <targets> Comma-separated agent targets. Default: all
|
|
1486
|
+
--out <dir> Output directory inside the current project. Default: .prompts-gpt
|
|
1487
|
+
--overwrite Replace existing Markdown files instead of skipping them.
|
|
1488
|
+
--dry-run Preview what would be synced without writing any files.
|
|
1489
|
+
--token <token> Override the saved local token for this command only.
|
|
1490
|
+
--token-stdin Read the override token from stdin for this command only.
|
|
1491
|
+
--token-prompt Prompt for the override token without echoing it.
|
|
1492
|
+
--api-url <url> Override the saved API base URL for this command only.
|
|
1493
|
+
--cwd <path> Project directory to inspect for local credentials and output files.
|
|
1494
|
+
--help Show this command help.
|
|
1495
|
+
`;
|
|
1496
|
+
}
|
|
1497
|
+
if (command === "run") {
|
|
1498
|
+
return `prompts-gpt run
|
|
1499
|
+
|
|
1500
|
+
Usage:
|
|
1501
|
+
prompts-gpt run [--prompt-file <path>] [--agent codex|cursor|claude|copilot|router] [--model <name>] [--timeout <seconds>] [--artifacts-dir <path>] [--run-id <id>] [--sandbox <mode>] [--no-approve-mcps] [--background] [--permission-mode <mode>] [--json] [--cwd <path>]
|
|
1502
|
+
|
|
1503
|
+
Why use it:
|
|
1504
|
+
Executes one local prompt file with the built-in provider adapter runtime and writes run artifacts. If \`--prompt-file\` is omitted, the command uses the configured default prompt.
|
|
1505
|
+
|
|
1506
|
+
Options:
|
|
1507
|
+
--prompt-file <path> Optional explicit prompt Markdown or text file.
|
|
1508
|
+
--agent <name> Orchestration profile. Default from ${DEFAULT_RUN_CONFIG_PATH} or router.
|
|
1509
|
+
--model <name> Optional model override for the selected provider.
|
|
1510
|
+
--timeout <seconds> Execution timeout in seconds.
|
|
1511
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1512
|
+
--run-id <id> Explicit run ID for artifact folder naming.
|
|
1513
|
+
--sandbox <mode> Codex sandbox mode. Default: workspace-write.
|
|
1514
|
+
--no-approve-mcps Disable Cursor MCP auto-approval flag.
|
|
1515
|
+
--background Run as a background agent (Cursor cloud agent mode).
|
|
1516
|
+
--permission-mode <mode> Claude Code permission mode. Default: acceptEdits.
|
|
1517
|
+
--json Print machine-readable JSON output.
|
|
1518
|
+
--cwd <path> Project directory.
|
|
1519
|
+
--help Show this command help.
|
|
1520
|
+
`;
|
|
1521
|
+
}
|
|
1522
|
+
if (command === "run-batch") {
|
|
1523
|
+
return `prompts-gpt run-batch
|
|
1524
|
+
|
|
1525
|
+
Usage:
|
|
1526
|
+
prompts-gpt run-batch [--manifest <path> | --prompt-files <a,b,c>] [--agent codex|cursor|claude|copilot|router] [--model <name>] [--timeout <seconds>] [--artifacts-dir <path>] [--json] [--cwd <path>]
|
|
1527
|
+
|
|
1528
|
+
Why use it:
|
|
1529
|
+
Executes multiple prompt files in sequence using the configured prompt source, a manifest, or an explicit file list.
|
|
1530
|
+
|
|
1531
|
+
Options:
|
|
1532
|
+
--manifest <path> Prompt manifest path. Overrides config batch defaults.
|
|
1533
|
+
--prompt-files <list> Comma-separated prompt files to run.
|
|
1534
|
+
--agent <name> Orchestration profile. Default from ${DEFAULT_RUN_CONFIG_PATH} or router.
|
|
1535
|
+
--model <name> Optional model override for all runs.
|
|
1536
|
+
--timeout <seconds> Execution timeout in seconds per prompt.
|
|
1537
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1538
|
+
--json Print machine-readable JSON output.
|
|
1539
|
+
--cwd <path> Project directory.
|
|
1540
|
+
--help Show this command help.
|
|
1541
|
+
`;
|
|
1542
|
+
}
|
|
1543
|
+
if (command === "sweep") {
|
|
1544
|
+
return `prompts-gpt sweep
|
|
1545
|
+
|
|
1546
|
+
Usage:
|
|
1547
|
+
prompts-gpt sweep [--prompt-file <path>] [--agent codex|cursor|claude|copilot|router] [--model <name>] [--iterations <n>] [--iteration-timeout <seconds>] [--max-retries <n>] [--phase <name>] [--artifacts-dir <path>] [--run-id <id>] [--sandbox <mode>] [--no-approve-mcps] [--background] [--permission-mode <mode>] [--max-run-dirs <n>] [--summary-lines <n>] [--dry-run] [--json] [--cwd <path>]
|
|
1548
|
+
|
|
1549
|
+
Why use it:
|
|
1550
|
+
Replaces the bash sweep scripts with a generic multi-iteration execution engine.
|
|
1551
|
+
Runs the same prompt N times, feeding each iteration's summary into the next.
|
|
1552
|
+
Includes pre-flight checks, safety guards, SIGTERM handling, progress monitoring,
|
|
1553
|
+
and a structured sweep manifest.
|
|
1554
|
+
|
|
1555
|
+
Options:
|
|
1556
|
+
--prompt-file <path> Prompt file to sweep. Reads from config if omitted.
|
|
1557
|
+
--agent <name> Orchestration profile. Default from config or router.
|
|
1558
|
+
--model <name> Model override for the selected provider.
|
|
1559
|
+
--iterations <n> Number of sweep iterations. Default: 1
|
|
1560
|
+
--iteration-timeout <secs> Timeout per iteration in seconds. Default: 5400 (90 min)
|
|
1561
|
+
--max-retries <n> Max retries per iteration on spawn/timeout. Default: 2
|
|
1562
|
+
--phase <name> Optional phase label injected into the prompt.
|
|
1563
|
+
--artifacts-dir <path> Override run artifacts directory.
|
|
1564
|
+
--run-id <id> Explicit run ID for artifact folder naming.
|
|
1565
|
+
--sandbox <mode> Codex sandbox mode. Default: workspace-write
|
|
1566
|
+
--no-approve-mcps Disable Cursor MCP auto-approval flag.
|
|
1567
|
+
--background Run as a background agent (Cursor cloud agent mode).
|
|
1568
|
+
--permission-mode <mode> Claude Code permission mode. Default: acceptEdits
|
|
1569
|
+
--max-run-dirs <n> Max artifact directories to keep. Default: 20
|
|
1570
|
+
--summary-lines <n> Lines of summary to extract per iteration. Default: 40
|
|
1571
|
+
--dry-run Preview what the sweep would do without executing.
|
|
1572
|
+
--json Print machine-readable JSON output.
|
|
1573
|
+
--cwd <path> Project directory.
|
|
1574
|
+
--help Show this command help.
|
|
1575
|
+
`;
|
|
1576
|
+
}
|
|
1577
|
+
if (command === "list") {
|
|
1578
|
+
return `prompts-gpt list
|
|
1579
|
+
|
|
1580
|
+
Usage:
|
|
1581
|
+
prompts-gpt list [--json] [--cwd <path>]
|
|
1582
|
+
|
|
1583
|
+
Why use it:
|
|
1584
|
+
Shows all prompt packs, sweep files, and agent integrations available in the workspace.
|
|
1585
|
+
Gives runnable commands for each entry so you can copy-paste them directly.
|
|
1586
|
+
|
|
1587
|
+
Options:
|
|
1588
|
+
--json Print as JSON.
|
|
1589
|
+
--cwd <path> Project directory.
|
|
1590
|
+
--help Show this command help.
|
|
1591
|
+
`;
|
|
1592
|
+
}
|
|
1593
|
+
if (command === "status") {
|
|
1594
|
+
return `prompts-gpt status
|
|
1595
|
+
|
|
1596
|
+
Usage:
|
|
1597
|
+
prompts-gpt status [--json] [--cwd <path>]
|
|
1598
|
+
|
|
1599
|
+
Why use it:
|
|
1600
|
+
Shows workspace readiness at a glance: credentials, config, manifest,
|
|
1601
|
+
prompts, sweeps, agent integrations, and available providers.
|
|
1602
|
+
|
|
1603
|
+
Options:
|
|
1604
|
+
--json Print as JSON.
|
|
1605
|
+
--cwd <path> Project directory.
|
|
1606
|
+
--help Show this command help.
|
|
1607
|
+
`;
|
|
1608
|
+
}
|
|
1609
|
+
if (command === "validate") {
|
|
1610
|
+
return `prompts-gpt validate
|
|
1611
|
+
|
|
1612
|
+
Usage:
|
|
1613
|
+
prompts-gpt validate [--json] [--cwd <path>]
|
|
1614
|
+
|
|
1615
|
+
Why use it:
|
|
1616
|
+
Validates the .prompts-gpt/config.json file and reports errors and
|
|
1617
|
+
warnings without running any commands.
|
|
1618
|
+
|
|
1619
|
+
Options:
|
|
1620
|
+
--json Print as JSON.
|
|
1621
|
+
--cwd <path> Project directory.
|
|
1622
|
+
--help Show this command help.
|
|
1623
|
+
`;
|
|
1624
|
+
}
|
|
1625
|
+
if (command === "providers") {
|
|
1626
|
+
return `prompts-gpt providers
|
|
1627
|
+
|
|
1628
|
+
Usage:
|
|
1629
|
+
prompts-gpt providers [--json] [--cwd <path>]
|
|
1630
|
+
|
|
1631
|
+
Why use it:
|
|
1632
|
+
Shows provider CLI detection details for codex, cursor, claude, and copilot so you can decide the best router order before running setup.
|
|
1633
|
+
`;
|
|
1634
|
+
}
|
|
1635
|
+
if (command === "doctor") {
|
|
1636
|
+
return `prompts-gpt doctor
|
|
1637
|
+
|
|
1638
|
+
Usage:
|
|
1639
|
+
prompts-gpt doctor [--json] [--cwd <path>]
|
|
1640
|
+
|
|
1641
|
+
Why use it:
|
|
1642
|
+
Checks runtime prerequisites, provider availability, prompt-source readiness, and run config health.
|
|
1643
|
+
`;
|
|
1644
|
+
}
|
|
1645
|
+
if (command === "load-config") {
|
|
1646
|
+
return `prompts-gpt load-config
|
|
1647
|
+
|
|
1648
|
+
Usage:
|
|
1649
|
+
prompts-gpt load-config [--agent <targets>] [--out <dir>] [--json] [--token <project-token> | --token-stdin | --token-prompt] [--api-url <url>] [--cwd <path>]
|
|
1650
|
+
|
|
1651
|
+
Why use it:
|
|
1652
|
+
One command to pull all prompts, agent files, and config from Prompts Studio
|
|
1653
|
+
into your local workspace. Replaces the multi-step init + sync + setup flow
|
|
1654
|
+
for users who manage their prompt library in the Prompts Studio web app.
|
|
1655
|
+
|
|
1656
|
+
Options:
|
|
1657
|
+
--agent <targets> Comma-separated agent targets. Default: all
|
|
1658
|
+
--out <dir> Output directory. Default: .prompts-gpt
|
|
1659
|
+
--json Print machine-readable JSON output.
|
|
1660
|
+
--token <token> Override saved token.
|
|
1661
|
+
--token-stdin Read token from stdin.
|
|
1662
|
+
--token-prompt Prompt for token.
|
|
1663
|
+
--api-url <url> Override API URL.
|
|
1664
|
+
--cwd <path> Project directory.
|
|
1665
|
+
--help Show this command help.
|
|
1666
|
+
`;
|
|
1667
|
+
}
|
|
1668
|
+
if (command === "version") {
|
|
1669
|
+
return `prompts-gpt version
|
|
1670
|
+
|
|
1671
|
+
Usage:
|
|
1672
|
+
prompts-gpt version
|
|
1673
|
+
|
|
1674
|
+
Why use it:
|
|
1675
|
+
Confirms the installed CLI version when debugging package resolution or publish issues.
|
|
1676
|
+
`;
|
|
1677
|
+
}
|
|
1678
|
+
return `prompts-gpt help
|
|
1679
|
+
|
|
1680
|
+
Usage:
|
|
1681
|
+
prompts-gpt help [command]
|
|
1682
|
+
|
|
1683
|
+
Why use it:
|
|
1684
|
+
Shows focused usage for the exact command you are trying to run so shell users do not have to scan the full command list.
|
|
1685
|
+
`;
|
|
1686
|
+
}
|
|
225
1687
|
main().catch((error) => {
|
|
1688
|
+
if (error instanceof CliError) {
|
|
1689
|
+
console.error(error.message);
|
|
1690
|
+
if (error.helpCommand) {
|
|
1691
|
+
console.error(`Run \`prompts-gpt help${error.helpCommand ? ` ${error.helpCommand}` : ""}\` for usage.`);
|
|
1692
|
+
}
|
|
1693
|
+
process.exitCode = error.exitCode;
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
226
1696
|
if (error instanceof PromptsGptApiError) {
|
|
227
|
-
console.error(
|
|
1697
|
+
console.error(formatApiError(error));
|
|
228
1698
|
process.exitCode = error.status === 401 || error.status === 403
|
|
229
1699
|
? CLI_EXIT_CODES.auth
|
|
230
|
-
: error.
|
|
231
|
-
? CLI_EXIT_CODES.
|
|
232
|
-
:
|
|
1700
|
+
: error.status === 429
|
|
1701
|
+
? CLI_EXIT_CODES.rateLimit
|
|
1702
|
+
: error.code === "VALIDATION_ERROR"
|
|
1703
|
+
? CLI_EXIT_CODES.validation
|
|
1704
|
+
: CLI_EXIT_CODES.general;
|
|
233
1705
|
return;
|
|
234
1706
|
}
|
|
235
|
-
|
|
1707
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1708
|
+
console.error(msg.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
|
|
236
1709
|
process.exitCode = CLI_EXIT_CODES.general;
|
|
237
1710
|
});
|
|
1711
|
+
function warnOnConfigIssues(config) {
|
|
1712
|
+
for (const w of config.configWarnings) {
|
|
1713
|
+
console.error(`[config warning] ${w}`);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function formatApiError(error) {
|
|
1717
|
+
const lines = [error.message];
|
|
1718
|
+
for (const [field, messages] of Object.entries(error.fieldErrors ?? {})) {
|
|
1719
|
+
for (const message of messages ?? []) {
|
|
1720
|
+
lines.push(`- ${field}: ${message}`);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
if (error.requestId) {
|
|
1724
|
+
lines.push(`Request ID: ${error.requestId}`);
|
|
1725
|
+
}
|
|
1726
|
+
if (error.recovery) {
|
|
1727
|
+
lines.push(error.recovery);
|
|
1728
|
+
}
|
|
1729
|
+
return lines.join("\n");
|
|
1730
|
+
}
|
|
238
1731
|
//# sourceMappingURL=cli.js.map
|