fix: expose web-probe provider candidates (#671)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -921,7 +921,56 @@ async function selectProvider(provider) {
|
|||||||
}
|
}
|
||||||
await page.keyboard.press("Escape").catch(() => null);
|
await page.keyboard.press("Escape").catch(() => null);
|
||||||
}
|
}
|
||||||
throw new Error("provider option not found: " + target + "; attempts=" + JSON.stringify(attempts.slice(-10)));
|
const providerCandidates = await collectProviderCandidates();
|
||||||
|
throw new Error("provider option not found: " + target + "; providerCandidates=" + JSON.stringify(providerCandidates.slice(0, 50)) + "; attempts=" + JSON.stringify(attempts.slice(-10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function collectProviderCandidates() {
|
||||||
|
return page.evaluate(() => {
|
||||||
|
const rows = [];
|
||||||
|
const seen = new Set();
|
||||||
|
const visible = (element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const style = window.getComputedStyle(element);
|
||||||
|
return rect.width > 0 && rect.height > 0 && style.visibility !== "hidden" && style.display !== "none";
|
||||||
|
};
|
||||||
|
const push = (kind, element, value, text) => {
|
||||||
|
const normalizedValue = String(value || "").trim().slice(0, 160);
|
||||||
|
const normalizedText = String(text || "").replace(/\s+/gu, " ").trim().slice(0, 220);
|
||||||
|
const label = `${normalizedValue} ${normalizedText}`.trim();
|
||||||
|
if (!label) return;
|
||||||
|
const key = `${kind}:${label}`.toLowerCase();
|
||||||
|
if (seen.has(key)) return;
|
||||||
|
seen.add(key);
|
||||||
|
rows.push({ kind, value: normalizedValue, text: normalizedText, testId: String(element?.getAttribute?.("data-testid") || "").slice(0, 120), ariaLabel: String(element?.getAttribute?.("aria-label") || "").slice(0, 160) });
|
||||||
|
};
|
||||||
|
for (const select of Array.from(document.querySelectorAll("select")).filter(visible)) {
|
||||||
|
for (const option of Array.from(select.options || [])) push("select-option", select, option.value, option.textContent || "");
|
||||||
|
}
|
||||||
|
const selector = [
|
||||||
|
'[role="option"]',
|
||||||
|
'[role="menuitem"]',
|
||||||
|
'[data-radix-collection-item]',
|
||||||
|
'[data-testid*="provider" i]',
|
||||||
|
'[data-testid*="profile" i]',
|
||||||
|
'[data-testid*="model" i]',
|
||||||
|
'[aria-label*="provider" i]',
|
||||||
|
'[aria-label*="profile" i]',
|
||||||
|
'[aria-label*="model" i]',
|
||||||
|
'[aria-label*="模型"]',
|
||||||
|
'[aria-label*="提供"]',
|
||||||
|
'button'
|
||||||
|
].join(", ");
|
||||||
|
for (const element of Array.from(document.querySelectorAll(selector)).filter(visible)) {
|
||||||
|
const text = String(element.textContent || "").replace(/\s+/gu, " ").trim();
|
||||||
|
const ariaLabel = String(element.getAttribute("aria-label") || "");
|
||||||
|
const testId = String(element.getAttribute("data-testid") || "");
|
||||||
|
const haystack = `${text} ${ariaLabel} ${testId}`;
|
||||||
|
if (!/provider|profile|model|模型|提供|codex|openai|deepseek|gpt|api|flash|spark|claude|gemini|moon/iu.test(haystack)) continue;
|
||||||
|
push("visible-control", element, element.getAttribute("value") || "", text || ariaLabel || testId);
|
||||||
|
}
|
||||||
|
return rows.slice(0, 80);
|
||||||
|
}).catch((error) => [{ kind: "candidate-scan-error", value: "", text: String(error?.message || error).slice(0, 240), testId: "", ariaLabel: "" }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickSession(sessionId) {
|
async function clickSession(sessionId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user