@framers/agentos-ext-browser-automation 0.1.0 → 0.2.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.
Files changed (129) hide show
  1. package/dist/attach/AttachController.d.ts +183 -0
  2. package/dist/attach/AttachController.d.ts.map +1 -0
  3. package/dist/attach/AttachController.js +283 -0
  4. package/dist/attach/AttachController.js.map +1 -0
  5. package/dist/attach/__tests__/AttachController.test.d.ts +2 -0
  6. package/dist/attach/__tests__/AttachController.test.d.ts.map +1 -0
  7. package/dist/attach/__tests__/AttachController.test.js +278 -0
  8. package/dist/attach/__tests__/AttachController.test.js.map +1 -0
  9. package/dist/attach/__tests__/attach-primitives.test.d.ts +2 -0
  10. package/dist/attach/__tests__/attach-primitives.test.d.ts.map +1 -0
  11. package/dist/attach/__tests__/attach-primitives.test.js +158 -0
  12. package/dist/attach/__tests__/attach-primitives.test.js.map +1 -0
  13. package/dist/attach/__tests__/jxa-args.test.d.ts +2 -0
  14. package/dist/attach/__tests__/jxa-args.test.d.ts.map +1 -0
  15. package/dist/attach/__tests__/jxa-args.test.js +37 -0
  16. package/dist/attach/__tests__/jxa-args.test.js.map +1 -0
  17. package/dist/attach/__tests__/pack-registration.test.d.ts +2 -0
  18. package/dist/attach/__tests__/pack-registration.test.d.ts.map +1 -0
  19. package/dist/attach/__tests__/pack-registration.test.js +34 -0
  20. package/dist/attach/__tests__/pack-registration.test.js.map +1 -0
  21. package/dist/attach/__tests__/tools.test.d.ts +2 -0
  22. package/dist/attach/__tests__/tools.test.d.ts.map +1 -0
  23. package/dist/attach/__tests__/tools.test.js +155 -0
  24. package/dist/attach/__tests__/tools.test.js.map +1 -0
  25. package/dist/attach/backends/__tests__/raw-cdp.test.d.ts +2 -0
  26. package/dist/attach/backends/__tests__/raw-cdp.test.d.ts.map +1 -0
  27. package/dist/attach/backends/__tests__/raw-cdp.test.js +133 -0
  28. package/dist/attach/backends/__tests__/raw-cdp.test.js.map +1 -0
  29. package/dist/attach/backends/jxa.d.ts +39 -0
  30. package/dist/attach/backends/jxa.d.ts.map +1 -0
  31. package/dist/attach/backends/jxa.js +188 -0
  32. package/dist/attach/backends/jxa.js.map +1 -0
  33. package/dist/attach/backends/raw-cdp.d.ts +53 -0
  34. package/dist/attach/backends/raw-cdp.d.ts.map +1 -0
  35. package/dist/attach/backends/raw-cdp.js +216 -0
  36. package/dist/attach/backends/raw-cdp.js.map +1 -0
  37. package/dist/attach/daemon/__tests__/client.test.d.ts +2 -0
  38. package/dist/attach/daemon/__tests__/client.test.d.ts.map +1 -0
  39. package/dist/attach/daemon/__tests__/client.test.js +58 -0
  40. package/dist/attach/daemon/__tests__/client.test.js.map +1 -0
  41. package/dist/attach/daemon/__tests__/daemon-lock.test.d.ts +2 -0
  42. package/dist/attach/daemon/__tests__/daemon-lock.test.d.ts.map +1 -0
  43. package/dist/attach/daemon/__tests__/daemon-lock.test.js +72 -0
  44. package/dist/attach/daemon/__tests__/daemon-lock.test.js.map +1 -0
  45. package/dist/attach/daemon/__tests__/daemon-loop.integration.test.d.ts +2 -0
  46. package/dist/attach/daemon/__tests__/daemon-loop.integration.test.d.ts.map +1 -0
  47. package/dist/attach/daemon/__tests__/daemon-loop.integration.test.js +102 -0
  48. package/dist/attach/daemon/__tests__/daemon-loop.integration.test.js.map +1 -0
  49. package/dist/attach/daemon/__tests__/harness.d.ts +44 -0
  50. package/dist/attach/daemon/__tests__/harness.d.ts.map +1 -0
  51. package/dist/attach/daemon/__tests__/harness.js +96 -0
  52. package/dist/attach/daemon/__tests__/harness.js.map +1 -0
  53. package/dist/attach/daemon/__tests__/protocol.test.d.ts +2 -0
  54. package/dist/attach/daemon/__tests__/protocol.test.d.ts.map +1 -0
  55. package/dist/attach/daemon/__tests__/protocol.test.js +71 -0
  56. package/dist/attach/daemon/__tests__/protocol.test.js.map +1 -0
  57. package/dist/attach/daemon/__tests__/runner.test.d.ts +2 -0
  58. package/dist/attach/daemon/__tests__/runner.test.d.ts.map +1 -0
  59. package/dist/attach/daemon/__tests__/runner.test.js +67 -0
  60. package/dist/attach/daemon/__tests__/runner.test.js.map +1 -0
  61. package/dist/attach/daemon/client.d.ts +64 -0
  62. package/dist/attach/daemon/client.d.ts.map +1 -0
  63. package/dist/attach/daemon/client.js +120 -0
  64. package/dist/attach/daemon/client.js.map +1 -0
  65. package/dist/attach/daemon/daemon-lock.d.ts +19 -0
  66. package/dist/attach/daemon/daemon-lock.d.ts.map +1 -0
  67. package/dist/attach/daemon/daemon-lock.js +87 -0
  68. package/dist/attach/daemon/daemon-lock.js.map +1 -0
  69. package/dist/attach/daemon/daemon-main.d.ts +6 -0
  70. package/dist/attach/daemon/daemon-main.d.ts.map +1 -0
  71. package/dist/attach/daemon/daemon-main.js +80 -0
  72. package/dist/attach/daemon/daemon-main.js.map +1 -0
  73. package/dist/attach/daemon/daemon.d.ts +52 -0
  74. package/dist/attach/daemon/daemon.d.ts.map +1 -0
  75. package/dist/attach/daemon/daemon.js +264 -0
  76. package/dist/attach/daemon/daemon.js.map +1 -0
  77. package/dist/attach/daemon/index.d.ts +12 -0
  78. package/dist/attach/daemon/index.d.ts.map +1 -0
  79. package/dist/attach/daemon/index.js +30 -0
  80. package/dist/attach/daemon/index.js.map +1 -0
  81. package/dist/attach/daemon/protocol.d.ts +69 -0
  82. package/dist/attach/daemon/protocol.d.ts.map +1 -0
  83. package/dist/attach/daemon/protocol.js +108 -0
  84. package/dist/attach/daemon/protocol.js.map +1 -0
  85. package/dist/attach/daemon/runner.d.ts +64 -0
  86. package/dist/attach/daemon/runner.d.ts.map +1 -0
  87. package/dist/attach/daemon/runner.js +60 -0
  88. package/dist/attach/daemon/runner.js.map +1 -0
  89. package/dist/attach/daemon/surface.d.ts +31 -0
  90. package/dist/attach/daemon/surface.d.ts.map +1 -0
  91. package/dist/attach/daemon/surface.js +89 -0
  92. package/dist/attach/daemon/surface.js.map +1 -0
  93. package/dist/attach/devtools-port.d.ts +37 -0
  94. package/dist/attach/devtools-port.d.ts.map +1 -0
  95. package/dist/attach/devtools-port.js +50 -0
  96. package/dist/attach/devtools-port.js.map +1 -0
  97. package/dist/attach/errors.d.ts +38 -0
  98. package/dist/attach/errors.d.ts.map +1 -0
  99. package/dist/attach/errors.js +72 -0
  100. package/dist/attach/errors.js.map +1 -0
  101. package/dist/attach/lease.d.ts +43 -0
  102. package/dist/attach/lease.d.ts.map +1 -0
  103. package/dist/attach/lease.js +92 -0
  104. package/dist/attach/lease.js.map +1 -0
  105. package/dist/attach/singleton-lock.d.ts +21 -0
  106. package/dist/attach/singleton-lock.d.ts.map +1 -0
  107. package/dist/attach/singleton-lock.js +30 -0
  108. package/dist/attach/singleton-lock.js.map +1 -0
  109. package/dist/attach/state.d.ts +31 -0
  110. package/dist/attach/state.d.ts.map +1 -0
  111. package/dist/attach/state.js +78 -0
  112. package/dist/attach/state.js.map +1 -0
  113. package/dist/attach/tools.d.ts +208 -0
  114. package/dist/attach/tools.d.ts.map +1 -0
  115. package/dist/attach/tools.js +195 -0
  116. package/dist/attach/tools.js.map +1 -0
  117. package/dist/attach/url-policy.d.ts +41 -0
  118. package/dist/attach/url-policy.d.ts.map +1 -0
  119. package/dist/attach/url-policy.js +59 -0
  120. package/dist/attach/url-policy.js.map +1 -0
  121. package/dist/attach.d.ts +18 -0
  122. package/dist/attach.d.ts.map +1 -0
  123. package/dist/attach.js +34 -0
  124. package/dist/attach.js.map +1 -0
  125. package/dist/index.d.ts +30 -0
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +29 -1
  128. package/dist/index.js.map +1 -1
  129. package/package.json +22 -7
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @fileoverview AttachController — the one object allowed to touch an attached
3
+ * (user-owned, already-running) browser.
4
+ *
5
+ * Non-negotiable contract, enforced here rather than by convention:
6
+ *
7
+ * 1. ATTACH-ONLY. The controller can never launch a browser. When the target
8
+ * is missing or fails identity verification it ABORTS with a structured
9
+ * error — it must not "helpfully" spawn Chrome (Codex spec review F9).
10
+ * 2. NON-DESTRUCTIVE DETACH. `detach()` tears down only OUR transport
11
+ * connection. The backend interface deliberately has no close/quit surface,
12
+ * so no code path can call `Browser.close()`/`Page.close()` on the user's
13
+ * browser (Codex F10 — wunderland's `BrowserSession.disconnect()` calls
14
+ * `browser.close()` and is exactly the hazard this replaces).
15
+ * 3. MARKER-TAB BOUND. Every operation targets the single agent tab the
16
+ * controller claimed; other tabs/windows are out of reach by construction.
17
+ * 4. LEASED. All operations require the cross-process lease nonce acquired at
18
+ * `claim()` (F3), and run under the no-replay state machine with deadlines
19
+ * (F14) plus the deny-by-default URL policy (F12).
20
+ *
21
+ * @module browser-automation/attach/AttachController
22
+ */
23
+ import { type StructuredAttachError } from './errors.js';
24
+ import { type UrlPolicyOptions } from './url-policy.js';
25
+ /**
26
+ * Transport backend contract. INTENTIONALLY has no `closeBrowser`/`closeTab`
27
+ * surface: the strongest guarantee that a detach can never destroy user state
28
+ * is that the API cannot express it.
29
+ */
30
+ export interface AttachBackend {
31
+ /** Transport id for status/reporting. */
32
+ readonly kind: 'cdp' | 'jxa';
33
+ /** Open the transport (e.g. CDP socket). Must NOT create or focus tabs. */
34
+ connect(): Promise<void>;
35
+ /** Close ONLY our transport connection. Must not touch browser state. */
36
+ disconnectTransport(): Promise<void>;
37
+ /** Claim (or create) the marker agent tab; returns an opaque tab handle. */
38
+ claimAgentTab(): Promise<string>;
39
+ /** Read a lightweight identity probe: current profile evidence (e.g. a known tab title). */
40
+ probeIdentity(): Promise<string>;
41
+ /** Navigate the agent tab. Returns the URL actually landed on. */
42
+ gotoTab(tab: string, url: string): Promise<string>;
43
+ /** Read innerText (optionally scoped by selector) from the agent tab. */
44
+ readTab(tab: string, selector?: string, maxChars?: number): Promise<string>;
45
+ /**
46
+ * OPTIONAL: evaluate an expression in the agent tab (returnByValue).
47
+ * Absent on backends without a safe eval primitive; callers surface
48
+ * `UNSUPPORTED_OP` when missing. Never exposed on the agent tool surface.
49
+ */
50
+ evalInTab?(tab: string, expression: string, timeoutMs?: number): Promise<unknown>;
51
+ }
52
+ /**
53
+ * What `createAttachTools` needs: satisfied in-process by {@link AttachController}
54
+ * (jxa transport) and over IPC by the daemon proxy surface (cdp transport).
55
+ * Deliberately NO eval and NO extract — the agent tool surface stays no-eval.
56
+ */
57
+ export interface AttachSurface {
58
+ status(): unknown;
59
+ claim(): Promise<unknown>;
60
+ goto(url: string): Promise<string>;
61
+ read(selector?: string, maxChars?: number): Promise<string>;
62
+ detach(): Promise<void>;
63
+ pause(): void;
64
+ resume(): void;
65
+ setDryRun(on: boolean): void;
66
+ }
67
+ /**
68
+ * Human-in-the-loop navigation decision. Called before every `goto` (after the
69
+ * URL clears the deny-by-default policy). Return `false`/`{ approved: false }`
70
+ * to block the navigation with a `POLICY_BLOCKED` result. Async so a caller can
71
+ * prompt a real operator.
72
+ */
73
+ export type NavigationApprover = (url: string) => boolean | {
74
+ approved: boolean;
75
+ reason?: string;
76
+ } | Promise<boolean | {
77
+ approved: boolean;
78
+ reason?: string;
79
+ }>;
80
+ /** Controller configuration. */
81
+ export interface AttachControllerOptions {
82
+ backend: AttachBackend;
83
+ /** Lease file path (one per machine/user). */
84
+ leaseFile: string;
85
+ /**
86
+ * Expected profile identity substring (e.g. the account email). Claim ABORTS
87
+ * with PROFILE_MISMATCH when the probe does not contain it. Required: an
88
+ * attach client must never guess which profile it is driving (F9).
89
+ */
90
+ expectedIdentity: string;
91
+ /** URL policy options (host allowlist etc.). */
92
+ urlPolicy?: UrlPolicyOptions;
93
+ /** Per-operation deadline in ms (default 45s). */
94
+ deadlineMs?: number;
95
+ /**
96
+ * Dry-run: navigation and reads are validated and reported but NOT performed
97
+ * against the browser. Lets a mission preview its plan (or run in CI) without
98
+ * touching the live session.
99
+ */
100
+ dryRun?: boolean;
101
+ /**
102
+ * HITL gate on navigation. Runs after the URL policy passes; a denial blocks
103
+ * the goto. Use to require operator approval for each page an assistant opens.
104
+ */
105
+ onNavigate?: NavigationApprover;
106
+ }
107
+ /** Status snapshot returned by {@link AttachController.status}. */
108
+ export interface AttachStatus {
109
+ transport: 'cdp' | 'jxa' | 'none';
110
+ state: string;
111
+ leaseHeld: boolean;
112
+ agentTab?: string;
113
+ lastError?: StructuredAttachError;
114
+ /** Session paused — operations are refused until resume(). */
115
+ paused: boolean;
116
+ /** Dry-run mode — navigation/reads are simulated, not performed. */
117
+ dryRun: boolean;
118
+ /** Count of navigations performed this session. */
119
+ navigations: number;
120
+ /** Last URL the agent tab navigated to. */
121
+ lastUrl?: string;
122
+ }
123
+ /**
124
+ * Orchestrates one attach session end to end. One controller instance = one
125
+ * lease = one agent tab.
126
+ */
127
+ export declare class AttachController {
128
+ private readonly backend;
129
+ private readonly opts;
130
+ private readonly machine;
131
+ private lease?;
132
+ private tab?;
133
+ private lastError?;
134
+ private paused;
135
+ private dryRun;
136
+ private navigations;
137
+ private lastUrl?;
138
+ constructor(opts: AttachControllerOptions);
139
+ private get deadline();
140
+ /** Non-throwing status snapshot. */
141
+ status(): AttachStatus;
142
+ /** Pause the session — navigation/read refuse until {@link resume}. */
143
+ pause(): void;
144
+ /** Resume a paused session. */
145
+ resume(): void;
146
+ /** Toggle dry-run at runtime (simulate navigation/reads, don't perform them). */
147
+ setDryRun(on: boolean): void;
148
+ /**
149
+ * Acquire the lease, open the transport, verify profile identity, and claim
150
+ * the marker agent tab. Aborts (never launches) on any verification failure.
151
+ */
152
+ claim(): Promise<AttachStatus>;
153
+ /** Navigate the agent tab (policy-checked, HITL-gated, redirect-revalidated). */
154
+ goto(url: string): Promise<string>;
155
+ /** Read text from the agent tab (size-capped by the backend). */
156
+ read(selector?: string, maxChars?: number): Promise<string>;
157
+ /** Fixed, parameterized extraction expression: the selector map is data, never code. */
158
+ private static extractExpression;
159
+ /** The backend's optional eval primitive, or a structured refusal. */
160
+ private requireEval;
161
+ /**
162
+ * Structured extraction over a fixed, parameterized expression: for each
163
+ * `name: cssSelector` pair, trimmed textContent lists; with no fields, a
164
+ * default page summary (url/title/heading/links/text). No caller-supplied
165
+ * code ever reaches the page — selectors are data.
166
+ */
167
+ extract(fields?: Record<string, string>): Promise<unknown>;
168
+ /**
169
+ * Arbitrary page evaluation. USER LANE ONLY: reachable through the daemon
170
+ * protocol's `eval` op and the JS client; no agent tool maps to it and the
171
+ * tool-facing surface has no eval member.
172
+ */
173
+ evaluate(expression: string, timeoutMs?: number): Promise<unknown>;
174
+ /**
175
+ * Release the session: park is the CALLER's responsibility (navigate to
176
+ * about:blank first if desired), then this closes only our transport and
177
+ * releases the lease. There is no code path to close browser/tabs.
178
+ */
179
+ detach(): Promise<void>;
180
+ private requireReady;
181
+ private safeReleaseOnFailure;
182
+ }
183
+ //# sourceMappingURL=AttachController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachController.d.ts","sourceRoot":"","sources":["../../src/attach/AttachController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AttachController = void 0;
4
+ /**
5
+ * @fileoverview AttachController — the one object allowed to touch an attached
6
+ * (user-owned, already-running) browser.
7
+ *
8
+ * Non-negotiable contract, enforced here rather than by convention:
9
+ *
10
+ * 1. ATTACH-ONLY. The controller can never launch a browser. When the target
11
+ * is missing or fails identity verification it ABORTS with a structured
12
+ * error — it must not "helpfully" spawn Chrome (Codex spec review F9).
13
+ * 2. NON-DESTRUCTIVE DETACH. `detach()` tears down only OUR transport
14
+ * connection. The backend interface deliberately has no close/quit surface,
15
+ * so no code path can call `Browser.close()`/`Page.close()` on the user's
16
+ * browser (Codex F10 — wunderland's `BrowserSession.disconnect()` calls
17
+ * `browser.close()` and is exactly the hazard this replaces).
18
+ * 3. MARKER-TAB BOUND. Every operation targets the single agent tab the
19
+ * controller claimed; other tabs/windows are out of reach by construction.
20
+ * 4. LEASED. All operations require the cross-process lease nonce acquired at
21
+ * `claim()` (F3), and run under the no-replay state machine with deadlines
22
+ * (F14) plus the deny-by-default URL policy (F12).
23
+ *
24
+ * @module browser-automation/attach/AttachController
25
+ */
26
+ const errors_js_1 = require("./errors.js");
27
+ const lease_js_1 = require("./lease.js");
28
+ const state_js_1 = require("./state.js");
29
+ const url_policy_js_1 = require("./url-policy.js");
30
+ /**
31
+ * Orchestrates one attach session end to end. One controller instance = one
32
+ * lease = one agent tab.
33
+ */
34
+ class AttachController {
35
+ constructor(opts) {
36
+ this.machine = new state_js_1.AttachStateMachine();
37
+ this.paused = false;
38
+ this.navigations = 0;
39
+ this.backend = opts.backend;
40
+ this.opts = opts;
41
+ this.dryRun = !!opts.dryRun;
42
+ }
43
+ get deadline() {
44
+ return this.opts.deadlineMs ?? 45000;
45
+ }
46
+ /** Non-throwing status snapshot. */
47
+ status() {
48
+ return {
49
+ transport: this.lease ? this.backend.kind : 'none',
50
+ state: this.machine.state,
51
+ leaseHeld: !!this.lease,
52
+ agentTab: this.tab,
53
+ lastError: this.lastError,
54
+ paused: this.paused,
55
+ dryRun: this.dryRun,
56
+ navigations: this.navigations,
57
+ lastUrl: this.lastUrl,
58
+ };
59
+ }
60
+ /** Pause the session — navigation/read refuse until {@link resume}. */
61
+ pause() {
62
+ this.paused = true;
63
+ }
64
+ /** Resume a paused session. */
65
+ resume() {
66
+ this.paused = false;
67
+ }
68
+ /** Toggle dry-run at runtime (simulate navigation/reads, don't perform them). */
69
+ setDryRun(on) {
70
+ this.dryRun = on;
71
+ }
72
+ /**
73
+ * Acquire the lease, open the transport, verify profile identity, and claim
74
+ * the marker agent tab. Aborts (never launches) on any verification failure.
75
+ */
76
+ async claim() {
77
+ this.machine.to('connecting');
78
+ try {
79
+ this.lease = (0, lease_js_1.acquireLease)({ file: this.opts.leaseFile });
80
+ await (0, state_js_1.withDeadline)(this.backend.connect(), this.deadline, 'connect');
81
+ const identity = await (0, state_js_1.withDeadline)(this.backend.probeIdentity(), this.deadline, 'probeIdentity');
82
+ if (!identity.includes(this.opts.expectedIdentity)) {
83
+ throw new errors_js_1.AttachError('PROFILE_MISMATCH', `attached browser did not present the expected profile identity (looked for "${this.opts.expectedIdentity}")`);
84
+ }
85
+ this.tab = await (0, state_js_1.withDeadline)(this.backend.claimAgentTab(), this.deadline, 'claimAgentTab');
86
+ this.machine.to('ready');
87
+ return this.status();
88
+ }
89
+ catch (err) {
90
+ this.lastError = (0, errors_js_1.toStructuredError)(err);
91
+ this.machine.to('failed');
92
+ await this.safeReleaseOnFailure();
93
+ throw err;
94
+ }
95
+ }
96
+ /** Navigate the agent tab (policy-checked, HITL-gated, redirect-revalidated). */
97
+ async goto(url) {
98
+ this.requireReady();
99
+ const verdict = (0, url_policy_js_1.isNavigationAllowed)(url, this.opts.urlPolicy);
100
+ if (!verdict.allowed) {
101
+ throw new errors_js_1.AttachError('POLICY_BLOCKED', `navigation to "${url}" rejected: ${verdict.reason}`);
102
+ }
103
+ // HITL gate: after the policy passes, an approver may still block the page.
104
+ if (this.opts.onNavigate) {
105
+ const decision = await this.opts.onNavigate(url);
106
+ const approved = typeof decision === 'boolean' ? decision : decision.approved;
107
+ if (!approved) {
108
+ const reason = typeof decision === 'object' && decision.reason ? decision.reason : 'operator denied';
109
+ throw new errors_js_1.AttachError('POLICY_BLOCKED', `navigation to "${url}" denied by approver: ${reason}`);
110
+ }
111
+ }
112
+ (0, lease_js_1.requireLease)(this.opts.leaseFile, this.lease.nonce);
113
+ // Dry-run: report the URL as the landed target without touching the browser.
114
+ if (this.dryRun) {
115
+ this.navigations += 1;
116
+ this.lastUrl = url;
117
+ return url;
118
+ }
119
+ this.machine.to('navigating');
120
+ try {
121
+ const landed = await (0, state_js_1.withDeadline)(this.backend.gotoTab(this.tab, url), this.deadline, 'goto');
122
+ this.navigations += 1;
123
+ this.lastUrl = landed;
124
+ const landedVerdict = (0, url_policy_js_1.revalidateRedirect)(landed, this.opts.urlPolicy);
125
+ if (!landedVerdict.allowed) {
126
+ this.machine.to('ready');
127
+ throw new errors_js_1.AttachError('POLICY_BLOCKED', `redirect landed on a blocked target: ${landedVerdict.reason}`);
128
+ }
129
+ this.machine.to('ready');
130
+ return landed;
131
+ }
132
+ catch (err) {
133
+ if (this.machine.state === 'navigating')
134
+ this.machine.to('failed');
135
+ this.lastError = (0, errors_js_1.toStructuredError)(err);
136
+ throw err;
137
+ }
138
+ }
139
+ /** Read text from the agent tab (size-capped by the backend). */
140
+ async read(selector, maxChars) {
141
+ this.requireReady();
142
+ (0, lease_js_1.requireLease)(this.opts.leaseFile, this.lease.nonce);
143
+ if (this.dryRun)
144
+ return '[dry-run] read skipped';
145
+ this.machine.to('reading');
146
+ try {
147
+ const text = await (0, state_js_1.withDeadline)(this.backend.readTab(this.tab, selector, maxChars), this.deadline, 'read');
148
+ this.machine.to('ready');
149
+ return text;
150
+ }
151
+ catch (err) {
152
+ if (this.machine.state === 'reading')
153
+ this.machine.to('failed');
154
+ this.lastError = (0, errors_js_1.toStructuredError)(err);
155
+ throw err;
156
+ }
157
+ }
158
+ /** Fixed, parameterized extraction expression: the selector map is data, never code. */
159
+ static extractExpression(fields) {
160
+ const spec = JSON.stringify(fields ?? {});
161
+ return `(() => {
162
+ const fields = ${spec};
163
+ const grab = (sel) => [...document.querySelectorAll(sel)].map((e) => (e.textContent || '').trim()).filter(Boolean);
164
+ if (Object.keys(fields).length) {
165
+ const out = {};
166
+ for (const [name, sel] of Object.entries(fields)) out[name] = grab(sel).slice(0, 200);
167
+ return out;
168
+ }
169
+ return {
170
+ url: location.href,
171
+ title: document.title,
172
+ heading: (document.querySelector('h1,h2') || {}).textContent?.trim() || '',
173
+ links: [...document.querySelectorAll('a[href]')].map((a) => ({ href: a.href, text: (a.textContent || '').trim().slice(0, 60) })).slice(0, 500),
174
+ text: (document.body.innerText || '').replace(/\\s+/g, ' ').slice(0, 4000),
175
+ };
176
+ })()`;
177
+ }
178
+ /** The backend's optional eval primitive, or a structured refusal. */
179
+ requireEval() {
180
+ const fn = this.backend.evalInTab?.bind(this.backend);
181
+ if (!fn) {
182
+ throw new errors_js_1.AttachError('UNSUPPORTED_OP', `${this.backend.kind} backend has no page-evaluation capability`);
183
+ }
184
+ return fn;
185
+ }
186
+ /**
187
+ * Structured extraction over a fixed, parameterized expression: for each
188
+ * `name: cssSelector` pair, trimmed textContent lists; with no fields, a
189
+ * default page summary (url/title/heading/links/text). No caller-supplied
190
+ * code ever reaches the page — selectors are data.
191
+ */
192
+ async extract(fields) {
193
+ this.requireReady();
194
+ const evalFn = this.requireEval();
195
+ (0, lease_js_1.requireLease)(this.opts.leaseFile, this.lease.nonce);
196
+ if (this.dryRun)
197
+ return { dryRun: true };
198
+ this.machine.to('reading');
199
+ try {
200
+ const out = await (0, state_js_1.withDeadline)(evalFn(this.tab, AttachController.extractExpression(fields)), this.deadline, 'extract');
201
+ this.machine.to('ready');
202
+ return out;
203
+ }
204
+ catch (err) {
205
+ if (this.machine.state === 'reading')
206
+ this.machine.to('failed');
207
+ this.lastError = (0, errors_js_1.toStructuredError)(err);
208
+ throw err;
209
+ }
210
+ }
211
+ /**
212
+ * Arbitrary page evaluation. USER LANE ONLY: reachable through the daemon
213
+ * protocol's `eval` op and the JS client; no agent tool maps to it and the
214
+ * tool-facing surface has no eval member.
215
+ */
216
+ async evaluate(expression, timeoutMs) {
217
+ this.requireReady();
218
+ const evalFn = this.requireEval();
219
+ (0, lease_js_1.requireLease)(this.opts.leaseFile, this.lease.nonce);
220
+ if (this.dryRun)
221
+ return '[dry-run] evaluate skipped';
222
+ this.machine.to('reading');
223
+ try {
224
+ const out = await (0, state_js_1.withDeadline)(evalFn(this.tab, expression, timeoutMs), Math.max(this.deadline, (timeoutMs ?? 0) + 5000), 'evaluate');
225
+ this.machine.to('ready');
226
+ return out;
227
+ }
228
+ catch (err) {
229
+ if (this.machine.state === 'reading')
230
+ this.machine.to('failed');
231
+ this.lastError = (0, errors_js_1.toStructuredError)(err);
232
+ throw err;
233
+ }
234
+ }
235
+ /**
236
+ * Release the session: park is the CALLER's responsibility (navigate to
237
+ * about:blank first if desired), then this closes only our transport and
238
+ * releases the lease. There is no code path to close browser/tabs.
239
+ */
240
+ async detach() {
241
+ try {
242
+ await this.backend.disconnectTransport();
243
+ }
244
+ finally {
245
+ if (this.lease)
246
+ (0, lease_js_1.releaseLease)(this.opts.leaseFile, this.lease.nonce);
247
+ this.lease = undefined;
248
+ this.tab = undefined;
249
+ if (this.machine.state !== 'disconnected') {
250
+ if (this.machine.state !== 'failed')
251
+ this.machine.to('failed');
252
+ this.machine.to('disconnected');
253
+ }
254
+ }
255
+ }
256
+ requireReady() {
257
+ if (this.paused) {
258
+ throw new errors_js_1.AttachError('UNKNOWN', 'attach session is paused — call resume() before further operations');
259
+ }
260
+ if (this.machine.state !== 'ready' || !this.tab || !this.lease) {
261
+ throw new errors_js_1.AttachError('UNKNOWN', `attach session not ready (state=${this.machine.state}) — call claim() first`);
262
+ }
263
+ }
264
+ async safeReleaseOnFailure() {
265
+ try {
266
+ await this.backend.disconnectTransport();
267
+ }
268
+ catch {
269
+ /* transport already dead */
270
+ }
271
+ if (this.lease) {
272
+ try {
273
+ (0, lease_js_1.releaseLease)(this.opts.leaseFile, this.lease.nonce);
274
+ }
275
+ catch {
276
+ /* foreign lease — leave it */
277
+ }
278
+ this.lease = undefined;
279
+ }
280
+ }
281
+ }
282
+ exports.AttachController = AttachController;
283
+ //# sourceMappingURL=AttachController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachController.js","sourceRoot":"","sources":["../../src/attach/AttachController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AttachController.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachController.test.d.ts","sourceRoot":"","sources":["../../../src/attach/__tests__/AttachController.test.ts"],"names":[],"mappings":""}