Skip to content

Commit ac063e0

Browse files
committed
Merge remote-tracking branch 'hc/main'
# Conflicts: # AGENTS.md # vite.config.ts
2 parents cc20aca + 5cde80e commit ac063e0

5 files changed

Lines changed: 71 additions & 21 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ xvfb-run -a /snap/bin/chromium \
161161
--disable-translate \
162162
--disable-infobars \
163163
--autoplay-policy=no-user-gesture-required \
164-
"https://www.youtube.com/watch?v=jfKfPfyJRdk"
164+
"https://www.youtube.com/watch?v=X4VbdwhkE10"
165165
```
166166
- That manual path was the one verified on 2026-04-01 for:
167167
- injected YTCF button bar
@@ -173,7 +173,7 @@ xvfb-run -a /snap/bin/chromium \
173173
- `bash scripts/codex-dev.sh status`
174174
- `bash scripts/codex-dev.sh stop`
175175
- Default testbed URL comes from `vite.config.ts`:
176-
- `https://www.youtube.com/watch?v=jfKfPfyJRdk`
176+
- `https://www.youtube.com/watch?v=X4VbdwhkE10`
177177
- Treat `reload` as the default after significant runtime changes to:
178178
- `src/scripts/**`
179179
- `src/components/**`

RELEASE_PROCESS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ xvfb-run -a /snap/bin/chromium \
6969
--disable-translate \
7070
--disable-infobars \
7171
--autoplay-policy=no-user-gesture-required \
72-
"https://www.youtube.com/watch?v=jfKfPfyJRdk"
72+
"https://www.youtube.com/watch?v=X4VbdwhkE10"
7373
```
7474

7575
Build output layout:

scripts/codex-dev.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ detect_repo_scripts() {
4747
resolve_ext_path || true
4848
EXT_PATH="${EXT_PATH:-$REPO_ROOT/build}"
4949
MODE_LABEL="mv3"
50-
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=jfKfPfyJRdk"
50+
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=X4VbdwhkE10"
5151
return 0
5252
fi
5353

@@ -59,7 +59,7 @@ detect_repo_scripts() {
5959
BUILD_NPM_SCRIPT="build"
6060
EXT_PATH="$REPO_ROOT/build"
6161
MODE_LABEL="mv2"
62-
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=5qap5aO4i9A"
62+
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=X4VbdwhkE10"
6363
return 0
6464
fi
6565

@@ -71,7 +71,7 @@ detect_repo_scripts() {
7171
BUILD_NPM_SCRIPT="build"
7272
EXT_PATH="$REPO_ROOT/build"
7373
MODE_LABEL="mv2"
74-
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=5qap5aO4i9A"
74+
DEFAULT_TEST_URL="https://www.youtube.com/watch?v=X4VbdwhkE10"
7575
return 0
7676
fi
7777

scripts/codex-ui-verify.mjs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,12 @@ const cdpCall = async (socketBuf, id, method, params) => {
175175
}
176176
};
177177

178-
const cdpEval = async (socketBuf, id, expression, { awaitPromise = false } = {}) => {
178+
const cdpEval = async (socketBuf, id, expression, { awaitPromise = false, contextId = undefined } = {}) => {
179179
const result = await cdpCall(socketBuf, id, 'Runtime.evaluate', {
180180
expression,
181181
returnByValue: true,
182-
awaitPromise
182+
awaitPromise,
183+
...(contextId === undefined ? {} : { contextId })
183184
});
184185
return result?.result?.value;
185186
};
@@ -208,6 +209,43 @@ const findTarget = async (predicate, label) => {
208209
throw new Error(`Timed out waiting for target: ${label}`);
209210
};
210211

212+
const flattenFrameTree = (frameTree) => {
213+
const out = [frameTree];
214+
for (const child of frameTree.childFrames ?? []) {
215+
out.push(...flattenFrameTree(child));
216+
}
217+
return out;
218+
};
219+
220+
const connectToTargetWithFrameContext = async (targetPredicate, framePredicate, targetLabel, frameLabel) => {
221+
const start = Date.now();
222+
while (Date.now() - start < TIMEOUT_MS) {
223+
const targets = await httpGetJson('/json/list');
224+
for (const target of targets.filter(targetPredicate)) {
225+
let socketBuf;
226+
try {
227+
socketBuf = await connectToTarget(target);
228+
const tree = await cdpCall(socketBuf, 101, 'Page.getFrameTree', {});
229+
const frameNode = flattenFrameTree(tree.frameTree).find((node) => framePredicate(node.frame));
230+
if (!frameNode) {
231+
socketBuf.socket.end();
232+
continue;
233+
}
234+
const world = await cdpCall(socketBuf, 102, 'Page.createIsolatedWorld', {
235+
frameId: frameNode.frame.id,
236+
worldName: 'ytcf-verify',
237+
grantUniveralAccess: true
238+
});
239+
return { socketBuf, contextId: world.executionContextId, target };
240+
} catch {
241+
socketBuf?.socket.destroy();
242+
}
243+
}
244+
await sleep(250);
245+
}
246+
throw new Error(`Timed out waiting for ${targetLabel} with ${frameLabel}`);
247+
};
248+
211249
const clickByText = async (socketBuf, id, text) => {
212250
const expr = `
213251
(() => {
@@ -232,6 +270,16 @@ const waitForSelector = async (socketBuf, id, selector) => {
232270
throw new Error(`Timed out waiting for selector: ${selector}`);
233271
};
234272

273+
const waitForEval = async (socketBuf, id, expression, label, options = {}) => {
274+
const start = Date.now();
275+
while (Date.now() - start < TIMEOUT_MS) {
276+
const ok = await cdpEval(socketBuf, id, expression, options);
277+
if (ok) return true;
278+
await sleep(250);
279+
}
280+
throw new Error(`Timed out waiting for: ${label}`);
281+
};
282+
235283
const main = async () => {
236284
const swTarget = await findTarget(
237285
(t) => t.type === 'service_worker' && typeof t.url === 'string' && t.url.includes('chat-background'),
@@ -281,22 +329,24 @@ const main = async () => {
281329
sw.socket.end();
282330
console.log('storage snapshot:', JSON.stringify(storageSnapshot));
283331

284-
const liveChatTarget = await findTarget(
285-
(t) => typeof t.url === 'string' && t.url.includes('/live_chat') && t.url.includes('jfKfPfyJRdk'),
286-
'live_chat popout'
332+
const { socketBuf: live, contextId: liveContextId } = await connectToTargetWithFrameContext(
333+
(t) => t.type === 'page' && typeof t.url === 'string' && t.url.includes('/watch') && t.url.includes('X4VbdwhkE10'),
334+
(frame) => frame.name === 'chatframe' && frame.url.includes('/live_chat') && frame.url.includes('continuation='),
335+
'youtube watch page',
336+
'embedded live chat frame'
287337
);
288338

289-
const live = await connectToTarget(liveChatTarget);
290-
291339
// Injected bar exists.
292-
const hasButtons = await cdpEval(live, 1, "!!document.querySelector('.ytcf-launch-button')");
293-
const hasMountContainer = await cdpEval(live, 2, "!!document.querySelector('.ytcf-iframe')");
294-
if (!hasButtons || !hasMountContainer) {
295-
throw new Error('Injected YTCF controls not present on live_chat page');
296-
}
340+
await waitForEval(
341+
live,
342+
1,
343+
"!!document.querySelector('.ytcf-launch-button') && !!document.querySelector('.ytcf-iframe')",
344+
'injected YTCF controls on embedded live_chat frame',
345+
{ contextId: liveContextId }
346+
);
297347

298348
// Use "Popout" so the embed surface becomes a top-level CDP target.
299-
await cdpEval(live, 3, "document.querySelector('.ytcf-popout-button')?.click(); true");
349+
await cdpEval(live, 3, "document.querySelector('.ytcf-popout-button')?.click(); true", { contextId: liveContextId });
300350

301351
// First run should redirect the embed to setup.html.
302352
const setupTarget = await findTarget(
@@ -331,7 +381,7 @@ const main = async () => {
331381
ytEmbed.socket.end();
332382

333383
// Open Settings from injected bar.
334-
await cdpEval(live, 30, "document.querySelector('.ytcf-settings-button')?.click(); true");
384+
await cdpEval(live, 30, "document.querySelector('.ytcf-settings-button')?.click(); true", { contextId: liveContextId });
335385
const optionsTarget = await findTarget(
336386
(t) => typeof t.url === 'string' && t.url.includes('options.html'),
337387
'options.html'

vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default defineConfig({
4949
disableAutoLaunch: process.env.AUTOLAUNCH !== 'true',
5050
browser,
5151
webExtConfig: {
52-
startUrl: 'https://www.youtube.com/watch?v=jfKfPfyJRdk'
52+
startUrl: 'https://www.youtube.com/watch?v=X4VbdwhkE10'
5353
},
5454
libModeViteConfig: defineConfig({
5555
build: {

0 commit comments

Comments
 (0)