@youdie006/prodex 0.16.2 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/banner.js +0 -1
  2. package/dist/bundle.js +0 -1
  3. package/dist/chatgpt-browser.js +34 -6
  4. package/dist/cli-args.js +0 -1
  5. package/dist/cli-help.js +2 -2
  6. package/dist/cli-ledger.js +0 -1
  7. package/dist/cli-pro.js +24 -13
  8. package/dist/cli-server.js +0 -1
  9. package/dist/cli-shared.js +0 -1
  10. package/dist/cli.js +7 -5
  11. package/dist/config.js +0 -1
  12. package/dist/http-mcp.js +6 -2
  13. package/dist/index.js +0 -1
  14. package/dist/mcp-tools.js +0 -1
  15. package/dist/mcp.js +15 -2
  16. package/dist/registry.js +0 -1
  17. package/dist/repo-write.js +0 -1
  18. package/dist/repo.js +0 -1
  19. package/dist/safe-file.js +0 -1
  20. package/dist/schema.js +0 -1
  21. package/dist/store.js +0 -1
  22. package/package.json +1 -1
  23. package/scripts/release-check.mjs +23 -2
  24. package/scripts/release-pack.mjs +5 -2
  25. package/dist/banner.d.ts +0 -5
  26. package/dist/banner.js.map +0 -1
  27. package/dist/bundle.d.ts +0 -15
  28. package/dist/bundle.js.map +0 -1
  29. package/dist/chatgpt-browser.d.ts +0 -252
  30. package/dist/chatgpt-browser.js.map +0 -1
  31. package/dist/cli-args.d.ts +0 -54
  32. package/dist/cli-args.js.map +0 -1
  33. package/dist/cli-help.d.ts +0 -20
  34. package/dist/cli-help.js.map +0 -1
  35. package/dist/cli-ledger.d.ts +0 -22
  36. package/dist/cli-ledger.js.map +0 -1
  37. package/dist/cli-pro.d.ts +0 -157
  38. package/dist/cli-pro.js.map +0 -1
  39. package/dist/cli-server.d.ts +0 -42
  40. package/dist/cli-server.js.map +0 -1
  41. package/dist/cli-shared.d.ts +0 -68
  42. package/dist/cli-shared.js.map +0 -1
  43. package/dist/cli.d.ts +0 -14
  44. package/dist/cli.js.map +0 -1
  45. package/dist/config.d.ts +0 -110
  46. package/dist/config.js.map +0 -1
  47. package/dist/http-mcp.d.ts +0 -20
  48. package/dist/http-mcp.js.map +0 -1
  49. package/dist/index.d.ts +0 -8
  50. package/dist/index.js.map +0 -1
  51. package/dist/mcp-tools.d.ts +0 -395
  52. package/dist/mcp-tools.js.map +0 -1
  53. package/dist/mcp.d.ts +0 -57
  54. package/dist/mcp.js.map +0 -1
  55. package/dist/registry.d.ts +0 -8
  56. package/dist/registry.js.map +0 -1
  57. package/dist/repo-write.d.ts +0 -47
  58. package/dist/repo-write.js.map +0 -1
  59. package/dist/repo.d.ts +0 -28
  60. package/dist/repo.js.map +0 -1
  61. package/dist/safe-file.d.ts +0 -25
  62. package/dist/safe-file.js.map +0 -1
  63. package/dist/schema.d.ts +0 -402
  64. package/dist/schema.js.map +0 -1
  65. package/dist/store.d.ts +0 -165
  66. package/dist/store.js.map +0 -1
package/dist/banner.js CHANGED
@@ -44,4 +44,3 @@ export function shouldColorize(env = process.env, isTty = process.stdout.isTTY)
44
44
  return env.FORCE_COLOR !== "0";
45
45
  return Boolean(isTty);
46
46
  }
47
- //# sourceMappingURL=banner.js.map
package/dist/bundle.js CHANGED
@@ -27,4 +27,3 @@ export async function buildDryRunBundle(root, input) {
27
27
  created_at: nowIso()
28
28
  };
