@youdie006/prodex 0.40.30 → 0.40.31

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.
@@ -256,6 +256,9 @@ export const CHATGPT_RENDERED_MESSAGE_TEXT_JS = `
256
256
  const isBlock = (node) => node.nodeType === 1 && !skipped(node) &&
257
257
  (BLOCK_TAGS.includes(tagOf(node)) || isCodeBlock(node) || (isMath(node) && isDisplayMath(node)) ||
258
258
  (tagOf(node) === "span" && findAll(node, (n) => BLOCK_TAGS.includes(tagOf(n))).length > 0));
259
+ // The renderer web-search answers use since 2026-10-10 marks a source as a
260
+ // badge inside a popover trigger; its urls only exist once it is opened.
261
+ const isSourceBadge = (node) => attr(node, "data-d-component") === "popover-trigger" && findAll(node, (n) => attr(n, "data-pill") !== null).length > 0;
259
262
  const pill = (node) => {
260
263
  const label = collapse(node.textContent || "").trim();
261
264
  if (!label) return "";
@@ -268,7 +271,7 @@ export const CHATGPT_RENDERED_MESSAGE_TEXT_JS = `
268
271
  const piece = inlineNode(child);
269
272
  if (!piece) continue;
270
273
  // A source pill sits right after its sentence; keep one space before it.
271
- if (child.nodeType === 1 && attr(child, "data-chatgpt-copy-reference") !== null && out && !isSpaceChar(out[out.length - 1])) out += " ";
274
+ if (child.nodeType === 1 && (attr(child, "data-chatgpt-copy-reference") !== null || isSourceBadge(child)) && out && !isSpaceChar(out[out.length - 1])) out += " ";
272
275
  out += piece;
273
276
  }
274
277
  return out;
