@nuanu-ai/agentbrowse 0.2.36 → 0.2.38
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.
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +11 -4
- package/dist/commands/observe-accessibility.d.ts.map +1 -1
- package/dist/commands/observe-accessibility.js +64 -2
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +91 -15
- package/dist/commands/observe-surfaces.d.ts.map +1 -1
- package/dist/commands/observe-surfaces.js +14 -28
- package/dist/commands/semantic-observe-lexical.d.ts +31 -0
- package/dist/commands/semantic-observe-lexical.d.ts.map +1 -0
- package/dist/commands/semantic-observe-lexical.js +188 -0
- package/dist/commands/semantic-observe.d.ts +1 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +183 -97
- package/dist/control-semantics.d.ts.map +1 -1
- package/dist/control-semantics.js +74 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/owned-process.d.ts +3 -0
- package/dist/owned-process.d.ts.map +1 -1
- package/dist/owned-process.js +3 -0
- package/dist/solver/browser-launcher.d.ts +1 -0
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +32 -2
- package/dist/solver/captcha-runtime.d.ts.map +1 -1
- package/dist/solver/captcha-runtime.js +4 -1
- package/package.json +2 -1
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { AgentpayStagehandLlmClient } from '../agentpay-stagehand-llm.js';
|
|
3
3
|
import { resolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
|
|
4
4
|
import { recordLlmUsage, recordPayloadBudget } from '../runtime-state.js';
|
|
5
|
+
import { analyzeSemanticObserveText, buildSemanticObserveBm25CorpusStats, buildSemanticObserveLexicalDocument, normalizeSemanticObserveText, scoreSemanticObserveBm25, } from './semantic-observe-lexical.js';
|
|
5
6
|
const rerankSchema = z.object({
|
|
6
7
|
matches: z
|
|
7
8
|
.array(z.object({
|
|
@@ -17,6 +18,31 @@ const SCOPE_BUCKET_RESERVE_LIMIT = 24;
|
|
|
17
18
|
const SCOPE_BUCKET_RESERVE_PER_BUCKET = 2;
|
|
18
19
|
const IFRAME_BUCKET_RESERVE_LIMIT = 24;
|
|
19
20
|
const IFRAME_BUCKET_RESERVE_PER_BUCKET = 2;
|
|
21
|
+
const RETRIEVAL_FIELD_WEIGHTS = {
|
|
22
|
+
entityLabel: 5.5,
|
|
23
|
+
representativeLabel: 5,
|
|
24
|
+
representativeLabels: 4,
|
|
25
|
+
surfaceLabel: 2.25,
|
|
26
|
+
placeholder: 2.5,
|
|
27
|
+
title: 1.25,
|
|
28
|
+
itemLabel: 2.5,
|
|
29
|
+
itemText: 1.5,
|
|
30
|
+
groupLabel: 1.75,
|
|
31
|
+
groupText: 1,
|
|
32
|
+
containerLabel: 1.5,
|
|
33
|
+
containerText: 0.9,
|
|
34
|
+
landmarkLabel: 1.25,
|
|
35
|
+
landmarkText: 0.75,
|
|
36
|
+
hintText: 1.5,
|
|
37
|
+
kind: 0.6,
|
|
38
|
+
role: 0.6,
|
|
39
|
+
surfaceKind: 0.75,
|
|
40
|
+
controlFamily: 0.9,
|
|
41
|
+
acceptancePolicy: 1,
|
|
42
|
+
allowedActions: 0.9,
|
|
43
|
+
structure: 1.25,
|
|
44
|
+
latentIntent: 1.2,
|
|
45
|
+
};
|
|
20
46
|
const HIGH_SIGNAL_SCOPE_KINDS = new Set([
|
|
21
47
|
'dialog',
|
|
22
48
|
'listbox',
|
|
@@ -29,27 +55,6 @@ const HIGH_SIGNAL_SCOPE_KINDS = new Set([
|
|
|
29
55
|
'card',
|
|
30
56
|
'form',
|
|
31
57
|
]);
|
|
32
|
-
const GOAL_TEXT_STOPWORDS = new Set([
|
|
33
|
-
'a',
|
|
34
|
-
'an',
|
|
35
|
-
'and',
|
|
36
|
-
'at',
|
|
37
|
-
'for',
|
|
38
|
-
'from',
|
|
39
|
-
'in',
|
|
40
|
-
'of',
|
|
41
|
-
'on',
|
|
42
|
-
'or',
|
|
43
|
-
'the',
|
|
44
|
-
'to',
|
|
45
|
-
'with',
|
|
46
|
-
'в',
|
|
47
|
-
'для',
|
|
48
|
-
'и',
|
|
49
|
-
'или',
|
|
50
|
-
'на',
|
|
51
|
-
'найти',
|
|
52
|
-
]);
|
|
53
58
|
function isFieldLikeTarget(target) {
|
|
54
59
|
const kind = (target.kind ?? '').trim().toLowerCase();
|
|
55
60
|
const role = (target.role ?? '').trim().toLowerCase();
|
|
@@ -73,16 +78,6 @@ function isActionLikeTargetCandidate(target) {
|
|
|
73
78
|
kind === 'link' ||
|
|
74
79
|
role === 'link');
|
|
75
80
|
}
|
|
76
|
-
function normalizeRetrievalText(value) {
|
|
77
|
-
const normalized = value?.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
78
|
-
return normalized ? normalized : undefined;
|
|
79
|
-
}
|
|
80
|
-
function tokenizeRetrievalText(value) {
|
|
81
|
-
if (!value) {
|
|
82
|
-
return [];
|
|
83
|
-
}
|
|
84
|
-
return (value.match(/[\p{L}\p{N}]+/gu) ?? []).map((token) => token.toLowerCase());
|
|
85
|
-
}
|
|
86
81
|
function semanticFormContextKey(context) {
|
|
87
82
|
for (const node of [context?.landmark, context?.container, context?.group, context?.item]) {
|
|
88
83
|
const kind = (node?.kind ?? '').trim().toLowerCase();
|
|
@@ -140,6 +135,13 @@ function isPrimaryFormControlTarget(target) {
|
|
|
140
135
|
acceptancePolicy === 'disclosure' &&
|
|
141
136
|
(kind === 'button' || role === 'button'));
|
|
142
137
|
}
|
|
138
|
+
function shouldPreserveStandaloneFormActionEntity(target) {
|
|
139
|
+
return (Boolean(formBucketKey(target)) &&
|
|
140
|
+
!isScopeLikeCandidate(target) &&
|
|
141
|
+
!isFieldLikeTarget(target) &&
|
|
142
|
+
isActionLikeTargetCandidate(target) &&
|
|
143
|
+
isPrimaryFormControlTarget(target));
|
|
144
|
+
}
|
|
143
145
|
function primaryFormTargetPriority(target) {
|
|
144
146
|
const acceptancePolicy = (target.acceptancePolicy ?? '').trim().toLowerCase();
|
|
145
147
|
if (isFieldLikeTarget(target)) {
|
|
@@ -178,11 +180,11 @@ function contentItemBucketKey(target) {
|
|
|
178
180
|
if (surfaceIdentity) {
|
|
179
181
|
return `surface:${surfaceIdentity}`;
|
|
180
182
|
}
|
|
181
|
-
const itemKey =
|
|
183
|
+
const itemKey = normalizeSemanticObserveText(target.context?.item?.label ?? target.context?.item?.text);
|
|
182
184
|
if (itemKey) {
|
|
183
185
|
return `item:${itemKey}`;
|
|
184
186
|
}
|
|
185
|
-
const containerKey =
|
|
187
|
+
const containerKey = normalizeSemanticObserveText(target.context?.container?.label ?? target.context?.container?.text);
|
|
186
188
|
if (containerKey) {
|
|
187
189
|
return `container:${containerKey}`;
|
|
188
190
|
}
|
|
@@ -205,7 +207,7 @@ function scopeCandidatePriority(target) {
|
|
|
205
207
|
return 4;
|
|
206
208
|
}
|
|
207
209
|
function representativeCandidateScore(target) {
|
|
208
|
-
const normalizedLabel =
|
|
210
|
+
const normalizedLabel = normalizeSemanticObserveText(target.label);
|
|
209
211
|
const kind = (target.kind ?? '').trim().toLowerCase();
|
|
210
212
|
const role = (target.role ?? '').trim().toLowerCase();
|
|
211
213
|
let score = (target.surfacePriority ?? 0) * 10;
|
|
@@ -295,26 +297,131 @@ function collectRepresentativeLabels(targets) {
|
|
|
295
297
|
}
|
|
296
298
|
return labels;
|
|
297
299
|
}
|
|
298
|
-
function
|
|
300
|
+
function structureLexicalValue(structure) {
|
|
301
|
+
if (!structure) {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
299
304
|
return [
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
representative.context?.group?.label,
|
|
307
|
-
representative.context?.group?.text,
|
|
308
|
-
representative.context?.container?.label,
|
|
309
|
-
representative.context?.container?.text,
|
|
310
|
-
representative.context?.landmark?.label,
|
|
311
|
-
representative.context?.landmark?.text,
|
|
312
|
-
representative.context?.hintText,
|
|
305
|
+
structure.family,
|
|
306
|
+
structure.variant,
|
|
307
|
+
structure.row,
|
|
308
|
+
structure.column,
|
|
309
|
+
structure.zone,
|
|
310
|
+
structure.cellLabel,
|
|
313
311
|
]
|
|
314
|
-
.
|
|
315
|
-
.filter((value) => Boolean(value))
|
|
312
|
+
.filter(Boolean)
|
|
316
313
|
.join(' ');
|
|
317
314
|
}
|
|
315
|
+
function latentActionHintText(target) {
|
|
316
|
+
const acceptancePolicy = (target.acceptancePolicy ?? '').trim().toLowerCase();
|
|
317
|
+
const controlFamily = (target.controlFamily ?? '').trim().toLowerCase();
|
|
318
|
+
const surfaceKind = (target.surfaceKind ?? '').trim().toLowerCase();
|
|
319
|
+
const kind = (target.kind ?? '').trim().toLowerCase();
|
|
320
|
+
const role = (target.role ?? '').trim().toLowerCase();
|
|
321
|
+
const popupBacked = acceptancePolicy === 'disclosure' ||
|
|
322
|
+
Boolean(target.controlsSurfaceSelector) ||
|
|
323
|
+
target.states?.expanded !== undefined;
|
|
324
|
+
if (!popupBacked) {
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
const hints = new Set();
|
|
328
|
+
hints.add('open menu options choices');
|
|
329
|
+
if (!isFieldLikeTarget(target)) {
|
|
330
|
+
hints.add('sort sorting filter filters view switch picker');
|
|
331
|
+
}
|
|
332
|
+
if (controlFamily === 'select' ||
|
|
333
|
+
['menu', 'listbox', 'dropdown', 'popover'].includes(surfaceKind)) {
|
|
334
|
+
hints.add('select choose option options menu dropdown listbox');
|
|
335
|
+
}
|
|
336
|
+
if (controlFamily === 'datepicker' || surfaceKind === 'datepicker') {
|
|
337
|
+
hints.add('open calendar datepicker date picker choose date calendar');
|
|
338
|
+
}
|
|
339
|
+
const evidenceText = [
|
|
340
|
+
target.label,
|
|
341
|
+
target.placeholder,
|
|
342
|
+
target.title,
|
|
343
|
+
target.surfaceLabel,
|
|
344
|
+
target.context?.group?.label,
|
|
345
|
+
target.context?.container?.label,
|
|
346
|
+
target.context?.landmark?.label,
|
|
347
|
+
target.context?.hintText,
|
|
348
|
+
]
|
|
349
|
+
.filter((value) => Boolean(value))
|
|
350
|
+
.join(' ')
|
|
351
|
+
.toLowerCase();
|
|
352
|
+
if (/(?:sort|sorting|show first|ordered by|order by|popular|relevance|recommended|price|cheap|cheapest|expensive|сорт|сначала|популяр|релевант|рекоменд|цене|дешев|дорог)/i.test(evidenceText)) {
|
|
353
|
+
hints.add('sort sorting order order by relevance popular recommended price cheapest cheapest first');
|
|
354
|
+
}
|
|
355
|
+
if (/(?:filter|filters|refine|brand|airline|amenit|фильтр|фильтры|бренд|авиакомпан|удобств)/i.test(evidenceText)) {
|
|
356
|
+
hints.add('filter filters refine refine results brand airline amenities');
|
|
357
|
+
}
|
|
358
|
+
if (/(?:view|layout|grid|list|map|calendar view|вид|список|сетка|карта|раскладк)/i.test(evidenceText)) {
|
|
359
|
+
hints.add('view layout grid list map switch');
|
|
360
|
+
}
|
|
361
|
+
if (kind === 'button' &&
|
|
362
|
+
role === 'button' &&
|
|
363
|
+
(acceptancePolicy === 'disclosure' || controlFamily === 'select' || controlFamily === 'datepicker')) {
|
|
364
|
+
hints.add('open selector choose mode');
|
|
365
|
+
}
|
|
366
|
+
return hints.size > 0 ? [...hints].join(' ') : undefined;
|
|
367
|
+
}
|
|
368
|
+
function buildEntityLexicalFields(entityLabel, representative, representativeLabels) {
|
|
369
|
+
return [
|
|
370
|
+
{ value: entityLabel, weight: RETRIEVAL_FIELD_WEIGHTS.entityLabel },
|
|
371
|
+
{ value: representative.label, weight: RETRIEVAL_FIELD_WEIGHTS.representativeLabel },
|
|
372
|
+
...representativeLabels.map((value) => ({
|
|
373
|
+
value,
|
|
374
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.representativeLabels,
|
|
375
|
+
})),
|
|
376
|
+
{ value: representative.surfaceLabel, weight: RETRIEVAL_FIELD_WEIGHTS.surfaceLabel },
|
|
377
|
+
{ value: representative.placeholder, weight: RETRIEVAL_FIELD_WEIGHTS.placeholder },
|
|
378
|
+
{ value: representative.title, weight: RETRIEVAL_FIELD_WEIGHTS.title },
|
|
379
|
+
{ value: representative.context?.item?.label, weight: RETRIEVAL_FIELD_WEIGHTS.itemLabel },
|
|
380
|
+
{ value: representative.context?.item?.text, weight: RETRIEVAL_FIELD_WEIGHTS.itemText },
|
|
381
|
+
{ value: representative.context?.group?.label, weight: RETRIEVAL_FIELD_WEIGHTS.groupLabel },
|
|
382
|
+
{ value: representative.context?.group?.text, weight: RETRIEVAL_FIELD_WEIGHTS.groupText },
|
|
383
|
+
{
|
|
384
|
+
value: representative.context?.container?.label,
|
|
385
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.containerLabel,
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
value: representative.context?.container?.text,
|
|
389
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.containerText,
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
value: representative.context?.landmark?.label,
|
|
393
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.landmarkLabel,
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
value: representative.context?.landmark?.text,
|
|
397
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.landmarkText,
|
|
398
|
+
},
|
|
399
|
+
{ value: representative.context?.hintText, weight: RETRIEVAL_FIELD_WEIGHTS.hintText },
|
|
400
|
+
{ value: representative.kind, weight: RETRIEVAL_FIELD_WEIGHTS.kind },
|
|
401
|
+
{ value: representative.role, weight: RETRIEVAL_FIELD_WEIGHTS.role },
|
|
402
|
+
{ value: representative.surfaceKind, weight: RETRIEVAL_FIELD_WEIGHTS.surfaceKind },
|
|
403
|
+
{
|
|
404
|
+
value: representative.controlFamily,
|
|
405
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.controlFamily,
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
value: representative.acceptancePolicy,
|
|
409
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.acceptancePolicy,
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
value: representative.allowedActions?.join(' '),
|
|
413
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.allowedActions,
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
value: structureLexicalValue(representative.structure),
|
|
417
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.structure,
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
value: latentActionHintText(representative),
|
|
421
|
+
weight: RETRIEVAL_FIELD_WEIGHTS.latentIntent,
|
|
422
|
+
},
|
|
423
|
+
];
|
|
424
|
+
}
|
|
318
425
|
function buildGoalRetrievalEntity(entityKind, entityKey, memberIndexes, targets) {
|
|
319
426
|
const orderedMembers = [...memberIndexes]
|
|
320
427
|
.map((index) => ({ index, target: targets[index] }))
|
|
@@ -322,6 +429,8 @@ function buildGoalRetrievalEntity(entityKind, entityKey, memberIndexes, targets)
|
|
|
322
429
|
const representative = orderedMembers[0].target;
|
|
323
430
|
const representativeLabels = collectRepresentativeLabels(orderedMembers.map((entry) => entry.target));
|
|
324
431
|
const label = pickEntityLabel(entityKind, representative);
|
|
432
|
+
const lexicalFields = buildEntityLexicalFields(label, representative, representativeLabels);
|
|
433
|
+
const lexicalDocument = buildSemanticObserveLexicalDocument(lexicalFields);
|
|
325
434
|
return {
|
|
326
435
|
entityKind,
|
|
327
436
|
entityKey,
|
|
@@ -342,7 +451,8 @@ function buildGoalRetrievalEntity(entityKind, entityKey, memberIndexes, targets)
|
|
|
342
451
|
context: representative.context,
|
|
343
452
|
structure: representative.structure,
|
|
344
453
|
representativeLabels,
|
|
345
|
-
|
|
454
|
+
analyzerKey: lexicalDocument.analyzerKey,
|
|
455
|
+
lexicalDocument,
|
|
346
456
|
};
|
|
347
457
|
}
|
|
348
458
|
function buildGoalRetrievalEntities(targets) {
|
|
@@ -376,7 +486,12 @@ function buildGoalRetrievalEntities(targets) {
|
|
|
376
486
|
}
|
|
377
487
|
for (const [key, memberIndexes] of formGroups.entries()) {
|
|
378
488
|
entities.push(buildGoalRetrievalEntity('form', `form:${key}`, memberIndexes, targets));
|
|
379
|
-
memberIndexes.forEach((index) =>
|
|
489
|
+
memberIndexes.forEach((index) => {
|
|
490
|
+
if (shouldPreserveStandaloneFormActionEntity(targets[index])) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
groupedTargetIndexes.add(index);
|
|
494
|
+
});
|
|
380
495
|
}
|
|
381
496
|
const itemGroups = new Map();
|
|
382
497
|
for (const [index, target] of targets.entries()) {
|
|
@@ -445,58 +560,28 @@ function retrievalEntityPriority(entity) {
|
|
|
445
560
|
score += representativeCandidateScore(entity.representative);
|
|
446
561
|
return score;
|
|
447
562
|
}
|
|
448
|
-
function scoreRetrievalEntityAgainstGoal(
|
|
449
|
-
|
|
450
|
-
if (!normalizedGoal) {
|
|
563
|
+
function scoreRetrievalEntityAgainstGoal(analyzedGoal, entity, corpusStats) {
|
|
564
|
+
if (!analyzedGoal.normalizedText) {
|
|
451
565
|
return 0;
|
|
452
566
|
}
|
|
453
|
-
|
|
454
|
-
if (!entityText) {
|
|
567
|
+
if (entity.lexicalDocument.weightedLength <= 0) {
|
|
455
568
|
return 0;
|
|
456
569
|
}
|
|
457
|
-
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
const entityLabel = normalizeRetrievalText(entity.label);
|
|
464
|
-
if (entityLabel) {
|
|
465
|
-
if (normalizedGoal.includes(entityLabel)) {
|
|
466
|
-
score += 180;
|
|
467
|
-
}
|
|
468
|
-
if (entityLabel.includes(normalizedGoal)) {
|
|
469
|
-
score += 140;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
let matchedTokenCount = 0;
|
|
473
|
-
for (const token of goalTokens) {
|
|
474
|
-
if (entityTokens.has(token)) {
|
|
475
|
-
matchedTokenCount += 1;
|
|
476
|
-
score += 8 + Math.min(token.length, 12);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
if (goalTokens.length > 0) {
|
|
480
|
-
const coverage = matchedTokenCount / goalTokens.length;
|
|
481
|
-
if (coverage === 1) {
|
|
482
|
-
score += 120;
|
|
483
|
-
}
|
|
484
|
-
else if (coverage >= 0.75) {
|
|
485
|
-
score += 70;
|
|
486
|
-
}
|
|
487
|
-
else if (coverage >= 0.5) {
|
|
488
|
-
score += 35;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
return score;
|
|
570
|
+
const bm25Score = scoreSemanticObserveBm25(analyzedGoal, entity.lexicalDocument, corpusStats);
|
|
571
|
+
const analyzerAlignmentScore = analyzedGoal.analyzerKey !== 'neutral' && analyzedGoal.analyzerKey === entity.analyzerKey
|
|
572
|
+
? 15
|
|
573
|
+
: 0;
|
|
574
|
+
return bm25Score * 100 + analyzerAlignmentScore;
|
|
492
575
|
}
|
|
493
576
|
function preselectRetrievalEntities(goal, entities) {
|
|
494
577
|
if (entities.length <= GOAL_RETRIEVAL_ENTITY_LIMIT) {
|
|
495
578
|
return [...entities];
|
|
496
579
|
}
|
|
580
|
+
const analyzedGoal = analyzeSemanticObserveText(goal);
|
|
581
|
+
const corpusStats = buildSemanticObserveBm25CorpusStats(entities.map((entity) => entity.lexicalDocument));
|
|
497
582
|
const scored = entities.map((entity) => ({
|
|
498
583
|
entity,
|
|
499
|
-
lexicalScore: scoreRetrievalEntityAgainstGoal(
|
|
584
|
+
lexicalScore: scoreRetrievalEntityAgainstGoal(analyzedGoal, entity, corpusStats),
|
|
500
585
|
priority: retrievalEntityPriority(entity),
|
|
501
586
|
}));
|
|
502
587
|
const selected = [];
|
|
@@ -634,9 +719,6 @@ function diversifyCandidates(targets) {
|
|
|
634
719
|
}
|
|
635
720
|
return orderedIndexes.map((index) => targets[index]).slice(0, RERANK_CANDIDATE_LIMIT);
|
|
636
721
|
}
|
|
637
|
-
function buildCandidateSummary(target, index, surfaceSummaryIdBySurfaceKey) {
|
|
638
|
-
return buildCompactCandidateSummary(target, index, surfaceSummaryIdBySurfaceKey);
|
|
639
|
-
}
|
|
640
722
|
function compactContextValue(value, maxLength = 80) {
|
|
641
723
|
const normalized = value?.replace(/\s+/g, ' ').trim();
|
|
642
724
|
if (!normalized) {
|
|
@@ -791,6 +873,9 @@ function buildCompactCandidateSummary(target, index, surfaceSummaryIdBySurfaceKe
|
|
|
791
873
|
if (target.controlFamily) {
|
|
792
874
|
parts.push(`family=${JSON.stringify(target.controlFamily)}`);
|
|
793
875
|
}
|
|
876
|
+
if (target.controlsSurfaceSelector) {
|
|
877
|
+
parts.push('controlsPopup=true');
|
|
878
|
+
}
|
|
794
879
|
if (target.capability && target.capability !== 'actionable') {
|
|
795
880
|
parts.push(`capability=${JSON.stringify(target.capability)}`);
|
|
796
881
|
}
|
|
@@ -836,6 +921,7 @@ export async function rerankDomTargetsForGoal(instruction, targets, options = {}
|
|
|
836
921
|
const prompt = [
|
|
837
922
|
'You are choosing from already discovered visible webpage candidates.',
|
|
838
923
|
'Select only candidate IDs that directly satisfy the goal.',
|
|
924
|
+
'A disclosure trigger with a current-state label can still directly satisfy sort, filter, view-switch, or picker goals when opening it is the immediate next step.',
|
|
839
925
|
'Prefer direct actionable controls over surrounding regions unless the goal explicitly asks for a form, region, widget, or set of controls.',
|
|
840
926
|
'Use owning surface, compact context, explicit state, and structure metadata to disambiguate similar labels.',
|
|
841
927
|
'For input/value goals, prefer the directly editable field or primary picker trigger over wrappers or mirrored summary content.',
|
|
@@ -847,7 +933,7 @@ export async function rerankDomTargetsForGoal(instruction, targets, options = {}
|
|
|
847
933
|
'',
|
|
848
934
|
...(surfaceSummaries.length > 0 ? ['Surfaces:', ...surfaceSummaries.map((entry) => entry.line), ''] : []),
|
|
849
935
|
'Candidates:',
|
|
850
|
-
...candidates.map((target, index) =>
|
|
936
|
+
...candidates.map((target, index) => buildCompactCandidateSummary(target, index, summaryIdBySurfaceKey)),
|
|
851
937
|
].join('\n');
|
|
852
938
|
const result = await client.createChatCompletion({
|
|
853
939
|
logger: () => { },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-semantics.d.ts","sourceRoot":"","sources":["../src/control-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"control-semantics.d.ts","sourceRoot":"","sources":["../src/control-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAwCtF,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,oBAAoB,GAC1B,mBAAmB,GAAG,SAAS,CAuCjC;AAyID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAYxE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,oBAAoB,GAAG,mBAAmB,EAAE,CAoG/F;AAED,wBAAgB,0BAA0B,CACxC,MAAM,CAAC,EAAE,gBAAgB,EACzB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B,GACL,uBAAuB,CAyBzB;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,mBAAmB,GAAG,SAAS,CA0EjC;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,sBAAsB,GAAG,SAAS,CA6CpC"}
|
|
@@ -83,6 +83,76 @@ function isButtonLikeInputFacts(facts) {
|
|
|
83
83
|
return (normalizeText(facts.kind) === 'input' &&
|
|
84
84
|
['button', 'submit', 'reset'].includes(normalizeText(facts.inputType)));
|
|
85
85
|
}
|
|
86
|
+
function isSelectionItemLikeFacts(facts) {
|
|
87
|
+
const kind = normalizeText(facts.kind);
|
|
88
|
+
const role = normalizeText(facts.role);
|
|
89
|
+
return (kind === 'option' ||
|
|
90
|
+
role === 'option' ||
|
|
91
|
+
role === 'menuitem' ||
|
|
92
|
+
facts.structure?.family === 'structured-grid');
|
|
93
|
+
}
|
|
94
|
+
function isBinaryToggleControlFacts(facts) {
|
|
95
|
+
const kind = normalizeText(facts.kind);
|
|
96
|
+
const role = normalizeText(facts.role);
|
|
97
|
+
const inputType = normalizeText(facts.inputType);
|
|
98
|
+
return (kind === 'checkbox' ||
|
|
99
|
+
kind === 'radio' ||
|
|
100
|
+
role === 'checkbox' ||
|
|
101
|
+
role === 'radio' ||
|
|
102
|
+
role === 'switch' ||
|
|
103
|
+
kind === 'tab' ||
|
|
104
|
+
role === 'tab' ||
|
|
105
|
+
inputType === 'checkbox' ||
|
|
106
|
+
inputType === 'radio');
|
|
107
|
+
}
|
|
108
|
+
function isDisclosureLikeTriggerFacts(facts, controlFamily) {
|
|
109
|
+
const kind = normalizeText(facts.kind);
|
|
110
|
+
const role = normalizeText(facts.role);
|
|
111
|
+
const inputType = normalizeText(facts.inputType);
|
|
112
|
+
const popupBacked = Boolean(facts.controlsSurfaceSelector) ||
|
|
113
|
+
facts.states?.expanded !== undefined;
|
|
114
|
+
if (!popupBacked) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (isSelectionItemLikeFacts(facts) || controlFamily === 'text-input') {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (controlFamily === 'select' || controlFamily === 'datepicker') {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
return (kind === 'button' ||
|
|
124
|
+
role === 'button' ||
|
|
125
|
+
kind === 'link' ||
|
|
126
|
+
role === 'link' ||
|
|
127
|
+
kind === 'combobox' ||
|
|
128
|
+
role === 'combobox' ||
|
|
129
|
+
kind === 'select' ||
|
|
130
|
+
isButtonLikeInputFacts(facts) ||
|
|
131
|
+
inputType === 'button' ||
|
|
132
|
+
isPopupBackedTextEntry(facts));
|
|
133
|
+
}
|
|
134
|
+
function isToggleLikeControlFacts(facts, controlFamily) {
|
|
135
|
+
const states = facts.states;
|
|
136
|
+
if (!states) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
if (states.checked !== undefined || isBinaryToggleControlFacts(facts)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (states.selected !== undefined) {
|
|
143
|
+
if (isSelectionItemLikeFacts(facts) ||
|
|
144
|
+
controlFamily === 'select' ||
|
|
145
|
+
controlFamily === 'datepicker' ||
|
|
146
|
+
isDisclosureLikeTriggerFacts(facts, controlFamily)) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
if (states.pressed !== undefined) {
|
|
152
|
+
return !isDisclosureLikeTriggerFacts(facts, controlFamily);
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
86
156
|
export function isLikelyDateLikeLabel(value) {
|
|
87
157
|
const trimmed = (value ?? '').trim();
|
|
88
158
|
if (!trimmed) {
|
|
@@ -280,17 +350,15 @@ export function inferAcceptancePolicyFromFacts(facts, allowedActions) {
|
|
|
280
350
|
if (facts.structure?.family === 'structured-grid') {
|
|
281
351
|
return facts.structure.variant === 'date-cell' ? 'date-selection' : 'selection';
|
|
282
352
|
}
|
|
283
|
-
if (states?.checked !== undefined ||
|
|
284
|
-
states?.selected !== undefined ||
|
|
285
|
-
states?.pressed !== undefined) {
|
|
286
|
-
return 'toggle';
|
|
287
|
-
}
|
|
288
353
|
if (controlFamily === 'text-input') {
|
|
289
354
|
return 'value-change';
|
|
290
355
|
}
|
|
291
|
-
if (
|
|
356
|
+
if (isDisclosureLikeTriggerFacts(facts, controlFamily)) {
|
|
292
357
|
return 'disclosure';
|
|
293
358
|
}
|
|
359
|
+
if (isToggleLikeControlFacts(facts, controlFamily)) {
|
|
360
|
+
return 'toggle';
|
|
361
|
+
}
|
|
294
362
|
if (controlFamily === 'datepicker') {
|
|
295
363
|
return 'date-selection';
|
|
296
364
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4QA,iBAAe,IAAI,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4KhE;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAEhB,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAWzF"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
loadEnv();
|
|
6
6
|
import { preflightAgentpayGateway } from './agentpay-gateway.js';
|
|
7
7
|
import { browseCommand, browseCommandName } from './command-name.js';
|
|
8
|
+
import { assertSemanticObserveRuntimeSupport } from './commands/semantic-observe-lexical.js';
|
|
8
9
|
import { loadSession } from './session.js';
|
|
9
10
|
import { outputError, outputJSON, fatal, info } from './output.js';
|
|
10
11
|
import { applyDemoProxyBootstrap } from './solver/config.js';
|
|
@@ -223,6 +224,12 @@ async function main(argv = process.argv) {
|
|
|
223
224
|
if (!KNOWN_COMMANDS.has(command)) {
|
|
224
225
|
outputError(`Unknown command: ${command}\n\n${usageText()}`);
|
|
225
226
|
}
|
|
227
|
+
try {
|
|
228
|
+
assertSemanticObserveRuntimeSupport();
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
outputError(err instanceof Error ? err.message : String(err));
|
|
232
|
+
}
|
|
226
233
|
if (command !== 'init') {
|
|
227
234
|
try {
|
|
228
235
|
await preflightAgentpayGateway();
|
package/dist/owned-process.d.ts
CHANGED
|
@@ -11,4 +11,7 @@ export declare function cleanupManagedBrowserPids(options?: {
|
|
|
11
11
|
export declare function listManagedBrowserPids(options?: {
|
|
12
12
|
processTable?: string;
|
|
13
13
|
}): number[];
|
|
14
|
+
export declare function isManagedBrowserPid(pid: number, options?: {
|
|
15
|
+
processTable?: string;
|
|
16
|
+
}): boolean;
|
|
14
17
|
//# sourceMappingURL=owned-process.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"owned-process.d.ts","sourceRoot":"","sources":["../src/owned-process.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,yBAAyB,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,CAAC;AACjG,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW/C;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAOvF;AAiCD,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;CAAO,GAC/C,OAAO,CAAC,2BAA2B,CAAC,CAqBtC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,MAAM,EAAE,CAuBV"}
|
|
1
|
+
{"version":3,"file":"owned-process.d.ts","sourceRoot":"","sources":["../src/owned-process.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,yBAAyB,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,CAAC;AACjG,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW/C;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAOvF;AAiCD,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;CAAO,GAC/C,OAAO,CAAC,2BAA2B,CAAC,CAqBtC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,MAAM,EAAE,CAuBV;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,OAAO,CAET"}
|
package/dist/owned-process.js
CHANGED
|
@@ -93,6 +93,9 @@ export function listManagedBrowserPids(options = {}) {
|
|
|
93
93
|
}
|
|
94
94
|
return Array.from(pids);
|
|
95
95
|
}
|
|
96
|
+
export function isManagedBrowserPid(pid, options = {}) {
|
|
97
|
+
return listManagedBrowserPids(options).includes(pid);
|
|
98
|
+
}
|
|
96
99
|
async function waitForPidExit(pid, attempts, intervalMs) {
|
|
97
100
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
98
101
|
if (!isPidAlive(pid)) {
|
|
@@ -10,4 +10,5 @@ export type SolverSession = {
|
|
|
10
10
|
disconnect: () => Promise<void>;
|
|
11
11
|
};
|
|
12
12
|
export declare function launchSolver(profile: ProfileInfo, opts?: LaunchOptions): Promise<SolverSession>;
|
|
13
|
+
export declare function chromeArgsForEnvironment(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string[];
|
|
13
14
|
//# sourceMappingURL=browser-launcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-launcher.d.ts","sourceRoot":"","sources":["../../src/solver/browser-launcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAsB,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-launcher.d.ts","sourceRoot":"","sources":["../../src/solver/browser-launcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAsB,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgBjF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAuBF,wBAAsB,YAAY,CAChC,OAAO,EAAE,WAAW,EACpB,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,aAAa,CAAC,CAmExB;AA8TD,wBAAgB,wBAAwB,CACtC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAGV"}
|
|
@@ -6,11 +6,20 @@ import puppeteerExtra from 'puppeteer-extra';
|
|
|
6
6
|
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
|
|
7
7
|
import { buildTurnstileApiShimSource, isTurnstileApiRequest } from './turnstile-challenge.js';
|
|
8
8
|
const enhancedPuppeteer = puppeteerExtra;
|
|
9
|
-
|
|
9
|
+
const solverStealthPlugin = StealthPlugin();
|
|
10
|
+
// Some iframe-backed checkout flows break when this evasion runs on a connected real Chrome.
|
|
11
|
+
solverStealthPlugin.enabledEvasions.delete('iframe.contentWindow');
|
|
12
|
+
enhancedPuppeteer.use(solverStealthPlugin);
|
|
10
13
|
const AUTO_CDP_PORT = 0;
|
|
11
14
|
const CDP_DISCOVERY_TIMEOUT_MS = 30_000;
|
|
12
15
|
const CDP_DISCOVERY_INTERVAL_MS = 500;
|
|
16
|
+
const BROWSER_DISCONNECT_TIMEOUT_MS = 1_000;
|
|
13
17
|
const INTERCEPTED_PAGES = new WeakSet();
|
|
18
|
+
const LINUX_CI_CHROME_ARGS = [
|
|
19
|
+
'--no-sandbox',
|
|
20
|
+
'--disable-setuid-sandbox',
|
|
21
|
+
'--disable-dev-shm-usage',
|
|
22
|
+
];
|
|
14
23
|
const CHROME_PATHS = [
|
|
15
24
|
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
16
25
|
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
|
|
@@ -30,6 +39,7 @@ export async function launchSolver(profile, opts) {
|
|
|
30
39
|
const cdpUrl = await discoverCdpUrl({
|
|
31
40
|
requestedPort: opts?.cdpPort,
|
|
32
41
|
userDataDir: profile.userDataDir,
|
|
42
|
+
chromeProcess,
|
|
33
43
|
});
|
|
34
44
|
if (!cdpUrl) {
|
|
35
45
|
throw buildCdpDiscoveryError(chromeProcess, opts?.cdpPort, profile.userDataDir);
|
|
@@ -63,7 +73,7 @@ export async function launchSolver(profile, opts) {
|
|
|
63
73
|
profile,
|
|
64
74
|
close: async () => {
|
|
65
75
|
try {
|
|
66
|
-
await browser
|
|
76
|
+
await disconnectBrowserWithinTimeout(browser, BROWSER_DISCONNECT_TIMEOUT_MS);
|
|
67
77
|
}
|
|
68
78
|
finally {
|
|
69
79
|
terminateProcessGroup(chromeProcess.pid);
|
|
@@ -96,10 +106,25 @@ async function discoverCdpUrl(options) {
|
|
|
96
106
|
return discoveredViaActivePort;
|
|
97
107
|
}
|
|
98
108
|
}
|
|
109
|
+
if (typeof options.chromeProcess?.exitCode === 'number' || options.chromeProcess?.signalCode) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
99
112
|
await sleep(CDP_DISCOVERY_INTERVAL_MS);
|
|
100
113
|
}
|
|
101
114
|
return null;
|
|
102
115
|
}
|
|
116
|
+
async function disconnectBrowserWithinTimeout(browser, timeoutMs) {
|
|
117
|
+
let timeoutId;
|
|
118
|
+
await Promise.race([
|
|
119
|
+
browser.disconnect().catch(() => { }),
|
|
120
|
+
new Promise((resolve) => {
|
|
121
|
+
timeoutId = setTimeout(resolve, timeoutMs);
|
|
122
|
+
}),
|
|
123
|
+
]);
|
|
124
|
+
if (timeoutId) {
|
|
125
|
+
clearTimeout(timeoutId);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
103
128
|
async function discoverCdpUrlOnPort(port) {
|
|
104
129
|
try {
|
|
105
130
|
const res = await fetch(`http://127.0.0.1:${port}/json/version`);
|
|
@@ -290,6 +315,7 @@ function spawnChromeProcess(executablePath, profile, fp, cdpPort, windowSize, he
|
|
|
290
315
|
'--no-first-run',
|
|
291
316
|
'--no-default-browser-check',
|
|
292
317
|
];
|
|
318
|
+
args.push(...chromeArgsForEnvironment());
|
|
293
319
|
if (headless) {
|
|
294
320
|
args.push('--headless=new');
|
|
295
321
|
}
|
|
@@ -311,6 +337,10 @@ function spawnChromeProcess(executablePath, profile, fp, cdpPort, windowSize, he
|
|
|
311
337
|
}
|
|
312
338
|
return proc;
|
|
313
339
|
}
|
|
340
|
+
export function chromeArgsForEnvironment(platform = process.platform, env = process.env) {
|
|
341
|
+
const isLinuxCi = platform === 'linux' && (env.CI === 'true' || env.GITHUB_ACTIONS === 'true');
|
|
342
|
+
return isLinuxCi ? [...LINUX_CI_CHROME_ARGS] : [];
|
|
343
|
+
}
|
|
314
344
|
function terminateProcessGroup(pid) {
|
|
315
345
|
try {
|
|
316
346
|
process.kill(-pid, 'SIGTERM');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captcha-runtime.d.ts","sourceRoot":"","sources":["../../src/solver/captcha-runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAMF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,yBAAyB,GAC/B,OAAO,CAAC,wBAAwB,CAAC,
|
|
1
|
+
{"version":3,"file":"captcha-runtime.d.ts","sourceRoot":"","sources":["../../src/solver/captcha-runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAMF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,yBAAyB,GAC/B,OAAO,CAAC,wBAAwB,CAAC,CAgInC"}
|