29
29
  }
30
- //# sourceMappingURL=bundle.js.map
@@ -470,8 +470,32 @@ async function readSettledChatGptPageStatus(page) {
470
470
  await sleep(400);
471
471
  status = await evaluateOnPage(page, statusExpression());
472
472
  }
473
+ // An open modal dialog (e.g. the "ChatGPT for Work" onboarding promo shipped
474
+ // with the 2026-07 update) puts the app behind aria-hidden, so the composer
475
+ // and the logged-in signals are undetectable and every flow would report
476
+ // "not ready". Escape dismisses such dialogs; try it (bounded) only when the
477
+ // composer is actually blocked and a dialog is open.
478
+ for (let attempt = 0; attempt < 2 && !status.hasComposer && (status.openDialogText ?? "").length > 0; attempt += 1) {
479
+ await dismissOpenDialogViaEscape(page);
480
+ await sleep(500);
481
+ status = await evaluateOnPage(page, statusExpression());
482
+ }
473
483
  return status;
474
484
  }
485
+ async function dismissOpenDialogViaEscape(page) {
486
+ const cdp = await connectCdp(page.webSocketDebuggerUrl);
487
+ try {
488
+ await cdp.send("Runtime.enable");
489
+ await dispatchEscapeKey(cdp);
490
+ }
491
+ catch {
492
+ // Best effort: if the Escape cannot be delivered the settle loop simply
493
+ // reports the original not-ready state.
494
+ }
495
+ finally {
496
+ cdp.close();
497
+ }
498
+ }
475
499
  async function ensureVisibleChatGptPage(port, page, status) {
476
500
  if (status.visibilityState === "visible")
477
501
  return status;
@@ -701,7 +725,11 @@ export function menuItemLabelMatches(text, candidates) {
701
725
  }
702
726
  function menuLabelMatchPredicate(label) {
703
727
  const c = JSON.stringify(toLabelCandidates(label));
704
- return `((r) => { const t = (r.textContent || "").trim(); return ${c}.includes(t) || ${c}.includes(t.split(String.fromCharCode(10))[0].trim()); })`;
728
+ // Prefer innerText over textContent: a badge rendered next to the label (e.g.
729
+ // the "5.5" chip on "Instant") concatenates in textContent ("Instant5.5",
730
+ // unmatchable) but keeps a line break in innerText ("Instant\n5.5"), which the
731
+ // first-line match handles (measured live on the 2026-07 ChatGPT update).
732
+ return `((r) => { const t = ((r.innerText || r.textContent || "")).trim(); return ${c}.includes(t) || ${c}.includes(t.split(String.fromCharCode(10))[0].trim()); })`;
705
733
  }
706
734
  export function menuItemPresentExpression(label) {
707
735
  return `[...document.querySelectorAll('[role="menuitemradio"],[role="menuitem"]')].some(${menuLabelMatchPredicate(label)})`;
@@ -764,7 +792,7 @@ export function menuItemRectExpression(label) {
764
792
  if (!m) return { ok: false, reason: "reasoning/model menu did not open" };
765
793
  const items = [...m.querySelectorAll('[role="menuitemradio"],[role="menuitem"]')];
766
794
  const it = items.find(${menuLabelMatchPredicate(label)});
767
- if (!it) return { ok: false, reason: "menu item not found", available: items.map((r) => (r.textContent || "").trim()).slice(0, 12) };
795
+ if (!it) return { ok: false, reason: "menu item not found", available: items.map((r) => ((r.innerText || r.textContent || "").trim().split(String.fromCharCode(10))[0] || "").trim()).slice(0, 12) };
768
796
  const point = clickPoint(it);
769
797
  if (!point.ok) return point;
770
798
  return { ...point, role: it.getAttribute("role"), haspopup: it.getAttribute("aria-haspopup") };
@@ -785,7 +813,7 @@ export function submenuItemRectExpression(label) {
785
813
  // or "Pro 확장"), so it must be matched by prefix, never by exact text.
786
814
  const PRO_RADIO_FINDER_SNIPPET = `
787
815
  const findProRadio = (scope) =>
788
- [...scope.querySelectorAll('[role="menuitemradio"]')].find((r) => /^Pro( |$)/.test((r.textContent || "").trim()));`;
816
+ [...scope.querySelectorAll('[role="menuitemradio"]')].find((r) => /^Pro( |$)/.test(((r.innerText || r.textContent || "").trim().split(String.fromCharCode(10))[0] || "").trim()));`;
789
817
  export function proRadioRectExpression() {
790
818
  return `(() => {${CLICK_POINT_SNIPPET}${PRO_RADIO_FINDER_SNIPPET}
791
819
  const m = document.querySelector('[data-testid="composer-intelligence-picker-content"]');
@@ -1257,7 +1285,7 @@ export function modelMenuOptionsExpression() {
1257
1285
  if (!m) return [];
1258
1286
  return [...m.querySelectorAll('[role="menuitemradio"],[role="menuitem"]')]
1259
1287
  .map((it) => ({
1260
- label: (it.textContent || "").trim(),
1288
+ label: (((it.innerText || it.textContent || "").trim().split(String.fromCharCode(10))[0]) || "").trim(),
1261
1289
  kind: it.getAttribute("aria-haspopup") === "menu" ? "submenu" : "radio",
1262
1290
  checked: it.getAttribute("aria-checked") === "true"
1263
1291
  }))
@@ -1547,7 +1575,8 @@ export function statusExpression() {
1547
1575
  visibleButtonLabels,
1548
1576
  hasComposer,
1549
1577
  generating: placeholder || Boolean(document.querySelector(${streamingSelector})) || visibleButtonLabels.some((label) => generatingControlPattern.test(label)),
1550
- modelHints: lines.filter((line) => /GPT|Pro|Thinking|ChatGPT|Extra High|Auto/i.test(line)).slice(0, 30)
1578
+ modelHints: lines.filter((line) => /GPT|Pro|Thinking|ChatGPT|Extra High|Auto/i.test(line)).slice(0, 30),
1579
+ openDialogText: (document.querySelector('[role="dialog"]')?.innerText || "").trim().slice(0, 200)
1551
1580
  };
1552
1581
  })()`;
1553
1582
  }
@@ -1873,4 +1902,3 @@ function hasChromeLikeVersion(command) {
1873
1902
  function sleep(ms) {
1874
1903
  return new Promise((resolve) => setTimeout(resolve, ms));
1875
1904
  }
1876
- //# sourceMappingURL=chatgpt-browser.js.map
package/dist/cli-args.js CHANGED
@@ -357,4 +357,3 @@ export function printHelpIfRequested(args, command, stdout, printHelp, options =
357
357
  printHelp(stdout);
358
358
  return true;
359
359
  }
360
- //# sourceMappingURL=cli-args.js.map
package/dist/cli-help.js CHANGED
@@ -45,6 +45,7 @@ Bridge ledger (durable tasks/results/receipts/sessions under .bridge/):
45
45
  prodex receipts rotate-key [--cwd /absolute/path/to/repo]
46
46
  prodex sessions list [--status preview|running|done|blocked] [--cwd /absolute/path/to/repo] [--json]
47
47
  prodex sessions show <session-id|latest> [--cwd /absolute/path/to/repo]
48
+ prodex sessions cancel <session-id|latest> [--cwd /absolute/path/to/repo]
48
49
 
49
50
  Agent / MCP integration:
50
51
  prodex mcp [--cwd /absolute/path/to/repo]
@@ -171,7 +172,7 @@ Commands:
171
172
  Use \`prodex pro ask\` for dry-run/manual previews.
172
173
  Use \`prodex pro browser ask\` only when you want an explicit visible-browser send.
173
174
  Model/project selection (visible-browser send):
174
- --model "label" Pick the composer model by its exact menu label (verified: Pro). Submenu models (e.g. GPT-5.5 variants) are rejected for now.
175
+ --model "label" Pick the composer model by its exact menu label (verified: Pro). Submenu models (e.g. the GPT-5.6 Sol variants) are rejected for now.
175
176
  --pro-mode 기본 | 확장 Pro sub-mode (only when the model is Pro); 확장 raises the default timeout to 300000 ms
176
177
  --effort 즉시|중간|높음|매우 높음 Reasoning effort (aliases: instant/medium/high/max); picking one deselects Pro
177
178
  --project "name" Enter an existing sidebar project first (cannot combine with --target-url)
@@ -275,4 +276,3 @@ Persist defaults with \`${cli} setup${sourceCliOption}\`; per-ask flags override
275
276
  Use \`${cli} pro ask\` for dry-run/manual previews.
276
277
  \`${cli} pro browser ask${sourceCliOption}\` always attempts an explicit visible-browser send.`);
277
278
  }
278
- //# sourceMappingURL=cli-help.js.map
@@ -378,4 +378,3 @@ export async function listResultsForInspection(store) {
378
378
  export async function listRawResultsForInspection(store) {
379
379
  return store.listResultsReadOnly();
380
380
  }
381
- //# sourceMappingURL=cli-ledger.js.map
package/dist/cli-pro.js CHANGED
@@ -215,16 +215,22 @@ export async function runProCommand(rest, io, runCliFn) {
215
215
  });
216
216
  return 0;
217
217
  }
218
- const opened = openChatGptBrowser({
219
- port,
220
- profileDir,
221
- url: loginUrl
222
- });
223
- await assertBrowserLaunchStayedAlive(opened, launchTimeoutMs);
218
+ // If the dedicated Chrome is already reachable on this port, do NOT spawn
219
+ // again: Chrome's singleton would just open ANOTHER window (the recurring
220
+ // "extra windows" problem, which then blocks sends as
221
+ // ambiguous_chatgpt_tabs). Reuse the running instance instead.
222
+ const alreadyRunning = (await getChatGptBrowserStatus({ port })).reachable;
223
+ const opened = alreadyRunning
224
+ ? { profileDir: profileDir ?? defaultChatGptProfileDir(), port }
225
+ : openChatGptBrowser({ port, profileDir, url: loginUrl });
226
+ if (!alreadyRunning) {
227
+ await assertBrowserLaunchStayedAlive(opened, launchTimeoutMs);
228
+ }
224
229
  // Remember this launch so ask auto-recovery reuses the same profile.
225
230
  await recordBrowserLoginLaunch({ profile_dir: opened.profileDir, port: opened.port });
226
231
  printBrowserLoginGuide(io.stdout, {
227
- opened: true,
232
+ opened: !alreadyRunning,
233
+ reused: alreadyRunning,
228
234
  loginUrl,
229
235
  profileDir: opened.profileDir,
230
236
  port: opened.port,
@@ -481,8 +487,9 @@ export async function runAskProCommand(rest, io) {
481
487
  throw new Error("--json applies to the visible-browser send output; the dry-run preview does not support it.");
482
488
  }
483
489
  const prompt = parsedAskPro.promptParts.join(" ").trim();
484
- if (!prompt)
485
- throw new Error("ask-pro requires a prompt");
490
+ if (!prompt) {
491
+ throw new Error('ask-pro requires a prompt. Example: prodex ask "Explain this stack trace" (or pipe input: git diff | prodex ask --stdin "review this diff").');
492
+ }
486
493
  let promptText = prompt;
487
494
  if (parsedAskPro.optionArgs.includes("--stdin")) {
488
495
  // Unix ergonomics: `git diff | prodex ask --stdin "review this"`.
@@ -1090,6 +1097,7 @@ export async function listConsultListEntries(store, options = { readOnly: true }
1090
1097
  return entries;
1091
1098
  }
1092
1099
  export function printBrowserLoginGuide(stdout, input) {
1100
+ const windowAvailable = input.opened || input.reused === true;
1093
1101
  const loginCommand = formatBrowserLoginCommand(input.sourceCli, input.commandOptions);
1094
1102
  const runtimeCommandOptions = {
1095
1103
  ...(input.commandOptions?.cwd ? { cwd: input.commandOptions.cwd } : {}),
@@ -1098,10 +1106,14 @@ export function printBrowserLoginGuide(stdout, input) {
1098
1106
  const checkCommand = formatBrowserCheckCommand(input.sourceCli, runtimeCommandOptions);
1099
1107
  const smokeCommand = formatBrowserSmokeCommand(input.sourceCli, runtimeCommandOptions);
1100
1108
  stdout("ChatGPT Pro browser login");
1101
- stdout(input.opened ? "Opened the dedicated Chrome window for ChatGPT." : "Dry run: no browser was opened.");
1109
+ stdout(input.reused
1110
+ ? "Chrome is already running for ChatGPT - reusing it (no new window opened)."
1111
+ : input.opened
1112
+ ? "Opened the dedicated Chrome window for ChatGPT."
1113
+ : "Dry run: no browser was opened.");
1102
1114
  stdout("");
1103
1115
  stdout("Steps:");
1104
- if (input.opened) {
1116
+ if (windowAvailable) {
1105
1117
  stdout(`1. Log in manually at ${input.loginUrl} in the dedicated Chrome window.`);
1106
1118
  stdout("2. If ChatGPT asks for captcha, Cloudflare/human verification, permission, or account verification, complete it in the browser.");
1107
1119
  stdout("3. For usage limit, message limit, model limit, or rate limit, wait for the reset or choose an available model in the browser.");
@@ -1123,7 +1135,7 @@ export function printBrowserLoginGuide(stdout, input) {
1123
1135
  stdout("");
1124
1136
  stdout(`Profile: ${input.profileDir}`);
1125
1137
  stdout(`Debug: http://127.0.0.1:${input.port}`);
1126
- if (input.opened) {
1138
+ if (windowAvailable) {
1127
1139
  stdout("You can close this Chrome window after check/smoke or when you are done. The dedicated profile is reused next time.");
1128
1140
  }
1129
1141
  else {
@@ -1390,4 +1402,3 @@ export function orphanConsultResultError(taskId) {
1390
1402
  export function sleep(ms) {
1391
1403
  return new Promise((resolve) => setTimeout(resolve, ms));
1392
1404
  }
1393
- //# sourceMappingURL=cli-pro.js.map
@@ -396,4 +396,3 @@ export async function assertGitignoreTargetSafe(filePath) {
396
396
  throw error;
397
397
  }
398
398
  }
399
- //# sourceMappingURL=cli-server.js.map
@@ -204,4 +204,3 @@ export function computeSendPacingWaitMs(lastSendAtMs, nowMs, intervalMs) {
204
204
  return 0; // clock skew / bad marker: do not wait
205
205
  return elapsed >= intervalMs ? 0 : intervalMs - elapsed;
206
206
  }
207
- //# sourceMappingURL=cli-shared.js.map
package/dist/cli.js CHANGED
@@ -622,15 +622,18 @@ async function readReleasePackStatus(cwd, packageJson, sourceCli, releaseHintCwd
622
622
  };
623
623
  }
624
624
  }
625
- function parsePackedFiles(stdout) {
626
- let entries;
625
+ export function parsePackedFiles(stdout) {
626
+ let parsed;
627
627
  try {
628
- entries = JSON.parse(stdout);
628
+ parsed = JSON.parse(stdout);
629
629
  }
630
630
  catch {
631
631
  throw new Error("npm pack dry-run did not return valid JSON");
632
632
  }
633
- const files = entries?.[0]?.files;
633
+ // npm <=11 prints an ARRAY of entries; npm 12 changed `pack --json` to an
634
+ // OBJECT keyed by package name (measured on npm 12.0.0). Accept both.
635
+ const first = (Array.isArray(parsed) ? parsed[0] : Object.values(parsed ?? {})[0]);
636
+ const files = first?.files;
634
637
  if (!Array.isArray(files)) {
635
638
  throw new Error("npm pack dry-run did not return a file list");
636
639
  }
@@ -1341,4 +1344,3 @@ if (isDirectCliInvocation()) {
1341
1344
  process.exitCode = 1;
1342
1345
  });
1343
1346
  }
1344
- //# sourceMappingURL=cli.js.map
package/dist/config.js CHANGED
@@ -316,4 +316,3 @@ async function assertDirectoryHandle(handle, label) {
316
316
  throw new Error(`${label} must be a real directory`);
317
317
  }
318
318
  }
319
- //# sourceMappingURL=config.js.map
package/dist/http-mcp.js CHANGED
@@ -23,7 +23,12 @@ export async function startHttpMcpServer(options) {
23
23
  return;
24
24
  }
25
25
  if (!isAuthorized(req, requestUrl, token, options.tokenExpiresAt)) {
26
- writeJson(res, 401, { error: "unauthorized" });
26
+ // Same 401 for missing/wrong/expired (no oracle), but tell the caller
27
+ // HOW to authorize without leaking anything token-specific.
28
+ writeJson(res, 401, {
29
+ error: "unauthorized",
30
+ hint: "Provide a valid token via `?prodex_token=<token>` or `Authorization: Bearer <token>`. If your token expired, regenerate the profile with `prodex setup` and re-read the URL from `prodex status`."
31
+ });
27
32
  return;
28
33
  }
29
34
  if (req.method === "POST") {
@@ -233,4 +238,3 @@ function writeJson(res, status, value) {
233
238
  res.writeHead(status, { "content-type": "application/json" });
234
239
  res.end(`${JSON.stringify(value)}\n`);
235
240
  }
236
- //# sourceMappingURL=http-mcp.js.map
package/dist/index.js CHANGED
@@ -6,4 +6,3 @@ export * from "./chatgpt-browser.js";
6
6
  export * from "./config.js";
7
7
  export * from "./http-mcp.js";
8
8
  export * from "./mcp-tools.js";
9
- //# sourceMappingURL=index.js.map
package/dist/mcp-tools.js CHANGED
@@ -199,4 +199,3 @@ function assertMcpFiles(files) {
199
199
  assertMcpTextField(file.path, `files[${index}].path`, MAX_MCP_SHORT_TEXT_BYTES);
200
200
  }
201
201
  }
202
- //# sourceMappingURL=mcp-tools.js.map
package/dist/mcp.js CHANGED
@@ -279,9 +279,22 @@ export class LimitedStdioServerTransport {
279
279
  }
280
280
  const line = this.buffer.toString("utf8", 0, newlineIndex).replace(/\r$/, "");
281
281
  this.buffer = this.buffer.subarray(newlineIndex + 1);
282
- const message = JSONRPCMessageSchema.parse(JSON.parse(line));
282
+ if (line.trim().length === 0)
283
+ continue;
284
+ let message;
285
+ try {
286
+ message = JSONRPCMessageSchema.parse(JSON.parse(line));
287
+ }
288
+ catch (error) {
289
+ // A single malformed frame is recoverable: report it and keep
290
+ // processing the rest of the buffer instead of tearing down the whole
291
+ // session (which would also drop any valid pipelined messages after
292
+ // it). This matches the SDK's StdioServerTransport. Only the oversize
293
+ // guards above stay fatal.
294
+ this.onerror?.(error instanceof Error ? error : new Error(String(error)));
295
+ continue;
296
+ }
283
297
  this.onmessage?.(message);
284
298
  }
285
299
  }
286
300
  }
287
- //# sourceMappingURL=mcp.js.map
package/dist/registry.js CHANGED
@@ -102,4 +102,3 @@ async function registerBridgeRootInner(root) {
102
102
  // Advisory registry - never let it fail a bridge operation.
103
103
  }
104
104
  }
105
- //# sourceMappingURL=registry.js.map
@@ -424,4 +424,3 @@ function buildSimpleDiff(repoPath, before, after) {
424
424
  ...after.replace(/\r\n/g, "\n").split("\n").map((line) => `+${line}`)
425
425
  ].join("\n");
426
426
  }
427
- //# sourceMappingURL=repo-write.js.map
package/dist/repo.js CHANGED
@@ -484,4 +484,3 @@ export async function assertResolvedRepoPathAllowed(root, resolved, repoPath) {
484
484
  function isErrorCode(error, code) {
485
485
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
486
486
  }
487
- //# sourceMappingURL=repo.js.map
package/dist/safe-file.js CHANGED
@@ -292,4 +292,3 @@ function procFdPath(fd) {
292
292
  function isMissingFileError(error) {
293
293
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
294
294
  }
295
- //# sourceMappingURL=safe-file.js.map
package/dist/schema.js CHANGED
@@ -106,4 +106,3 @@ export function makeBridgeId(prefix, title, date = new Date()) {
106
106
  const stamp = date.toISOString().replace(/[-:]/g, "").replace(/\..+$/, "").replace("T", "_");
107
107
  return `${prefix}_${stamp}_${slugify(title)}`;
108
108
  }
109
- //# sourceMappingURL=schema.js.map
package/dist/store.js CHANGED
@@ -1565,4 +1565,3 @@ function redactReceiptForDisplay(receipt, integrityStatus) {
1565
1565
  }
1566
1566
  return ReceiptSchema.parse({ ...receipt, metadata });
1567
1567
  }
1568
- //# sourceMappingURL=store.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdie006/prodex",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "description": "Local receipt bus for coordinating Codex execution with ChatGPT Pro/Projects consultation.",
5
5
  "author": "youdie006",
6
6
  "license": "MIT",
@@ -198,7 +198,9 @@ async function readPackedFiles(rootDir) {
198
198
  }
199
199
  try {
200
200
  const entries = JSON.parse(stdout);
201
- const files = entries?.[0]?.files;
201
+ // npm <=11 prints an array; npm 12 prints an object keyed by package name.
202
+ const firstEntry = Array.isArray(entries) ? entries[0] : Object.values(entries ?? {})[0];
203
+ const files = firstEntry?.files;
202
204
  if (!Array.isArray(files)) {
203
205
  throw new Error("release metadata failed: npm pack dry-run did not return a file list");
204
206
  }
@@ -336,10 +338,27 @@ async function run(command, commandArgs, cwd) {
336
338
  maxBuffer: 20 * 1024 * 1024
337
339
  });
338
340
  } catch (error) {
341
+ // Surface the real failure: the one-line detail used to show the FIRST
342
+ // stderr line, which npm noise ("npm warn ...") could occupy while the
343
+ // actual test failure sat in stdout and was silently dropped.
344
+ printCapturedOutputTail(error, commandLine);
339
345
  throw new Error(`release verification failed: ${commandLine}: ${commandFailureDetail(error)}`);
340
346
  }
341
347
  }
342
348
 
349
+ function printCapturedOutputTail(error, commandLine) {
350
+ const failed = error && typeof error === "object" ? error : {};
351
+ for (const [label, value] of [
352
+ ["stdout", failed.stdout],
353
+ ["stderr", failed.stderr]
354
+ ]) {
355
+ if (typeof value !== "string" || value.trim().length === 0) continue;
356
+ const tail = value.split(/\r?\n/).filter((line) => line.trim().length > 0).slice(-40);
357
+ console.error(`release_check: ${commandLine} ${label} tail:`);
358
+ for (const line of tail) console.error(` ${line}`);
359
+ }
360
+ }
361
+
343
362
  function commandForPlatform(command) {
344
363
  return process.platform === "win32" && command === "npm" ? "npm.cmd" : command;
345
364
  }
@@ -432,5 +451,7 @@ function firstOutputLine(value) {
432
451
  return value
433
452
  .split(/\r?\n/)
434
453
  .map((line) => line.trim())
435
- .find(Boolean);
454
+ // npm chatter is never the failure - skip it so the one-line summary shows
455
+ // the real error instead of "npm warn Unknown user config ...".
456
+ .find((line) => Boolean(line) && !/^npm (warn|notice)\b/i.test(line));
436
457
  }
@@ -133,7 +133,9 @@ async function readPackedFiles(root) {
133
133
  } catch {
134
134
  throw new Error("npm pack dry-run did not return valid JSON");
135
135
  }
136
- const files = entries?.[0]?.files;
136
+ // npm <=11 prints an array; npm 12 prints an object keyed by package name.
137
+ const first = Array.isArray(entries) ? entries[0] : Object.values(entries ?? {})[0];
138
+ const files = first?.files;
137
139
  if (!Array.isArray(files)) {
138
140
  throw new Error("npm pack dry-run did not return a file list");
139
141
  }
@@ -170,7 +172,8 @@ function resolvePackedTarball(destination, stdout) {
170
172
  } catch {
171
173
  throw new Error("npm pack did not return valid JSON");
172
174
  }
173
- const filename = entries?.[0]?.filename;
175
+ const firstEntry = Array.isArray(entries) ? entries[0] : Object.values(entries ?? {})[0];
176
+ const filename = firstEntry?.filename;
174
177
  if (typeof filename !== "string" || !filename.endsWith(".tgz")) {
175
178
  throw new Error(`could not determine npm pack tarball from output: ${stdout}`);
176
179
  }
package/dist/banner.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export interface BannerOptions {
2
- color?: boolean;
3
- }
4
- export declare function renderBanner(options?: BannerOptions): string;
5
- export declare function shouldColorize(env?: NodeJS.ProcessEnv, isTty?: boolean): boolean;
@@ -1 +0,0 @@
1
- {"version":3,"file":"banner.js","sourceRoot":"","sources":["../src/banner.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,8EAA8E;AAC9E,oCAAoC;AACpC,MAAM,QAAQ,GAAG;IACf,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;CAC5B,CAAC;AAEF,MAAM,QAAQ,GAAG;IACf,0BAA0B;IAC1B,0BAA0B;IAC1B,0BAA0B;IAC1B,0BAA0B;IAC1B,0BAA0B;IAC1B,2BAA2B;CAC5B,CAAC;AAEF,MAAM,GAAG,GAAG,GAAG,CAAC;AAChB,MAAM,GAAG,GAAG,GAAG,GAAG,kBAAkB,CAAC,CAAC,gBAAgB;AACtD,MAAM,GAAG,GAAG,GAAG,GAAG,oBAAoB,CAAC,CAAC,mDAAmD;AAC3F,MAAM,GAAG,GAAG,GAAG,GAAG,oBAAoB,CAAC,CAAC,UAAU;AAClD,MAAM,KAAK,GAAG,GAAG,GAAG,KAAK,CAAC;AAE1B,MAAM,OAAO,GAAG,gEAAgE,CAAC;AAEjF,MAAM,UAAU,YAAY,CAAC,UAAyB,EAAE;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IACpC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK;IAC/F,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACpE,uHAAuH;IACvH,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,GAAG,CAAC,WAAW,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC;IAC5F,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC"}
package/dist/bundle.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import { type BridgeFile } from "./schema.js";
2
- export interface DryRunBundleInput {
3
- prompt: string;
4
- files: string[];
5
- }
6
- export interface DryRunBundle {
7
- schema_version: 1;
8
- id: string;
9
- mode: "manual_copy";
10
- prompt: string;
11
- files: BridgeFile[];
12
- text: string;
13
- created_at: string;
14
- }
15
- export declare function buildDryRunBundle(root: string, input: DryRunBundleInput): Promise<DryRunBundle>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAiBzC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,KAAwB;IAC5E,MAAM,QAAQ,GAAa;QACzB,0BAA0B;QAC1B,EAAE;QACF,qCAAqC;QACrC,EAAE;QACF,WAAW;QACX,EAAE;QACF,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;KACpB,CAAC;IACF,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/F,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO;QACL,cAAc,EAAE,cAAc;QAC9B,EAAE,EAAE,YAAY,CAAC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACvE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACzB,UAAU,EAAE,MAAM,EAAE;KACrB,CAAC;AACJ,CAAC"}