@geometra/mcp 1.63.2 → 1.65.0
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/README.md +29 -7
- package/dist/index.js +2 -5
- package/dist/proxy-spawn.d.ts +29 -0
- package/dist/proxy-spawn.js +49 -17
- package/dist/server.js +1557 -526
- package/dist/session-state.js +262 -80
- package/dist/session.d.ts +189 -13
- package/dist/session.js +1600 -319
- package/dist/state-privacy.d.ts +23 -0
- package/dist/state-privacy.js +171 -0
- package/dist/version.d.ts +6 -0
- package/dist/version.js +32 -0
- package/package.json +4 -4
package/dist/session.d.ts
CHANGED
|
@@ -29,10 +29,29 @@ export interface A11yNode {
|
|
|
29
29
|
scrollX?: number;
|
|
30
30
|
scrollY?: number;
|
|
31
31
|
controlTag?: string;
|
|
32
|
+
/** Stable authored DOM identity emitted by the proxy extractor (`id:` or `name:`). */
|
|
33
|
+
controlKey?: string;
|
|
34
|
+
controlId?: string;
|
|
35
|
+
controlName?: string;
|
|
36
|
+
options?: Array<{
|
|
37
|
+
value: string;
|
|
38
|
+
label: string;
|
|
39
|
+
disabled: boolean;
|
|
40
|
+
selected: boolean;
|
|
41
|
+
index: number;
|
|
42
|
+
}>;
|
|
32
43
|
placeholder?: string;
|
|
33
44
|
inputPattern?: string;
|
|
34
45
|
inputType?: string;
|
|
35
46
|
autocomplete?: string;
|
|
47
|
+
/** True when this semantic node represents an `<input type="file">`. */
|
|
48
|
+
fileInput?: boolean;
|
|
49
|
+
/** Authored file-type filter from the input's `accept` attribute. */
|
|
50
|
+
accept?: string;
|
|
51
|
+
/** True when the file input accepts more than one file. */
|
|
52
|
+
multiple?: boolean;
|
|
53
|
+
/** Geometry-only fallback that cannot be resolved by semantic proxy actions. */
|
|
54
|
+
coordinateOnly?: boolean;
|
|
36
55
|
/**
|
|
37
56
|
* True when the extractor detected that this `<input>` (or role=textbox)
|
|
38
57
|
* lives inside an autocomplete / searchable combobox wrapper — React
|
|
@@ -281,11 +300,22 @@ export interface PageSectionDetail {
|
|
|
281
300
|
items: PageListItemModel[];
|
|
282
301
|
textPreview: string[];
|
|
283
302
|
}
|
|
284
|
-
export type FormSchemaFieldKind = 'text' | 'choice' | 'toggle' | 'multi_choice';
|
|
303
|
+
export type FormSchemaFieldKind = 'text' | 'choice' | 'toggle' | 'multi_choice' | 'file';
|
|
285
304
|
export type FormSchemaChoiceType = 'select' | 'group' | 'listbox';
|
|
286
305
|
export type FormSchemaContextMode = 'auto' | 'always' | 'none';
|
|
306
|
+
export interface FormSchemaOption {
|
|
307
|
+
/** Stable within the authored control identity; index disambiguates duplicate values/labels. */
|
|
308
|
+
id: string;
|
|
309
|
+
value: string;
|
|
310
|
+
label: string;
|
|
311
|
+
index: number;
|
|
312
|
+
disabled?: boolean;
|
|
313
|
+
selected?: boolean;
|
|
314
|
+
}
|
|
287
315
|
export interface FormSchemaField {
|
|
288
316
|
id: string;
|
|
317
|
+
/** Authored DOM identity used for exact proxy-side resolution before accessible-label fallback. */
|
|
318
|
+
fieldKey?: string;
|
|
289
319
|
kind: FormSchemaFieldKind;
|
|
290
320
|
label: string;
|
|
291
321
|
required?: boolean;
|
|
@@ -299,12 +329,15 @@ export interface FormSchemaField {
|
|
|
299
329
|
values?: string[];
|
|
300
330
|
optionCount?: number;
|
|
301
331
|
options?: string[];
|
|
332
|
+
optionDetails?: FormSchemaOption[];
|
|
302
333
|
aliases?: Record<string, string[]>;
|
|
303
334
|
format?: {
|
|
304
335
|
placeholder?: string;
|
|
305
336
|
pattern?: string;
|
|
306
337
|
inputType?: string;
|
|
307
338
|
autocomplete?: string;
|
|
339
|
+
accept?: string;
|
|
340
|
+
multiple?: boolean;
|
|
308
341
|
};
|
|
309
342
|
context?: NodeContextModel;
|
|
310
343
|
}
|
|
@@ -346,6 +379,60 @@ export interface FormSchemaBuildOptions {
|
|
|
346
379
|
includeOptions?: boolean;
|
|
347
380
|
includeContext?: FormSchemaContextMode;
|
|
348
381
|
}
|
|
382
|
+
export interface FormGraphSource {
|
|
383
|
+
id: string;
|
|
384
|
+
kind: 'html';
|
|
385
|
+
title?: string;
|
|
386
|
+
url?: string;
|
|
387
|
+
}
|
|
388
|
+
export interface FormGraphSourceAnchor {
|
|
389
|
+
sourceId: string;
|
|
390
|
+
kind: 'html';
|
|
391
|
+
fieldName?: string;
|
|
392
|
+
pointer?: string;
|
|
393
|
+
}
|
|
394
|
+
export interface FormGraphField {
|
|
395
|
+
id: string;
|
|
396
|
+
path: string;
|
|
397
|
+
label: string;
|
|
398
|
+
kind: 'boolean' | 'enum' | 'text' | 'textarea' | 'email' | 'phone' | 'date' | 'number';
|
|
399
|
+
required?: boolean;
|
|
400
|
+
reviewRequired?: boolean;
|
|
401
|
+
aliases?: string[];
|
|
402
|
+
options?: Array<{
|
|
403
|
+
value: string;
|
|
404
|
+
label: string;
|
|
405
|
+
}>;
|
|
406
|
+
constraints?: {
|
|
407
|
+
pattern?: string;
|
|
408
|
+
};
|
|
409
|
+
sourceAnchors?: FormGraphSourceAnchor[];
|
|
410
|
+
metadata?: Record<string, unknown>;
|
|
411
|
+
}
|
|
412
|
+
export interface FormGraphModel {
|
|
413
|
+
formgraph: '0.1';
|
|
414
|
+
id: string;
|
|
415
|
+
title: string;
|
|
416
|
+
description?: string;
|
|
417
|
+
sources: FormGraphSource[];
|
|
418
|
+
fields: FormGraphField[];
|
|
419
|
+
evidence: [];
|
|
420
|
+
dependencies: [];
|
|
421
|
+
review: {
|
|
422
|
+
autoSubmitAllowed: false;
|
|
423
|
+
requiredBeforeSubmit: true;
|
|
424
|
+
};
|
|
425
|
+
metadata: {
|
|
426
|
+
producer: 'geometra';
|
|
427
|
+
geometra: {
|
|
428
|
+
formId: string;
|
|
429
|
+
fieldCount: number;
|
|
430
|
+
requiredCount: number;
|
|
431
|
+
invalidCount: number;
|
|
432
|
+
sections?: FormSchemaSection[];
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
}
|
|
349
436
|
export interface UiNodeUpdate {
|
|
350
437
|
before: CompactUiNode;
|
|
351
438
|
after: CompactUiNode;
|
|
@@ -389,7 +476,11 @@ export interface WorkflowPageEntry {
|
|
|
389
476
|
pageUrl: string;
|
|
390
477
|
formId?: string;
|
|
391
478
|
formName?: string;
|
|
392
|
-
|
|
479
|
+
/** Backward-compatible value map whose contents are always redaction markers. */
|
|
480
|
+
filledValues: Record<string, '[REDACTED]'>;
|
|
481
|
+
/** Stable field identities retained without submitted values. */
|
|
482
|
+
filledFields: string[];
|
|
483
|
+
valuesRedacted: true;
|
|
393
484
|
filledAt: number;
|
|
394
485
|
fieldCount: number;
|
|
395
486
|
invalidCount: number;
|
|
@@ -405,7 +496,28 @@ export interface Session {
|
|
|
405
496
|
layout: Record<string, unknown> | null;
|
|
406
497
|
tree: Record<string, unknown> | null;
|
|
407
498
|
url: string;
|
|
499
|
+
/** Private bearer capability for an authenticated proxy transport. */
|
|
500
|
+
transportAuthToken?: string;
|
|
408
501
|
updateRevision: number;
|
|
502
|
+
/** Negotiated owner of the WebSocket endpoint. */
|
|
503
|
+
peerTransport?: 'native' | 'proxy';
|
|
504
|
+
/** Negotiated shared geometry protocol version. */
|
|
505
|
+
peerGeometryProtocolVersion?: number;
|
|
506
|
+
/** Negotiated browser-only action protocol version. */
|
|
507
|
+
peerProxyActionProtocolVersion?: number;
|
|
508
|
+
/** True when the peer advertised the split protocol contract explicitly. */
|
|
509
|
+
peerAdvertisedSplitProtocol?: boolean;
|
|
510
|
+
peerProtocolCapabilities?: {
|
|
511
|
+
authenticatedController?: boolean;
|
|
512
|
+
requestScopedAcks?: boolean;
|
|
513
|
+
actionDeadlines?: boolean;
|
|
514
|
+
idempotentRequestIds?: boolean;
|
|
515
|
+
atomicTypeText?: boolean;
|
|
516
|
+
proxyActions?: boolean;
|
|
517
|
+
exactFieldIdentity?: boolean;
|
|
518
|
+
verifiedFileUploads?: boolean;
|
|
519
|
+
binaryFraming?: boolean;
|
|
520
|
+
};
|
|
409
521
|
/** Present when this session owns a child geometra-proxy process (pageUrl connect). */
|
|
410
522
|
proxyChild?: ChildProcess;
|
|
411
523
|
proxyRuntime?: EmbeddedProxyRuntime;
|
|
@@ -426,6 +538,10 @@ export interface Session {
|
|
|
426
538
|
revision: number;
|
|
427
539
|
forms: FormSchemaModel[];
|
|
428
540
|
}>;
|
|
541
|
+
/** True only after the current WebSocket transport has supplied a full frame. */
|
|
542
|
+
hasFreshFrame?: boolean;
|
|
543
|
+
/** Permanently set when this session has been disconnected or otherwise retired. */
|
|
544
|
+
disposed?: boolean;
|
|
429
545
|
workflowState?: WorkflowState;
|
|
430
546
|
reconnectInFlight?: Promise<boolean>;
|
|
431
547
|
lifecycleTaskId?: string;
|
|
@@ -436,6 +552,10 @@ export interface Session {
|
|
|
436
552
|
heartbeatInterval?: ReturnType<typeof setInterval> | null;
|
|
437
553
|
heartbeatLastMessageAt?: number;
|
|
438
554
|
heartbeatPendingPongBy?: number | null;
|
|
555
|
+
/** Mutating operations whose caller timed out before a terminal response. */
|
|
556
|
+
ambiguousOperations?: Map<string, AmbiguousOperation>;
|
|
557
|
+
/** Mutating operations currently awaiting a terminal response. */
|
|
558
|
+
inFlightMutations?: Map<string, AmbiguousOperation>;
|
|
439
559
|
}
|
|
440
560
|
export interface SessionConnectTrace {
|
|
441
561
|
mode: 'direct-ws' | 'fresh-proxy' | 'reused-proxy';
|
|
@@ -455,17 +575,53 @@ export interface SessionConnectTrace {
|
|
|
455
575
|
export interface UpdateWaitResult {
|
|
456
576
|
status: 'updated' | 'acknowledged' | 'timed_out';
|
|
457
577
|
timeoutMs: number;
|
|
578
|
+
/** Wire identity used to correlate the terminal proxy response. */
|
|
579
|
+
requestId: string;
|
|
580
|
+
/** Stable logical identity shared by every wire phase of one action. */
|
|
581
|
+
actionId: string;
|
|
458
582
|
result?: unknown;
|
|
459
583
|
}
|
|
584
|
+
interface AmbiguousOperation {
|
|
585
|
+
fingerprint: string;
|
|
586
|
+
actionId: string;
|
|
587
|
+
requestId: string;
|
|
588
|
+
requestIds: string[];
|
|
589
|
+
wireMessages: string[];
|
|
590
|
+
actionTimeoutMs?: number;
|
|
591
|
+
timeoutMs: number;
|
|
592
|
+
idempotent: boolean;
|
|
593
|
+
mutating: boolean;
|
|
594
|
+
/** A correlated ACK alone is insufficient for actions such as navigation. */
|
|
595
|
+
requireUpdateOnAck?: boolean;
|
|
596
|
+
/** Protocol floor that the terminal ACK must explicitly satisfy. */
|
|
597
|
+
requiredProtocolVersion?: number;
|
|
598
|
+
/** Any non-deduplication phase error permanently blocks later ACK promotion. */
|
|
599
|
+
stickyError?: Error;
|
|
600
|
+
/**
|
|
601
|
+
* Once any caller observes a timeout, identical intent is permanently
|
|
602
|
+
* pinned to this identity for the rest of the session. A future caller
|
|
603
|
+
* cannot prove it is (or is not) the timed-out caller.
|
|
604
|
+
*/
|
|
605
|
+
permanentTombstone?: boolean;
|
|
606
|
+
completion?: {
|
|
607
|
+
kind: 'result';
|
|
608
|
+
value: UpdateWaitResult;
|
|
609
|
+
} | {
|
|
610
|
+
kind: 'error';
|
|
611
|
+
error: Error;
|
|
612
|
+
};
|
|
613
|
+
}
|
|
460
614
|
export type ProxyFillField = {
|
|
461
615
|
kind: 'auto';
|
|
462
616
|
fieldId?: string;
|
|
617
|
+
fieldKey?: string;
|
|
463
618
|
fieldLabel: string;
|
|
464
619
|
value: string | boolean;
|
|
465
620
|
exact?: boolean;
|
|
466
621
|
} | {
|
|
467
622
|
kind: 'text';
|
|
468
623
|
fieldId?: string;
|
|
624
|
+
fieldKey?: string;
|
|
469
625
|
fieldLabel: string;
|
|
470
626
|
value: string;
|
|
471
627
|
exact?: boolean;
|
|
@@ -474,13 +630,17 @@ export type ProxyFillField = {
|
|
|
474
630
|
} | {
|
|
475
631
|
kind: 'choice';
|
|
476
632
|
fieldId?: string;
|
|
633
|
+
fieldKey?: string;
|
|
477
634
|
fieldLabel: string;
|
|
478
635
|
value: string;
|
|
636
|
+
optionIndex?: number;
|
|
479
637
|
query?: string;
|
|
480
638
|
exact?: boolean;
|
|
481
639
|
choiceType?: FormSchemaChoiceType;
|
|
482
640
|
} | {
|
|
483
641
|
kind: 'toggle';
|
|
642
|
+
fieldId?: string;
|
|
643
|
+
fieldKey?: string;
|
|
484
644
|
label: string;
|
|
485
645
|
checked?: boolean;
|
|
486
646
|
exact?: boolean;
|
|
@@ -488,6 +648,7 @@ export type ProxyFillField = {
|
|
|
488
648
|
} | {
|
|
489
649
|
kind: 'file';
|
|
490
650
|
fieldId?: string;
|
|
651
|
+
fieldKey?: string;
|
|
491
652
|
fieldLabel: string;
|
|
492
653
|
paths: string[];
|
|
493
654
|
exact?: boolean;
|
|
@@ -522,6 +683,8 @@ export declare function connect(url: string, opts?: {
|
|
|
522
683
|
skipInitialResize?: boolean;
|
|
523
684
|
closePreviousProxy?: boolean;
|
|
524
685
|
awaitInitialFrame?: boolean;
|
|
686
|
+
authToken?: string;
|
|
687
|
+
isolated?: boolean;
|
|
525
688
|
}): Promise<Session>;
|
|
526
689
|
/**
|
|
527
690
|
* Start geometra-proxy for `pageUrl`, connect to its WebSocket, and attach the child
|
|
@@ -538,12 +701,10 @@ export declare function connectThroughProxy(options: {
|
|
|
538
701
|
awaitInitialFrame?: boolean;
|
|
539
702
|
eagerInitialExtract?: boolean;
|
|
540
703
|
/**
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
* submission so localStorage / cookies / page state from one job cannot
|
|
546
|
-
* leak into another. Default false preserves the existing pool behavior.
|
|
704
|
+
* Browser sessions are isolated by default. Pass `false` explicitly to
|
|
705
|
+
* opt into sequential warm-browser reuse, including shared cookies and
|
|
706
|
+
* localStorage. Isolated sessions never enter the reusable pool and their
|
|
707
|
+
* browser is destroyed on disconnect.
|
|
547
708
|
*/
|
|
548
709
|
isolated?: boolean;
|
|
549
710
|
/**
|
|
@@ -598,7 +759,10 @@ export declare function disconnect(opts?: {
|
|
|
598
759
|
closeProxy?: boolean;
|
|
599
760
|
sessionId?: string;
|
|
600
761
|
}): void;
|
|
762
|
+
/** Process/test teardown only. User-facing disconnects are always owner-scoped. */
|
|
763
|
+
export declare function shutdownAllSessionsAndProxies(): void;
|
|
601
764
|
export declare function waitForUiCondition(session: Session, predicate: () => boolean, timeoutMs: number): Promise<boolean>;
|
|
765
|
+
export declare function ensureSessionConnected(session: Session): Promise<void>;
|
|
602
766
|
/**
|
|
603
767
|
* Send a click event at (x, y) and wait for the next frame/patch response.
|
|
604
768
|
*/
|
|
@@ -618,13 +782,17 @@ export declare function sendKey(session: Session, key: string, modifiers?: {
|
|
|
618
782
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
619
783
|
/**
|
|
620
784
|
* Attach local file(s). Paths must exist on the machine running `@geometra/proxy` (not the MCP host).
|
|
621
|
-
* Optional `x`,`y` click opens a file chooser
|
|
785
|
+
* Optional `x`,`y` click opens a file chooser. Callers must provide an explicit
|
|
786
|
+
* coordinate or semantic target; MCP never intentionally requests a global
|
|
787
|
+
* first-file-input fallback.
|
|
622
788
|
*/
|
|
623
789
|
export declare function sendFileUpload(session: Session, paths: string[], opts?: {
|
|
624
790
|
click?: {
|
|
625
791
|
x: number;
|
|
626
792
|
y: number;
|
|
627
793
|
};
|
|
794
|
+
fieldId?: string;
|
|
795
|
+
fieldKey?: string;
|
|
628
796
|
fieldLabel?: string;
|
|
629
797
|
exact?: boolean;
|
|
630
798
|
strategy?: 'auto' | 'chooser' | 'hidden' | 'drop';
|
|
@@ -632,11 +800,14 @@ export declare function sendFileUpload(session: Session, paths: string[], opts?:
|
|
|
632
800
|
x: number;
|
|
633
801
|
y: number;
|
|
634
802
|
};
|
|
803
|
+
contextText?: string;
|
|
804
|
+
sectionText?: string;
|
|
635
805
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
636
806
|
/** Set a labeled text-like field (`input`, `textarea`, contenteditable, ARIA textbox) semantically. */
|
|
637
807
|
export declare function sendFieldText(session: Session, fieldLabel: string, value: string, opts?: {
|
|
638
808
|
exact?: boolean;
|
|
639
809
|
fieldId?: string;
|
|
810
|
+
fieldKey?: string;
|
|
640
811
|
typingDelayMs?: number;
|
|
641
812
|
imeFriendly?: boolean;
|
|
642
813
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
@@ -646,6 +817,8 @@ export declare function sendFieldChoice(session: Session, fieldLabel: string, va
|
|
|
646
817
|
query?: string;
|
|
647
818
|
choiceType?: FormSchemaChoiceType;
|
|
648
819
|
fieldId?: string;
|
|
820
|
+
fieldKey?: string;
|
|
821
|
+
optionIndex?: number;
|
|
649
822
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
650
823
|
/** Fill several semantic form fields in one proxy-side batch. */
|
|
651
824
|
export declare function sendFillFields(session: Session, fields: ProxyFillField[], timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
@@ -662,12 +835,10 @@ export declare function sendFillOtp(session: Session, value: string, opts?: {
|
|
|
662
835
|
/** ARIA `role=option` listbox (e.g. React Select). Optional click opens the list. */
|
|
663
836
|
export declare function sendListboxPick(session: Session, label: string, opts?: {
|
|
664
837
|
exact?: boolean;
|
|
665
|
-
open?: {
|
|
666
|
-
x: number;
|
|
667
|
-
y: number;
|
|
668
|
-
};
|
|
669
838
|
fieldLabel?: string;
|
|
670
839
|
query?: string;
|
|
840
|
+
fieldId?: string;
|
|
841
|
+
fieldKey?: string;
|
|
671
842
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
672
843
|
/** Native `<select>` only: click the control center, then pick by value, label text, or zero-based index. */
|
|
673
844
|
export declare function sendSelectOption(session: Session, x: number, y: number, option: {
|
|
@@ -680,6 +851,9 @@ export declare function sendSetChecked(session: Session, label: string, opts?: {
|
|
|
680
851
|
checked?: boolean;
|
|
681
852
|
exact?: boolean;
|
|
682
853
|
controlType?: 'checkbox' | 'radio';
|
|
854
|
+
fieldKey?: string;
|
|
855
|
+
contextText?: string;
|
|
856
|
+
sectionText?: string;
|
|
683
857
|
}, timeoutMs?: number): Promise<UpdateWaitResult>;
|
|
684
858
|
/** Mouse wheel / scroll. Optional `x`,`y` move pointer before scrolling. */
|
|
685
859
|
export declare function sendWheel(session: Session, deltaY: number, opts?: {
|
|
@@ -732,6 +906,8 @@ export declare function buildPageModel(root: A11yNode, options?: {
|
|
|
732
906
|
blockDetection?: boolean;
|
|
733
907
|
}): PageModel;
|
|
734
908
|
export declare function buildFormSchemas(root: A11yNode, options?: FormSchemaBuildOptions): FormSchemaModel[];
|
|
909
|
+
export declare function buildFormGraphs(root: A11yNode, options?: FormSchemaBuildOptions): FormGraphModel[];
|
|
910
|
+
export declare function formSchemaToFormGraph(schema: FormSchemaModel, pageUrl?: string): FormGraphModel;
|
|
735
911
|
/**
|
|
736
912
|
* Required-field snapshot for automation: every required field in a form, including
|
|
737
913
|
* offscreen entries, annotated with visibility and scroll hints so agents do not
|