| 1227 | } |
| 1228 | |
| 1229 | async function waitForUiText(label, text, options = {}) { |
| 1230 | const timeoutMs = options.waitTimeoutMs ?? 5_000; |
| 1231 | const pollMs = options.pollMs ?? 250; |
| 1232 | const startedAt = Date.now(); |
| 1233 | let lastError = ""; |
| 1234 | while (Date.now() - startedAt <= timeoutMs) { |
| 1235 | if (options.expectFixture) { |
| 1236 | try { |
| 1237 | const status = await queryUi(label, { |
| 1238 | selector: { id: "fixture.status" }, |
| 1239 | limit: 1, |
| 1240 | maxDepth: options.maxDepth ?? 3, |
| 1241 | maxElapsedMs: options.queryMaxElapsedMs ?? httpActionBudgetMs, |
| 1242 | }); |
| 1243 | if (JSON.stringify(status.matches ?? []).includes(text)) { |
| 1244 | return status.matches[0]; |
| 1245 | } |
| 1246 | } catch (error) { |
| 1247 | lastError = error?.message ?? String(error); |
| 1248 | } |
| 1249 | } |
| 1250 | for (const selector of [{ label: text }, { value: text }, { id: text }]) { |
| 1251 | try { |
| 1252 | const result = await queryUi(label, { |
| 1253 | selector, |
| 1254 | limit: 1, |
| 1255 | maxDepth: options.maxDepth ?? 3, |
| 1256 | maxElapsedMs: options.queryMaxElapsedMs ?? httpActionBudgetMs, |
| 1257 | }); |
| 1258 | if (result.matches?.length > 0) { |
| 1259 | return result.matches[0]; |
| 1260 | } |
| 1261 | } catch (error) { |
| 1262 | lastError = error?.message ?? String(error); |
| 1263 | } |
| 1264 | } |
| 1265 | await sleep(pollMs); |
| 1266 | } |
| 1267 | throw new Error(`Timed out waiting for UI text "${text}": ${lastError}`); |
| 1268 | } |
| 1269 | |
| 1270 | async function resolveKnownSystemPromptsWithQueries(label) { |
| 1271 | const prompts = [{ kind: "open-url", selector: { label: "Open" } }]; |