prompts-gpt 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -115,8 +115,10 @@ prompts-gpt models --provider codex
115
115
  prompts-gpt sync-models
116
116
 
117
117
  # Use model aliases for shorter commands
118
- prompts-gpt run --model opus # resolves to claude-4.6-opus-high
118
+ prompts-gpt run --model opus # resolves to claude-opus-4-7
119
119
  prompts-gpt run --model mini # resolves to gpt-5.4-mini
120
+ prompts-gpt run --model pro # resolves to gpt-5.5-pro
121
+ prompts-gpt run --model o3 # resolves to o3
120
122
 
121
123
  # Sync from cloud
122
124
  prompts-gpt sync --agent all
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync, readFileSync } from "node:fs";
2
+ import { existsSync, readFileSync, statSync, readdirSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { parseArgs } from "node:util";
5
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, ensureGitignoreEntry, } from "./index.js";
@@ -79,7 +79,10 @@ async function main() {
79
79
  }
80
80
  const command = asCommandName(first);
81
81
  if (!command) {
82
- throw new CliError(`Unknown command: ${first}.`, CLI_EXIT_CODES.usage);
82
+ const suggestion = COMMANDS.find((c) => c.startsWith(first.slice(0, 3)));
83
+ const hint = suggestion ? ` Did you mean \`prompts-gpt ${suggestion}\`?` : "";
84
+ const installHint = "\nIf you installed from npm, ensure you have the latest version: npm install -g prompts-gpt@latest";
85
+ throw new CliError(`Unknown command: ${first}.${hint}${installHint}`, CLI_EXIT_CODES.usage);
83
86
  }