@@ -280,11 +283,12 @@ export const CHATGPT_RENDERED_MESSAGE_TEXT_JS = `
280
283
  // A task list item's box (measured: button[role=checkbox][aria-checked]).
281
284
  if (isCheckbox(node)) return (attr(node, "aria-checked") === "true" || attr(node, "checked") !== null ? "[x]" : "[ ]") + " ";
282
285
  if (isMath(node)) return isDisplayMath(node) ? "$$" + mathSource(node) + "$$" : "$" + mathSource(node) + "$";
283
- if (attr(node, "data-chatgpt-copy-reference") !== null) return pill(node);
286
+ if (attr(node, "data-chatgpt-copy-reference") !== null || isSourceBadge(node)) return pill(node);
284
287
  if (attr(node, "data-markdown-copy") === "inline-code" || tag === "code") return BT + (node.textContent || "") + BT;
285
288
  if (tag === "br") return NL;
286
289
  const inner = inline(node);
287
- if (tag === "strong" || tag === "b") return inner.trim() ? "**" + inner.trim() + "**" : "";
290
+ // The newer renderer marks bold as span[data-d-default-strong].
291
+ if (tag === "strong" || tag === "b" || attr(node, "data-d-default-strong") !== null) return inner.trim() ? "**" + inner.trim() + "**" : "";
288
292
  if (tag === "em" || tag === "i") return inner.trim() ? "*" + inner.trim() + "*" : "";
289
293
  if (tag === "del" || tag === "s") return inner.trim() ? "~~" + inner.trim() + "~~" : "";
290
294
  if (tag === "a") {
@@ -6059,8 +6063,23 @@ function chatGptRequestMarkerMatches(userText, requestId) {
6059
6063
  }
6060
6064
  /** Full prompt and per-send identity; wrappers may contain tool/file labels. */
6061
6065
  export function chatGptRequestMatchesUserTurn(userText, sentPrompt, requestId) {
6062
- return chatGptRequestMarkerMatches(userText, requestId) &&
6063
- normalizeChatGptPromptText(userText).includes(normalizeChatGptPromptText(sentPrompt));
6066
+ if (!chatGptRequestMarkerMatches(userText, requestId))
6067
+ return false;
6068
+ if (normalizeChatGptPromptText(userText).includes(normalizeChatGptPromptText(sentPrompt)))
6069
+ return true;
6070
+ // The container's ChatGPT renders a sent turn as markdown since 2026-10-10:
6071
+ // a --file prompt's fence lines disappear and the inner fences shift, so
6072
+ // every such send posted and was then refused. Fence lines carry no request
6073
+ // text; everything else, punctuation and inline backticks included, must
6074
+ // still match in order.
6075
+ return withoutFenceLines(userText).includes(withoutFenceLines(sentPrompt));
6076
+ }
6077
+ function withoutFenceLines(value) {
6078
+ return value
6079
+ .replace(AUTOLINKED_URL_PATTERN, "$1")
6080
+ .replace(/\\([\\`*_{}[\]()#+\-.!>~|])/g, "$1")
6081
+ .replace(/^[ \t]*```[\w-]*[ \t]*$/gm, "")
6082
+ .replace(/\s+/g, "");
6064
6083
  }
6065
6084
  /**
6066
6085
  * Does this transcript belong to the consult that is waiting on it?
package/docs/releasing.md CHANGED
@@ -16,6 +16,45 @@ Release target: `v0.40.13` on `main`. The GitHub Release records the resolved co
16
16
 
17
17
  The release adds a guarded, opt-in transition and more accurate blocker reporting. It does not claim that headless Pro consultation is verified on either deployment target or that authentication can be retained indefinitely.
18
18
 
19
+ ## Browser Container Rebuild 2026-10-10
20
+
21
+ **Patches**
22
+ - `container/redesign-patches` `5047ef9` ports 0.40.28-0.40.30 and PR #23 (newer answer renderer, sent turn drawn as markdown) onto the container branch. It is based on `b5eac7d`; `feat/headless-browser-compatibility` itself is unchanged.
23
+
24
+ **Image**
25
+ - `547e852632b5`, built from `5047ef9`; the branch suite passed (2027 passed, 3 skipped).
26
+ - Both swaps were gated on the send lock being free. After the swap the browser had no ChatGPT tab, so `prodex pro browser login --wait` reopened it (logged in, 3 s). MCP clients of the container need `/mcp` reconnects.
27
+
28
+ **Verified live**
29
+ - Image `9b51e0639a37` (the port without the fence fix): web search with bold and `[GitHub+1]` badges, continued and temporary attach, recover, models (the picker now lists GPT-6), smoke in a new chat, `pro list` in 5 s. A Markdown `--file` send posted but was refused as unverified: the container's ChatGPT drew the sent turn as markdown and dropped the ```` ```text ```` fence line.
30
+ - Image `547e852632b5`: the same `--file` send answered 2/2, and the smoke answered `PRODEX_PRO_SMOKE_OK`.
31
+
32
+ **Not a bug**
33
+ - A host 0.40.30 `--file` run failed during this check only because another send held the browser lock past its wait budget; the next run answered.
34
+
35
+ ## 0.40.30 Release Record
36
+
37
+ Release commit `e566efc` on `main` (cut after PR #22, merge `c0964f2`, plus the docs commit `09e80bc`); tag `v0.40.30`.
38
+
39
+ **Publishing**
40
+ - `publish.yml` run 37798469373 passed all six platforms on the first attempt, then npm publish with SLSA v1 provenance and the GitHub Release (2026-10-08 15:32 UTC).
41
+ - `npm run release:verify` passed on the release commit after a build.
42
+
43
+ **What it fixes**
44
+ - `pro browser smoke` always uses a fresh chat instead of whatever conversation was open.
45
+ - Its default budget is 5 minutes instead of 90 s.
46
+ - The page canary and the watchdog changes from the same PR are maintainer tooling and are not in the package. See Maintainer Watchdog.
47
+
48
+ **Installation on 2026-10-09**
49
+ - Global npm with `--prefer-online`, each verified with `prodex --version` = 0.40.30.
50
+ - WSL, M3, Mac mini: installed. Running services were not restarted: 21 stdio MCP servers on WSL and 10 on M3 keep older code until their clients reconnect. The Mac mini had none running.
51
+ - M4: not reachable (hostname does not resolve); not updated.
52
+
53
+ **Live check after install (installed 0.40.30, shared WSL browser)**
54
+ - With the tab on an existing conversation, `pro browser smoke` answered `PRODEX_PRO_SMOKE_OK` in a new conversation, not the open one.
55
+ - A new-chat attachment answered.
56
+ - The hourly watchdog had already logged `canary: ok` runs for build `4c511f80`.
57
+
19
58
  ## Maintainer Watchdog
20
59
 
21
60
  On the maintainer's WSL machine, cron runs the UI watchdog every hour (since 2026-10-08):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdie006/prodex",
3
- "version": "0.40.30",
3
+ "version": "0.40.31",
4
4
  "description": "Local receipt bus for coordinating Codex execution with ChatGPT Pro/Projects consultation.",
5
5
  "author": "youdie006",
6
6
  "license": "MIT",