Skip to content

Commit ba68635

Browse files
committed
Merge branch 'main' into codex/fix-public-boundary-scan-fixtures-20260917
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
2 parents bcd25ac + ecd1df5 commit ba68635

1 file changed

Lines changed: 65 additions & 12 deletions

File tree

‎examples/personal-workspace-browser/execution-chip.mjs‎

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,64 @@ async function chipText(page) {
9494
return (await page.locator(".personal-execution-chip").innerText()).replace(/\s+/g, " ").trim();
9595
}
9696

97+
const pickerSelector = "div.personal-agent-select button.personal-select-trigger";
98+
99+
async function readPickerLabel(page) {
100+
return (await page.locator(pickerSelector).innerText()).replace(/\s+/g, " ").trim();
101+
}
102+
103+
// What the page resolved, phrased so a failed CI run is diagnosable without a
104+
// local reproduction: the declared endpoint, the adapters the page actually
105+
// received and the label it rendered are the three facts that decide the label.
106+
async function pickerResolution(page) {
107+
const capabilities = await page.evaluate(async () => {
108+
try {
109+
const response = await fetch("/api/chat/capabilities");
110+
const body = await response.json();
111+
return {
112+
status: response.status,
113+
declaredEndpoint: body.manager?.channel_binding?.executor_endpoint ?? null,
114+
adapters: (body.adapters ?? []).map(
115+
(adapter) => `${adapter.agent_id}:${adapter.available ? "available" : "unavailable"}`,
116+
),
117+
};
118+
} catch (error) {
119+
return { status: "unavailable", declaredEndpoint: null, adapters: [], error: String(error) };
120+
}
121+
});
122+
return [
123+
`label=${await readPickerLabel(page)}`,
124+
`declared=${capabilities.declaredEndpoint ?? "<none>"}`,
125+
`adapters=[${capabilities.adapters.join(", ")}]`,
126+
`capabilities=${capabilities.status}${capabilities.error ? ` (${capabilities.error})` : ""}`,
127+
].join(" ");
128+
}
129+
130+
// The picker resolves from the same capabilities response that carries the
131+
// channel binding, and the execution chip only renders once that binding
132+
// lands. A single read therefore asserts on a state the page never promised was
133+
// settled, and it can still hold the pre-fetch Codex fallback. Wait for the
134+
// declared value instead, and name what the page really resolved if the wait
135+
// runs out.
136+
async function waitForPickerLabel(page, settled, timeoutMs = 15_000) {
137+
const deadline = Date.now() + timeoutMs;
138+
let label = await readPickerLabel(page);
139+
while (!settled(label) && Date.now() < deadline) {
140+
await page.waitForTimeout(100);
141+
label = await readPickerLabel(page);
142+
}
143+
if (settled(label)) {
144+
return label;
145+
}
146+
const resolution = await pickerResolution(page);
147+
await page.screenshot({
148+
animations: "disabled",
149+
fullPage: false,
150+
path: resolve(outputDir, "execution-chip-picker-unresolved.png"),
151+
});
152+
throw new Error(`Chat runtime picker never settled: ${resolution}`);
153+
}
154+
97155
async function assertHairlineRow(page) {
98156
const headerBox = await page.locator(".personal-channel-header").boundingBox();
99157
const chipBox = await page.locator(".personal-execution-chip").boundingBox();
@@ -214,12 +272,10 @@ export const executionChipScenario = {
214272
collectCoverage,
215273
});
216274
try {
217-
const pickerLabel = (await stewardPicker.page
218-
.locator("div.personal-agent-select button.personal-select-trigger")
219-
.innerText()).replace(/\s+/g, " ").trim();
220-
if (!pickerLabel.includes("DeepSeek Harness (managed)")) {
221-
throw new Error(`Chat runtime picker ignored the declared steward executor: ${pickerLabel}`);
222-
}
275+
const pickerLabel = await waitForPickerLabel(
276+
stewardPicker.page,
277+
(label) => label.includes("DeepSeek Harness (managed)"),
278+
);
223279
if (pickerLabel.includes("Codex")) {
224280
throw new Error(`Chat runtime picker advertised a discovered CLI as the steward: ${pickerLabel}`);
225281
}
@@ -242,12 +298,9 @@ export const executionChipScenario = {
242298
collectCoverage,
243299
});
244300
try {
245-
const pickerLabel = (await undeclaredSteward.page
246-
.locator("div.personal-agent-select button.personal-select-trigger")
247-
.innerText()).replace(/\s+/g, " ").trim();
248-
if (pickerLabel !== "Chat Codex") {
249-
throw new Error(`An undeclared steward executor no longer used the shipped default: ${pickerLabel}`);
250-
}
301+
// The shipped default is the settled value a machine with no declared
302+
// steward executor must keep.
303+
await waitForPickerLabel(undeclaredSteward.page, (label) => label === "Chat Codex");
251304
} finally {
252305
coverageEntries.push(...await undeclaredSteward.close());
253306
}

0 commit comments

Comments
 (0)