84
87
  if (!isRunnableCommand(command)) {
85
88
  throw new CliError(`Unknown command: ${first}.`, CLI_EXIT_CODES.usage, {
@@ -617,8 +620,7 @@ async function runCommand(command, flags) {
617
620
  const statusModelCache = path.resolve(cwd, DEFAULT_PROMPTS_GPT_OUT_DIR, ".models.json");
618
621
  if (existsSync(statusModelCache)) {
619
622
  try {
620
- const fs = require("node:fs");
621
- const mStat = fs.statSync(statusModelCache);
623
+ const mStat = statSync(statusModelCache);
622
624
  const ageMs = Date.now() - mStat.mtimeMs;
623
625
  const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));
624
626
  console.log(` Models: ${ageDays <= 7 ? "✓" : "⚠"} synced ${ageDays === 0 ? "today" : `${ageDays}d ago`}${ageDays > 7 ? " — run 'prompts-gpt sync-models'" : ""}`);
@@ -629,18 +631,6 @@ async function runCommand(command, flags) {
629
631
  console.log(" Models: — not synced. Run 'prompts-gpt sync-models'");
630
632
  }
631
633
  console.log("");
632
- const lockFile = path.resolve(cwd, ".sweep.lock");
633
- if (existsSync(lockFile)) {
634
- try {
635
- const { readFile: fsRead } = await import("node:fs/promises");
636
- const lockData = JSON.parse(await fsRead(lockFile, "utf8"));
637
- console.log(` Sweep lock: ⚠ active (PID ${lockData.pid}, started ${lockData.startedAt})`);
638
- }
639
- catch {
640
- console.log(" Sweep lock: ⚠ found but unreadable");
641
- }
642
- }
643
- console.log("");
644
634
  if (assets.prompts.length > 0 && availableProviders.length > 0) {
645
635
  console.log("Ready to run:");
646
636
  console.log(` prompts-gpt run --prompt-file .prompts-gpt/${assets.prompts[0].file}`);
@@ -1041,24 +1031,31 @@ async function runCommand(command, flags) {
1041
1031
  }
1042
1032
  const providers = await detectProviders(cwd);
1043
1033
  const availableProviders = providers.filter((p) => p.available);
1044
- if (!getStringFlag(flags, "agent") && isTTYInteractive(flags) && !Boolean(flags.json) && availableProviders.length > 1) {
1045
- const lastProvider = await getLastUsedProvider(cwd);
1046
- const providerOptions = availableProviders.map((p) => ({
1047
- label: `${p.provider} (${p.modelDefault}${p.version ? `, ${p.version}` : ""})${p.provider === lastProvider ? " ★" : ""}`,
1048
- value: p.provider,
1049
- }));
1050
- providerOptions.push({ label: "router (auto-select best available)", value: "router" });
1051
- if (lastProvider) {
1052
- const idx = providerOptions.findIndex((o) => o.value === lastProvider);
1053
- if (idx > 0) {
1054
- const [item] = providerOptions.splice(idx, 1);
1055
- providerOptions.unshift(item);
1034
+ if (!getStringFlag(flags, "agent") && isTTYInteractive(flags) && !Boolean(flags.json)) {
1035
+ if (availableProviders.length === 1) {
1036
+ const only = availableProviders[0];
1037
+ console.log(`Using provider: ${only.provider} (${only.modelDefault}${only.version ? `, ${only.version}` : ""})`);
1038
+ flags.agent = only.provider;
1039
+ }
1040
+ else if (availableProviders.length > 1) {
1041
+ const lastProvider = await getLastUsedProvider(cwd);
1042
+ const providerOptions = availableProviders.map((p) => ({
1043
+ label: `${p.provider} (${p.modelDefault}${p.version ? `, ${p.version}` : ""})${p.provider === lastProvider ? " ★" : ""}`,
1044
+ value: p.provider,
1045
+ }));
1046
+ providerOptions.push({ label: "router (auto-select best available)", value: "router" });
1047
+ if (lastProvider) {
1048
+ const idx = providerOptions.findIndex((o) => o.value === lastProvider);
1049
+ if (idx > 0) {
1050
+ const [item] = providerOptions.splice(idx, 1);
1051
+ providerOptions.unshift(item);
1052
+ }
1053
+ }
1054
+ const picked = await interactiveSelect("Select a provider:", providerOptions);
1055
+ flags.agent = picked;
1056
+ if (picked !== "router") {
1057
+ await saveLastUsedProvider(cwd, picked);
1056
1058
  }
1057
- }
1058
- const picked = await interactiveSelect("Select a provider:", providerOptions);
1059
- flags.agent = picked;
1060
- if (picked !== "router") {
1061
- await saveLastUsedProvider(cwd, picked);
1062
1059
  }
1063
1060
  }
1064
1061
  if (!getStringFlag(flags, "model") && isTTYInteractive(flags) && !Boolean(flags.json)) {
@@ -1107,7 +1104,7 @@ async function runCommand(command, flags) {
1107
1104
  const resolvedP = resolveRunProvider(agent, providers, config.providerOrder);
1108
1105
  const check = validateModelForProvider(sweepModelFlag, resolvedP);
1109
1106
  if (!check.valid) {
1110
- console.log(`⚠ Model "${sweepModelFlag}" may not be available for ${resolvedP}.${check.suggestion ? ` Did you mean "${check.suggestion}"?` : ""}`);
1107
+ console.log(`⚠ Model "${sweepModelFlag}" may not be available for ${resolvedP}.${check.suggestion ? ` Did you mean "${check.suggestion}"?` : ""}\n Run \`prompts-gpt sweep --list-models --agent ${resolvedP}\` to see available models.`);
1111
1108
  }
1112
1109
  }
1113
1110
  if (isTTYInteractive(flags) && !Boolean(flags.json) && !Boolean(flags["dry-run"])) {
@@ -1128,14 +1125,16 @@ async function runCommand(command, flags) {
1128
1125
  ];
1129
1126
  const longestVal = Math.max(...boxValues.map((v) => v.length), 30);
1130
1127
  const innerW = longestVal + 16;
1131
- const bar = "═".repeat(innerW);
1128
+ const uc = supportsColor();
1129
+ const [TL, H, TR, V, ML, MR, BL, BR] = uc ? ["╔", "═", "╗", "║", "╠", "╣", "╚", "╝"] : ["+", "-", "+", "|", "+", "+", "+", "+"];
1130
+ const bar = H.repeat(innerW);
1132
1131
  const pad = (v) => v.padEnd(longestVal);
1133
- const row = (label, val) => `${colorize("║", "\x1b[36m")} ${label.padEnd(12)} ${pad(val)} ${colorize("║", "\x1b[36m")}`;
1132
+ const row = (label, val) => `${colorize(V, "\x1b[36m")} ${label.padEnd(12)} ${pad(val)} ${colorize(V, "\x1b[36m")}`;
1134
1133
  const titleText = "Prompts-GPT Sweep";
1135
1134
  const titlePad = Math.max(0, Math.floor((innerW - titleText.length) / 2));
1136
- console.log(colorize(`╔${bar}╗`, "\x1b[36m"));
1137
- console.log(colorize(`║${" ".repeat(titlePad)}${titleText}${" ".repeat(innerW - titlePad - titleText.length)}║`, "\x1b[36m"));
1138
- console.log(colorize(`╠${bar}╣`, "\x1b[36m"));
1135
+ console.log(colorize(`${TL}${bar}${TR}`, "\x1b[36m"));
1136
+ console.log(colorize(`${V}${" ".repeat(titlePad)}${titleText}${" ".repeat(innerW - titlePad - titleText.length)}${V}`, "\x1b[36m"));
1137
+ console.log(colorize(`${ML}${bar}${MR}`, "\x1b[36m"));
1139
1138
  console.log(row("Sweep:", path.basename(sweepFile)));
1140
1139
  console.log(row("Provider:", resolvedProvider));
1141
1140
  console.log(row("Model:", resolvedModel));
@@ -1145,9 +1144,9 @@ async function runCommand(command, flags) {
1145
1144
  console.log(row("Retries:", String(maxRetries)));
1146
1145
  console.log(row("Tier:", tierBadge));
1147
1146
  if (modelTier === "frontier") {
1148
- console.log(`${colorize("║", "\x1b[36m")} ${colorize("⚠ Frontier model — higher cost per token", "\x1b[33m")}${" ".repeat(Math.max(0, innerW - 43))} ${colorize("║", "\x1b[36m")}`);
1147
+ console.log(`${colorize(V, "\x1b[36m")} ${colorize(uc ? "⚠ Frontier model — higher cost per token" : "! Frontier model -- higher cost per token", "\x1b[33m")}${" ".repeat(Math.max(0, innerW - 43))} ${colorize(V, "\x1b[36m")}`);
1149
1148
  }
1150
- console.log(colorize(`╚${bar}╝`, "\x1b[36m"));
1149
+ console.log(colorize(`${BL}${bar}${BR}`, "\x1b[36m"));
1151
1150
  console.log("");
1152
1151
  const confirmOpts = [
1153
1152
  { label: "Yes, run this sweep", value: "y" },
@@ -1171,12 +1170,11 @@ async function runCommand(command, flags) {
1171
1170
  console.log(`Branch: ${report.gitBranch} | Dirty files: ${report.gitDirtyFiles} | Free disk: ${report.diskFreeMb}MB`);
1172
1171
  console.log(`Prompt: ${path.basename(report.promptFile)}`);
1173
1172
  try {
1174
- const fs = require("node:fs");
1175
1173
  const skillDir = path.resolve(cwd, ".agents", "skills");
1176
1174
  const ruleDir = path.resolve(cwd, ".cursor", "rules");
1177
- const skillCount = fs.existsSync(skillDir) ? fs.readdirSync(skillDir, { recursive: true }).filter((f) => String(f).endsWith("SKILL.md")).length : 0;
1178
- const ruleCount = fs.existsSync(ruleDir) ? fs.readdirSync(ruleDir).filter((f) => String(f).endsWith(".mdc")).length : 0;
1179
- const mcpConfig = fs.existsSync(path.resolve(cwd, ".cursor", "mcp.json")) ? "found" : "none";
1175
+ const skillCount = existsSync(skillDir) ? readdirSync(skillDir, { recursive: true }).filter((f) => String(f).endsWith("SKILL.md")).length : 0;
1176
+ const ruleCount = existsSync(ruleDir) ? readdirSync(ruleDir).filter((f) => String(f).endsWith(".mdc")).length : 0;
1177
+ const mcpConfig = existsSync(path.resolve(cwd, ".cursor", "mcp.json")) ? "found" : "none";
1180
1178
  console.log(`Skills: ${skillCount} | Rules: ${ruleCount} | MCP config: ${mcpConfig}`);
1181
1179
  }
1182
1180
  catch { /* skip */ }
@@ -2479,6 +2477,8 @@ function getStringFlag(flags, name) {
2479
2477
  return typeof value === "string" ? value : undefined;
2480
2478
  }
2481
2479
  function formatDuration(ms) {
2480
+ if (!Number.isFinite(ms) || ms < 0)
2481
+ return "unknown";
2482
2482
  if (ms < 1000)
2483
2483
  return ms < 1 ? "<1ms" : `${Math.round(ms)}ms`;
2484
2484
  const totalSeconds = Math.round(ms / 1000);
@@ -2689,16 +2689,15 @@ const PROVIDER_MODELS = Object.freeze({
2689
2689
  { value: "gpt-4.1", label: "gpt-4.1 — legacy", tier: "budget" },
2690
2690
  ],
2691
2691
  claude: [
2692
- { value: "claude-opus-4-7", label: "claude-opus-4-7 — most capable, complex reasoning", tier: "frontier" },
2692
+ { value: "claude-opus-4-7", label: "claude-opus-4-7 — latest, most capable", tier: "frontier" },
2693
+ { value: "claude-opus-4-6", label: "claude-opus-4-6 — previous gen opus", tier: "frontier" },
2693
2694
  { value: "claude-sonnet-4-6", label: "claude-sonnet-4-6 — speed + intelligence", tier: "standard" },
2694
2695
  { value: "claude-haiku-4-5", label: "claude-haiku-4-5 — fastest near-frontier", tier: "fast" },
2695
- { value: "claude-4.6-opus-high", label: "claude-4.6-opus-high — high-thinking opus", tier: "frontier" },
2696
- { value: "claude-4.6-sonnet-high", label: "claude-4.6-sonnet-high — high-thinking sonnet", tier: "standard" },
2697
- { value: "claude-4.5-opus", label: "claude-4.5-opus — previous gen opus", tier: "standard" },
2698
2696
  ],
2699
2697
  cursor: [
2700
2698
  { value: "auto", label: "auto — Cursor auto-selects best", tier: "standard" },
2701
2699
  { value: "claude-4.6-opus-high", label: "claude-4.6-opus-high — frontier reasoning", tier: "frontier" },
2700
+ { value: "claude-4.6-opus-high-thinking", label: "claude-4.6-opus-high-thinking — reasoning + thinking", tier: "frontier" },
2702
2701
  { value: "claude-4.6-sonnet-high", label: "claude-4.6-sonnet-high — fast + smart", tier: "standard" },
2703
2702
  { value: "gpt-5.5-medium", label: "gpt-5.5-medium — GPT frontier", tier: "frontier" },
2704
2703
  { value: "composer-2", label: "composer-2 — balanced multi-file", tier: "standard" },
@@ -2717,7 +2716,7 @@ const PROVIDER_MODELS = Object.freeze({
2717
2716
  ],
2718
2717
  });
2719
2718
  const MODEL_ALIASES = {
2720
- opus: "claude-4.6-opus-high",
2719
+ opus: "claude-opus-4-7",
2721
2720
  sonnet: "claude-sonnet-4-6",
2722
2721
  haiku: "claude-haiku-4-5",
2723
2722
  codex: "gpt-5.3-codex",
@@ -2727,6 +2726,8 @@ const MODEL_ALIASES = {
2727
2726
  composer: "composer-2",
2728
2727
  fast: "composer-2-fast",
2729
2728
  gemini: "gemini-3.1-pro",
2729
+ o3: "o3",
2730
+ pro: "gpt-5.5-pro",
2730
2731
  };
2731
2732
  function resolveModelAlias(model) {
2732
2733
  return MODEL_ALIASES[model.toLowerCase().trim()] ?? model;
@@ -3267,7 +3268,7 @@ Why use it:
3267
3268
  function supportsColor() {
3268
3269
  if (process.env.NO_COLOR || process.env.TERM === "dumb")
3269
3270
  return false;
3270
- if (process.env.FORCE_COLOR)
3271
+ if (process.env.FORCE_COLOR || process.env.COLORTERM)
3271
3272
  return true;
3272
3273
  if (process.platform === "win32") {
3273
3274
  if (process.env.WT_SESSION || process.env.TERM_PROGRAM || process.env.ConEmuANSI === "ON" || process.env.ANSICON)
@@ -3291,6 +3292,8 @@ function isTTYInteractive(flags) {
3291
3292
  return false;
3292
3293
  if (process.env.PROMPTS_GPT_NON_INTERACTIVE === "1" || process.env.PROMPTS_GPT_NON_INTERACTIVE === "true")
3293
3294
  return false;
3295
+ if (process.env.POWERSHELL_ISE === "1" || process.env.PSModulePath?.includes("ISE"))
3296
+ return false;
3294
3297
  return true;
3295
3298
  }
3296
3299
  function interactiveSelect(prompt, options) {
@@ -3311,10 +3314,12 @@ function interactiveSelect(prompt, options) {
3311
3314
  let escBuf = "";
3312
3315
  let filterText = "";
3313
3316
  const termRows = typeof process.stdout.rows === "number" && process.stdout.rows > 0 ? process.stdout.rows : 24;
3314
- const maxVisible = Math.max(3, Math.min(options.length, termRows - 4));
3317
+ const maxVisible = Math.min(options.length, Math.max(3, termRows - 4));
3315
3318
  const useUnicode = supportsColor();
3316
3319
  const pointer = useUnicode ? "❯" : ">";
3317
3320
  const formatLine = (i, selected) => {
3321
+ if (i >= options.length)
3322
+ return "";
3318
3323
  const num = i < 9 ? `${i + 1}` : " ";
3319
3324
  const prefix = selected ? colorize(pointer, "\x1b[36m") : " ";
3320
3325
  const label = selected ? colorize(options[i].label, "\x1b[1m") : options[i].label;
@@ -3323,7 +3328,8 @@ function interactiveSelect(prompt, options) {
3323
3328
  const hints = colorize(" ↑↓ navigate · 1-9 jump · Enter select · type to filter", "\x1b[90m");
3324
3329
  const writeInitial = () => {
3325
3330
  stdout.write(`${prompt}\n`);
3326
- for (let i = 0; i < maxVisible; i++) {
3331
+ const visibleCount = Math.min(maxVisible, options.length);
3332
+ for (let i = 0; i < visibleCount; i++) {
3327
3333
  stdout.write(`${formatLine(i, i === cursor)}\n`);
3328
3334
  }
3329
3335
  if (options.length > maxVisible) {
@@ -3331,10 +3337,12 @@ function interactiveSelect(prompt, options) {
3331
3337
  }
3332
3338
  stdout.write(`${hints}\n`);
3333
3339
  };
3340
+ const supportsAnsiCursor = supportsColor() || (process.platform === "win32" && Boolean(process.env.WT_SESSION));
3334
3341
  const render = () => {
3342
+ const visibleCount = Math.min(maxVisible, options.length);
3335
3343
  const footerLines = 1 + (options.length > maxVisible ? 1 : 0) + 1;
3336
- const lines = maxVisible + footerLines;
3337
- if (supportsColor()) {
3344
+ const lines = visibleCount + footerLines;
3345
+ if (supportsAnsiCursor) {
3338
3346
  stdout.write(`\x1b[${lines}A\x1b[J`);
3339
3347
  }
3340
3348
  else {
@@ -3343,10 +3351,14 @@ function interactiveSelect(prompt, options) {
3343
3351
  const posLabel = options.length > 1 ? ` (${cursor + 1}/${options.length})` : "";
3344
3352
  const filterLabel = filterText ? colorize(` filter: "${filterText}"`, "\x1b[33m") : "";
3345
3353
  stdout.write(`${prompt}${posLabel}${filterLabel}\n`);
3346
- const scrollStart = Math.max(0, Math.min(cursor - Math.floor(maxVisible / 2), options.length - maxVisible));
3347
- for (let vi = 0; vi < maxVisible; vi++) {
3354
+ const scrollStart = options.length <= maxVisible
3355
+ ? 0
3356
+ : Math.max(0, Math.min(cursor - Math.floor(maxVisible / 2), options.length - maxVisible));
3357
+ for (let vi = 0; vi < visibleCount; vi++) {
3348
3358
  const i = scrollStart + vi;
3349
- stdout.write(`${formatLine(i, i === cursor)}\n`);
3359
+ if (i < options.length) {
3360
+ stdout.write(`${formatLine(i, i === cursor)}\n`);
3361
+ }
3350
3362
  }
3351
3363
  if (options.length > maxVisible) {
3352
3364
  stdout.write(` ... showing ${scrollStart + 1}-${scrollStart + maxVisible} of ${options.length}\n`);
@@ -3383,10 +3395,14 @@ function interactiveSelect(prompt, options) {
3383
3395
  const onData = (data) => {
3384
3396
  for (let ci = 0; ci < data.length; ci++) {
3385
3397
  const ch = data[ci];
3386
- if (escBuf.length > 0) {
3398
+ if (escBuf.length > 0 && escBuf[0] === "\x1b") {
3387
3399
  escBuf += ch;
3388
3400
  if (escBuf.length === 2 && ch === "[")
3389
3401
  continue;
3402
+ if (escBuf.length === 2 && ch !== "[") {
3403
+ escBuf = "";
3404
+ continue;
3405
+ }
3390
3406
  if (escBuf.length >= 3) {
3391
3407
  if (escBuf === "\x1b[A" || escBuf === "\x1b[k") {
3392
3408
  cursor = cursor > 0 ? cursor - 1 : options.length - 1;
@@ -3408,12 +3424,40 @@ function interactiveSelect(prompt, options) {
3408
3424
  }
3409
3425
  escBuf = "";
3410
3426
  }
3427
+ if (escBuf.length > 8)
3428
+ escBuf = "";
3411
3429
  continue;
3412
3430
  }
3413
3431
  if (ch === "\x1b") {
3414
3432
  escBuf = "\x1b";
3415
3433
  continue;
3416
3434
  }
3435
+ if (ch === "\x00" || ch === "\xe0") {
3436
+ escBuf = ch;
3437
+ continue;
3438
+ }
3439
+ if (escBuf === "\x00" || escBuf === "\xe0") {
3440
+ if (ch === "H") {
3441
+ cursor = cursor > 0 ? cursor - 1 : options.length - 1;
3442
+ filterText = "";
3443
+ render();
3444
+ }
3445
+ else if (ch === "P") {
3446
+ cursor = cursor < options.length - 1 ? cursor + 1 : 0;
3447
+ filterText = "";
3448
+ render();
3449
+ }
3450
+ else if (ch === "G") {
3451
+ cursor = 0;
3452
+ render();
3453
+ }
3454
+ else if (ch === "O") {
3455
+ cursor = options.length - 1;
3456
+ render();
3457
+ }
3458
+ escBuf = "";
3459
+ continue;
3460
+ }
3417
3461
  if (ch === "\x03") {
3418
3462
  cleanup();
3419
3463
  stdout.write("\n");
@@ -3549,7 +3593,12 @@ main().catch((error) => {
3549
3593
  return;
3550
3594
  }
3551
3595
  if (error instanceof PromptsGptApiError) {
3552
- console.error(formatApiError(error));
3596
+ try {
3597
+ console.error(formatApiError(error));
3598
+ }
3599
+ catch {
3600
+ console.error(`API error: ${error.message} (${error.status})`);
3601
+ }
3553
3602
  process.exitCode = error.status === 401 || error.status === 403
3554
3603
  ? CLI_EXIT_CODES.auth
3555
3604
  : error.status === 429
@@ -3560,10 +3609,13 @@ main().catch((error) => {
3560
3609
  return;
3561
3610
  }
3562
3611
  const msg = error instanceof Error ? error.message : String(error);
3563
- console.error(msg.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
3564
- if (process.env.PROMPTS_GPT_DEBUG === "1" && error instanceof Error && error.stack) {
3565
- console.error(error.stack.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
3612
+ try {
3613
+ console.error(msg.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
3614
+ if (process.env.PROMPTS_GPT_DEBUG === "1" && error instanceof Error && error.stack) {
3615
+ console.error(error.stack.replace(/pgpt_[a-zA-Z0-9]{4,}/g, "pgpt_***"));
3616
+ }
3566
3617
  }
3618
+ catch { /* stderr closed or broken pipe */ }
3567
3619
  process.exitCode = CLI_EXIT_CODES.general;
3568
3620
  });
3569
3621
  async function extractRunDiagnostics(logFile, provider, model) {