@felan-ai/ext-browser 0.3.0 → 0.4.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/NOTICE CHANGED
@@ -1,12 +1,12 @@
1
1
  @felan-ai/ext-browser
2
2
  Copyright (c) 2026 Felan contributors
3
3
 
4
- This package integrates with, but does not include, agent-browser 0.31.1 from
4
+ This package integrates with, but does not include, agent-browser 0.37.1 from
5
5
  https://github.com/vercel-labs/agent-browser, distributed under the Apache License 2.0.
6
- The reviewed upstream release is v0.31.1 at tag commit
7
- ed2e10598c9064aecfaeb7cf21b540684db4be2c and its npm archive is identified by
6
+ The reviewed upstream release is v0.37.1 at tag commit
7
+ 72007a6788d863611b23bed0b59d0d659c638d8e and its npm archive is identified by
8
8
  SHA-512 integrity
9
- RjgfT0EsHe1oZQbwzUqJTPb7w3sU8DGbbAjMxLNI5dW1y0cc81TbVsqgjqQJmsy3GEbEcKe/ryARwmWGqJAXXQ==.
9
+ NDojTSXrIq7zS090T0VwI1uzBryZWvewgxXvS0swj8/5GGnziBZLmyhEkfETO8n4n3DsJpZbZkq9F/MV2rIQKw==.
10
10
 
11
11
  The optional managed installer downloads agent-browser only after explicit
12
12
  host-owned confirmation. It verifies the immutable npm archive and selected
package/README.md CHANGED
@@ -1,13 +1,23 @@
1
1
  # @felan-ai/ext-browser
2
2
 
3
- Portable Felan browser automation backed by the reviewed `agent-browser 0.31.1`
3
+ Portable Felan browser automation backed by the reviewed `agent-browser 0.37.1`
4
4
  CLI. The package does not vendor the upstream Rust daemon or Chrome. It probes
5
5
  the exact reviewed CLI on Felan's `AgentRuntime` and otherwise remains safely
6
6
  unavailable.
7
7
 
8
8
  ## Tool
9
9
 
10
- The extension registers one `browser` tool with two operations:
10
+ The extension registers the ordinary `browser` tool and, when its host supplies
11
+ authorization, a separate `browser_authorize` control-plane tool.
12
+
13
+ `browser_authorize` supports `authorize`, `status`, and `revoke`. Authorization
14
+ is interactive, held only for the current session, and opens a fresh strict
15
+ pinned tab in the existing Chrome session. The host supplies a transient
16
+ validated loopback CDP endpoint; it never returns cookies, profile paths, CDP
17
+ endpoints, or unrelated tab data. Direct `connect`, `--cdp`, and
18
+ `--auto-connect` arguments are rejected by `browser`.
19
+
20
+ The `browser` tool has two operations:
11
21
 
12
22
  - `skill` runs the installed CLI's `skills get <name>` command. Start with
13
23
  `core`, use `full: true` for the complete command reference, and request a
@@ -40,8 +50,13 @@ returns native image content. Text-only models or unreadable/invalid staged
40
50
  images receive a bounded text fallback instead. Model-selected screenshot
41
51
  paths remain text-only and are never opened automatically.
42
52
 
43
- The owned browser session is closed during session shutdown. A managed CLI
44
- install sets a one-hour daemon idle timeout; it does not install Chrome. Run
53
+ The owned browser session is closed during session shutdown. Revocation and
54
+ shutdown disconnect an attached session without closing the user's Chrome.
55
+ CDP attachment remains browser-level authority; pinned-tab and origin checks
56
+ are defense in depth, not a network sandbox. Felan makes one connection attempt
57
+ per approval and retries setup only after an explicit user action.
58
+
59
+ A managed CLI install sets a one-hour daemon idle timeout; it does not install Chrome. Run
45
60
  the explicit `agent-browser install` action when a local Chrome for Testing
46
61
  binary is needed.
47
62
 
@@ -79,8 +94,8 @@ The extension owns literal-argv validation, session namespacing, bounded output,
79
94
  version-matched skill retrieval, screenshot validation, and safe text/image
80
95
  fallbacks. Hosts own credentials, attachment authorization, dependency
81
96
  installation, and browser policy. Page content, CLI output, and bundled skill
82
- text are untrusted. Existing browser/profile/auth-state attachment requires
83
- explicit authorization unless the current request already grants that action.
97
+ text are untrusted. Existing-browser attachment requires `browser_authorize`;
98
+ noninteractive hosts fail closed.
84
99
 
85
100
  ## Related documentation
86
101
 
@@ -90,6 +105,6 @@ explicit authorization unless the current request already grants that action.
90
105
 
91
106
  ## Attribution
92
107
 
93
- The integration is reviewed against `agent-browser` 0.31.1. The package does
108
+ The integration is reviewed against `agent-browser` 0.37.1. The package does
94
109
  not vendor its daemon or Chrome. See [NOTICE](NOTICE) and [LICENSE](LICENSE) for
95
110
  the immutable upstream release, digests, and TypeBox attribution.
@@ -0,0 +1,49 @@
1
+ import type { AgentRuntime, ExtensionContext } from '@felan-ai/agent-core';
2
+ import type { BrowserAuthorizationHost, BrowserAuthorizationLease } from './authorization.js';
3
+ import type { BrowserCliResult, BrowserSessionScope } from './cli.js';
4
+ import type { AgentBrowserInvocation } from './installer.js';
5
+ type AttachmentState = 'pending' | 'authorized' | 'blocked' | 'revoked';
6
+ export interface BrowserAttachment {
7
+ readonly root: BrowserSessionScope;
8
+ readonly scope: BrowserSessionScope;
9
+ readonly origin: string;
10
+ readonly controller: AbortController;
11
+ readonly rejectedLeases: Set<BrowserAuthorizationLease>;
12
+ state: AttachmentState;
13
+ authorization: Promise<AuthorizationResult>;
14
+ invocation?: AgentBrowserInvocation;
15
+ lease?: BrowserAuthorizationLease;
16
+ endpoint?: string;
17
+ targetId?: string;
18
+ daemonPid?: number;
19
+ attempted: boolean;
20
+ started: boolean;
21
+ verified: boolean;
22
+ nativeOperation?: Promise<BrowserCliResult>;
23
+ cleanup?: Promise<boolean>;
24
+ cleanupVerified: boolean;
25
+ removeLeaseListener?: () => void;
26
+ }
27
+ export interface AuthorizationResult {
28
+ readonly state: 'authorized' | 'cancelled' | 'unavailable' | 'idle' | 'blocked' | 'revoked';
29
+ readonly message?: string;
30
+ readonly reused?: boolean;
31
+ }
32
+ export declare class BrowserAttachments {
33
+ #private;
34
+ readonly runtime: AgentRuntime;
35
+ readonly host: BrowserAuthorizationHost | undefined;
36
+ readonly getInvocation: (signal?: AbortSignal) => Promise<AgentBrowserInvocation>;
37
+ constructor(runtime: AgentRuntime, host: BrowserAuthorizationHost | undefined, getInvocation: (signal?: AbortSignal) => Promise<AgentBrowserInvocation>);
38
+ current(root: BrowserSessionScope): BrowserAttachment | undefined;
39
+ assertActive(attempt: BrowserAttachment): void;
40
+ status(root: BrowserSessionScope): Promise<AuthorizationResult>;
41
+ authorize(root: BrowserSessionScope, origin: string, context: ExtensionContext, signal?: AbortSignal): Promise<AuthorizationResult>;
42
+ verify(attempt: BrowserAttachment, signal?: AbortSignal): Promise<void>;
43
+ invalidate(attempt: BrowserAttachment): Promise<boolean>;
44
+ revoke(root: BrowserSessionScope): Promise<AuthorizationResult>;
45
+ close(): Promise<boolean>;
46
+ }
47
+ export declare function successData(result: BrowserCliResult): Record<string, unknown>;
48
+ export {};
49
+ //# sourceMappingURL=attachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../src/attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,417 @@
1
+ import { createBrowserAttachmentScope, runBrowserCli } from './cli.js';
2
+ export class BrowserAttachments {
3
+ runtime;
4
+ host;
5
+ getInvocation;
6
+ #attempts = new Map();
7
+ #history = new Set();
8
+ #closed = false;
9
+ constructor(runtime, host, getInvocation) {
10
+ this.runtime = runtime;
11
+ this.host = host;
12
+ this.getInvocation = getInvocation;
13
+ }
14
+ current(root) {
15
+ if (this.#closed)
16
+ throw new Error('Browser session is closed.');
17
+ const attempt = this.#attempts.get(scopeKey(root));
18
+ if (!attempt)
19
+ return undefined;
20
+ this.assertActive(attempt);
21
+ return attempt;
22
+ }
23
+ assertActive(attempt) {
24
+ if (this.#closed || this.#attempts.get(scopeKey(attempt.root)) !== attempt
25
+ || attempt.state !== 'authorized' || attempt.controller.signal.aborted || attempt.lease?.signal.aborted
26
+ || this.#uncleanPrevious(attempt.root, attempt)) {
27
+ throw new Error('Existing-browser authorization is inactive or quarantined; authorize again before using browser.');
28
+ }
29
+ }
30
+ async status(root) {
31
+ const attempt = this.#attempts.get(scopeKey(root));
32
+ if (!attempt)
33
+ return { state: 'idle' };
34
+ if (this.#uncleanPrevious(root, attempt))
35
+ return { state: 'unavailable', message: 'Previous browser cleanup is unconfirmed.' };
36
+ if (attempt.state === 'authorized') {
37
+ try {
38
+ await this.verify(attempt);
39
+ return { state: 'authorized' };
40
+ }
41
+ catch {
42
+ return { state: 'blocked', message: 'Existing-browser authorization is no longer active.' };
43
+ }
44
+ }
45
+ if (attempt.state === 'revoked' && !attempt.cleanupVerified) {
46
+ return { state: 'unavailable', message: 'Browser access is blocked, but cleanup is unconfirmed.' };
47
+ }
48
+ return { state: attempt.state === 'revoked' ? 'revoked' : 'blocked' };
49
+ }
50
+ async authorize(root, origin, context, signal) {
51
+ if (this.#closed || signal?.aborted)
52
+ return { state: 'cancelled' };
53
+ if (!this.host)
54
+ return { state: 'unavailable', message: 'Existing-browser authorization is unavailable in this host.' };
55
+ const key = scopeKey(root);
56
+ const previous = this.#attempts.get(key);
57
+ if (previous?.state === 'pending') {
58
+ if (previous.origin !== origin)
59
+ return { state: 'unavailable', message: 'Another browser authorization request is already in progress.' };
60
+ try {
61
+ return await (signal ? abortable(previous.authorization, signal) : previous.authorization);
62
+ }
63
+ catch {
64
+ return { state: 'cancelled', message: 'This authorization request was cancelled.' };
65
+ }
66
+ }
67
+ if (previous?.state === 'authorized') {
68
+ if (previous.origin !== origin)
69
+ return { state: 'unavailable', message: 'Revoke the current browser authorization before authorizing a different origin.' };
70
+ try {
71
+ await this.verify(previous, signal);
72
+ return { state: 'authorized', reused: true };
73
+ }
74
+ catch {
75
+ return { state: 'unavailable', message: 'Existing-browser authorization was lost. Request authorization again.' };
76
+ }
77
+ }
78
+ if ((previous && !previous.cleanupVerified) || this.#uncleanPrevious(root, previous)) {
79
+ return { state: 'unavailable', message: 'Previous browser cleanup is unconfirmed. Revoke again before requesting authorization.' };
80
+ }
81
+ const attempt = {
82
+ root: { ...root },
83
+ scope: createBrowserAttachmentScope(this.runtime, context.sessionManager.getSessionId()),
84
+ origin,
85
+ controller: new AbortController(),
86
+ rejectedLeases: new Set(),
87
+ state: 'pending',
88
+ authorization: Promise.resolve({ state: 'unavailable' }),
89
+ attempted: false,
90
+ started: false,
91
+ verified: false,
92
+ cleanupVerified: false,
93
+ };
94
+ this.#attempts.set(key, attempt);
95
+ this.#history.add(attempt);
96
+ attempt.authorization = this.#authorize(attempt, context, signal);
97
+ return attempt.authorization;
98
+ }
99
+ async #authorize(attempt, context, signal) {
100
+ const authorizationSignal = attempt.controller.signal;
101
+ const onAbort = () => attempt.controller.abort();
102
+ signal?.addEventListener('abort', onAbort, { once: true });
103
+ if (signal?.aborted)
104
+ onAbort();
105
+ const timeout = setTimeout(() => attempt.controller.abort(), 120_000);
106
+ try {
107
+ const outcome = await abortable(this.host.authorize({
108
+ origin: attempt.origin,
109
+ signal: authorizationSignal,
110
+ extensionContext: context,
111
+ attach: (connection, lease) => this.#attach(attempt, connection, lease, authorizationSignal),
112
+ }), authorizationSignal);
113
+ if (outcome.status === 'authorized' && attempt.verified && this.#isCurrent(attempt) && !authorizationSignal.aborted) {
114
+ await this.#observe(attempt, authorizationSignal);
115
+ authorizationSignal.throwIfAborted();
116
+ if (!this.#isCurrent(attempt))
117
+ throw new Error('Authorization request is no longer active.');
118
+ attempt.state = 'authorized';
119
+ return { state: 'authorized' };
120
+ }
121
+ await this.invalidate(attempt);
122
+ return outcome.status === 'cancelled'
123
+ ? { state: 'cancelled', message: 'Existing-browser authorization was cancelled.' }
124
+ : { state: 'unavailable', message: 'Chrome authorization did not complete a verified attachment.' };
125
+ }
126
+ catch {
127
+ const cancelled = signal?.aborted || this.#closed || attempt.state === 'revoked';
128
+ await this.invalidate(attempt);
129
+ return cancelled
130
+ ? { state: 'cancelled', message: 'Existing-browser authorization was cancelled.' }
131
+ : { state: 'unavailable', message: 'Chrome authorization could not be completed.' };
132
+ }
133
+ finally {
134
+ clearTimeout(timeout);
135
+ signal?.removeEventListener('abort', onAbort);
136
+ }
137
+ }
138
+ async #attach(attempt, connection, lease, signal) {
139
+ if (attempt.attempted || !this.#isCurrent(attempt) || signal.aborted) {
140
+ if (lease && lease !== attempt.lease)
141
+ await this.#rejectLease(attempt, lease);
142
+ return { ready: false, reason: 'Chrome attachment is no longer available for this request.' };
143
+ }
144
+ attempt.attempted = true;
145
+ if (!lease || typeof lease.close !== 'function' || !lease.signal || lease.signal.aborted) {
146
+ if (lease)
147
+ await this.#rejectLease(attempt, lease);
148
+ return { ready: false, reason: 'The host must provide a revocable single-connection browser lease.' };
149
+ }
150
+ attempt.lease = lease;
151
+ const onDisconnect = () => { void this.invalidate(attempt); };
152
+ lease.signal.addEventListener('abort', onDisconnect, { once: true });
153
+ attempt.removeLeaseListener = () => lease.signal.removeEventListener('abort', onDisconnect);
154
+ try {
155
+ attempt.endpoint = validateConnection(connection);
156
+ attempt.invocation = await this.getInvocation(signal);
157
+ signal.throwIfAborted();
158
+ if (!this.#isCurrent(attempt))
159
+ throw new Error('Authorization request is no longer active.');
160
+ attempt.started = true;
161
+ attempt.nativeOperation = runBrowserCli(this.runtime, attempt.invocation, [
162
+ 'open', attempt.origin, '--cdp', attempt.endpoint, '--pin-tab', '--no-auto-dialog', '--no-webmcp',
163
+ ], attempt.scope, { internalAttachment: true, timeoutMs: 120_000, signal });
164
+ const result = await attempt.nativeOperation;
165
+ successData(result);
166
+ await this.#observe(attempt, signal);
167
+ signal.throwIfAborted();
168
+ if (!this.#isCurrent(attempt))
169
+ throw new Error('Authorization request is no longer active.');
170
+ attempt.verified = true;
171
+ return { ready: true };
172
+ }
173
+ catch {
174
+ await this.invalidate(attempt);
175
+ return { ready: false, reason: 'Chrome did not complete the verified existing-browser connection.' };
176
+ }
177
+ }
178
+ async verify(attempt, signal) {
179
+ try {
180
+ this.assertActive(attempt);
181
+ await this.#observe(attempt, signal);
182
+ this.assertActive(attempt);
183
+ }
184
+ catch {
185
+ await this.invalidate(attempt);
186
+ throw new Error('Existing-browser authorization was lost or its target changed. No further browser action is permitted.');
187
+ }
188
+ }
189
+ async #observe(attempt, signal) {
190
+ const combined = AbortSignal.any([attempt.controller.signal, ...(signal ? [signal] : [])]);
191
+ const read = async (args) => {
192
+ combined.throwIfAborted();
193
+ if (!attempt.invocation || !this.#isCurrent(attempt))
194
+ throw new Error('Attachment is inactive.');
195
+ await this.host?.checkExecution?.();
196
+ combined.throwIfAborted();
197
+ if (!this.#isCurrent(attempt))
198
+ throw new Error('Attachment is inactive.');
199
+ const result = await runBrowserCli(this.runtime, attempt.invocation, args, attempt.scope, {
200
+ signal: combined, timeoutMs: 15_000, internalAttachment: true,
201
+ ...(args[0] === 'session' || attempt.endpoint === undefined ? {} : { attachmentEndpoint: attempt.endpoint }),
202
+ });
203
+ combined.throwIfAborted();
204
+ return successData(result);
205
+ };
206
+ const info = await read(['session', 'info']);
207
+ const runtime = info.runtime;
208
+ if (info.active !== true || !isRecord(runtime) || runtime.browserLaunched !== true
209
+ || !Number.isSafeInteger(info.pid) || Number(info.pid) <= 0 || runtime.backgroundPid !== info.pid
210
+ || (info.runtimeError !== undefined && info.runtimeError !== null)
211
+ || (attempt.daemonPid !== undefined && info.pid !== attempt.daemonPid)) {
212
+ throw new Error('Browser daemon identity changed.');
213
+ }
214
+ const connection = await read(['get', 'cdp-url']);
215
+ if (connection.cdpUrl !== attempt.endpoint)
216
+ throw new Error('Browser connection identity changed.');
217
+ const pages = await read(['tab', 'list']);
218
+ if (!Array.isArray(pages.tabs))
219
+ throw new Error('Browser target observation is invalid.');
220
+ const active = pages.tabs.filter((tab) => isRecord(tab) && tab.active === true);
221
+ const tab = active[0];
222
+ if (active.length !== 1 || !tab || typeof tab.targetId !== 'string' || !tab.targetId
223
+ || (attempt.targetId !== undefined && tab.targetId !== attempt.targetId)
224
+ || originOf(tab.url) !== attempt.origin)
225
+ throw new Error('Pinned browser target changed.');
226
+ const location = await read(['get', 'url']);
227
+ if (originOf(location.url) !== attempt.origin)
228
+ throw new Error('Browser left its authorized origin.');
229
+ attempt.daemonPid = Number(info.pid);
230
+ attempt.targetId = tab.targetId;
231
+ }
232
+ async invalidate(attempt) {
233
+ if (attempt.state !== 'revoked')
234
+ attempt.state = 'blocked';
235
+ attempt.controller.abort();
236
+ return this.#cleanup(attempt);
237
+ }
238
+ async revoke(root) {
239
+ const attempts = [...this.#history].filter(attempt => scopeKey(attempt.root) === scopeKey(root));
240
+ if (attempts.length === 0)
241
+ return { state: 'revoked' };
242
+ const outcomes = await Promise.all(attempts.map(async (attempt) => {
243
+ attempt.state = 'revoked';
244
+ attempt.controller.abort();
245
+ return this.#retryCleanup(attempt);
246
+ }));
247
+ return outcomes.every(Boolean)
248
+ ? { state: 'revoked', message: 'Existing-browser authorization revoked. Request authorization before using this browser again.' }
249
+ : { state: 'unavailable', message: 'Browser access is blocked, but cleanup is unconfirmed. Retry revoke; do not reconnect.' };
250
+ }
251
+ async #retryCleanup(attempt) {
252
+ if (attempt.cleanup && !attempt.cleanupVerified) {
253
+ const previous = attempt.cleanup;
254
+ await previous;
255
+ if (!attempt.cleanupVerified && attempt.cleanup === previous)
256
+ delete attempt.cleanup;
257
+ }
258
+ return this.#cleanup(attempt);
259
+ }
260
+ async #rejectLease(attempt, lease) {
261
+ attempt.rejectedLeases.add(lease);
262
+ attempt.cleanupVerified = false;
263
+ if (attempt.state !== 'revoked')
264
+ attempt.state = 'blocked';
265
+ attempt.controller.abort();
266
+ await this.#retryCleanup(attempt);
267
+ if (!attempt.cleanupVerified) {
268
+ const current = this.#attempts.get(scopeKey(attempt.root));
269
+ if (current && current !== attempt)
270
+ await this.invalidate(current);
271
+ }
272
+ }
273
+ #cleanup(attempt) {
274
+ if (attempt.cleanup)
275
+ return attempt.cleanup;
276
+ attempt.removeLeaseListener?.();
277
+ attempt.cleanup = (async () => {
278
+ let clean = !attempt.lease || await closeLease(attempt.lease);
279
+ for (const lease of attempt.rejectedLeases) {
280
+ if (await closeLease(lease))
281
+ attempt.rejectedLeases.delete(lease);
282
+ else
283
+ clean = false;
284
+ }
285
+ if (attempt.nativeOperation) {
286
+ try {
287
+ await abortable(attempt.nativeOperation.then(() => { }, () => { }), AbortSignal.timeout(15_000));
288
+ }
289
+ catch {
290
+ clean = false;
291
+ }
292
+ }
293
+ if (attempt.started && attempt.invocation) {
294
+ try {
295
+ await this.host?.checkExecution?.();
296
+ const result = await runBrowserCli(this.runtime, attempt.invocation, ['close'], attempt.scope, {
297
+ timeoutMs: 15_000, internalAttachment: true,
298
+ });
299
+ successData(result);
300
+ const deadline = AbortSignal.timeout(5_000);
301
+ for (;;) {
302
+ deadline.throwIfAborted();
303
+ await this.host?.checkExecution?.();
304
+ const status = successData(await runBrowserCli(this.runtime, attempt.invocation, ['session', 'info'], attempt.scope, {
305
+ timeoutMs: 5_000, internalAttachment: true, signal: deadline,
306
+ }));
307
+ if (status.active === false && status.pid === null && status.runtime === null
308
+ && (status.runtimeError === undefined || status.runtimeError === null))
309
+ break;
310
+ if (status.active !== true || (status.runtime !== null
311
+ && (!isRecord(status.runtime) || status.runtime.browserLaunched !== false))) {
312
+ clean = false;
313
+ break;
314
+ }
315
+ // Native close acknowledges before its delayed daemon shutdown notification.
316
+ await abortable(new Promise(resolve => setTimeout(resolve, 50)), deadline);
317
+ }
318
+ }
319
+ catch {
320
+ clean = false;
321
+ }
322
+ }
323
+ attempt.cleanupVerified = clean && attempt.rejectedLeases.size === 0;
324
+ return attempt.cleanupVerified;
325
+ })();
326
+ return attempt.cleanup;
327
+ }
328
+ async close() {
329
+ this.#closed = true;
330
+ const outcomes = await Promise.all([...this.#history].map(async (attempt) => {
331
+ attempt.state = 'blocked';
332
+ attempt.controller.abort();
333
+ return this.#retryCleanup(attempt);
334
+ }));
335
+ return outcomes.every(Boolean);
336
+ }
337
+ #isCurrent(attempt) {
338
+ return !this.#closed && this.#attempts.get(scopeKey(attempt.root)) === attempt
339
+ && !attempt.controller.signal.aborted && !attempt.lease?.signal.aborted
340
+ && !this.#uncleanPrevious(attempt.root, attempt)
341
+ && (attempt.state === 'pending' || attempt.state === 'authorized');
342
+ }
343
+ #uncleanPrevious(root, current) {
344
+ return [...this.#history].some(attempt => attempt !== current
345
+ && scopeKey(attempt.root) === scopeKey(root) && !attempt.cleanupVerified);
346
+ }
347
+ }
348
+ function validateConnection(connection) {
349
+ const { port, webSocketPath } = connection ?? {};
350
+ if (!Number.isInteger(port) || port < 1 || port > 65_535 || typeof webSocketPath !== 'string'
351
+ || webSocketPath.length > 4_096
352
+ || !/^\/(?:devtools\/browser(?:\/(?!\.{1,2}$)[A-Za-z0-9._-]+)?|felan-browser\/(?!\.{1,2}$)[A-Za-z0-9._-]+)$/u.test(webSocketPath)) {
353
+ throw new Error('Chrome authorization returned an invalid connection.');
354
+ }
355
+ return `ws://127.0.0.1:${port}${webSocketPath}`;
356
+ }
357
+ function scopeKey(scope) {
358
+ return `${scope.namespace}/${scope.session}`;
359
+ }
360
+ function originOf(value) {
361
+ if (typeof value !== 'string')
362
+ return undefined;
363
+ try {
364
+ return new URL(value).origin;
365
+ }
366
+ catch {
367
+ return undefined;
368
+ }
369
+ }
370
+ function isRecord(value) {
371
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
372
+ }
373
+ export function successData(result) {
374
+ if (result.code !== 0 || result.killed || result.outputTruncated)
375
+ throw new Error('Browser command did not complete.');
376
+ let response;
377
+ try {
378
+ response = JSON.parse(result.stdout);
379
+ }
380
+ catch {
381
+ throw new Error('Browser response was invalid JSON.');
382
+ }
383
+ if (!isRecord(response) || response.success !== true)
384
+ throw new Error('Browser response was not successful.');
385
+ return isRecord(response.data) ? response.data : {};
386
+ }
387
+ async function closeLease(lease) {
388
+ try {
389
+ await abortable(lease.close(), AbortSignal.timeout(5_000));
390
+ return lease.signal.aborted;
391
+ }
392
+ catch {
393
+ return false;
394
+ }
395
+ }
396
+ async function abortable(promise, signal) {
397
+ if (signal.aborted) {
398
+ void promise.catch(() => { });
399
+ throw new Error('Browser operation was cancelled.');
400
+ }
401
+ let onAbort;
402
+ try {
403
+ return await Promise.race([
404
+ promise,
405
+ new Promise((_resolve, reject) => {
406
+ onAbort = () => reject(new Error('Browser operation was cancelled.'));
407
+ signal.addEventListener('abort', onAbort, { once: true });
408
+ if (signal.aborted)
409
+ onAbort();
410
+ }),
411
+ ]);
412
+ }
413
+ finally {
414
+ signal.removeEventListener('abort', onAbort);
415
+ }
416
+ }
417
+ //# sourceMappingURL=attachment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.js","sourceRoot":"","sources":["../src/attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ExtensionContext } from '@felan-ai/agent-core';
2
+ export interface BrowserAuthorizationConnection {
3
+ readonly port: number;
4
+ readonly webSocketPath: string;
5
+ }
6
+ export interface BrowserAuthorizationAttachment {
7
+ readonly ready: boolean;
8
+ readonly reason?: string;
9
+ }
10
+ export interface BrowserAuthorizationLease {
11
+ readonly signal: AbortSignal;
12
+ close(): Promise<void>;
13
+ }
14
+ export interface BrowserAuthorizationRequest {
15
+ readonly origin: string;
16
+ readonly signal: AbortSignal;
17
+ readonly extensionContext: ExtensionContext;
18
+ readonly attach: (connection: BrowserAuthorizationConnection, lease?: BrowserAuthorizationLease) => Promise<BrowserAuthorizationAttachment>;
19
+ }
20
+ export type BrowserAuthorizationOutcome = {
21
+ readonly status: 'authorized' | 'cancelled' | 'unavailable';
22
+ readonly message?: string;
23
+ };
24
+ export interface BrowserAuthorizationHost {
25
+ /** Inherited CLI configuration can select an attached browser even for an isolated command. */
26
+ checkExecution?(): void | Promise<void>;
27
+ authorize(request: BrowserAuthorizationRequest): Promise<BrowserAuthorizationOutcome>;
28
+ }
29
+ //# sourceMappingURL=authorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,CACf,UAAU,EAAE,8BAA8B,EAC1C,KAAK,CAAC,EAAE,yBAAyB,KAC9B,OAAO,CAAC,8BAA8B,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,GAAG,aAAa,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/F,MAAM,WAAW,wBAAwB;IACvC,+FAA+F;IAC/F,cAAc,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACvF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":""}
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { AgentRuntime } from '@felan-ai/agent-core';
2
2
  import type { AgentBrowserInvocation } from './installer.js';
3
+ export { findBrowserCommand } from './command-policy.js';
3
4
  export declare const MAX_BROWSER_OUTPUT_CHARACTERS = 44000;
4
5
  export declare const MAX_BROWSER_SKILL_OUTPUT_CHARACTERS = 100000;
5
6
  export declare const DEFAULT_BROWSER_TIMEOUT_MS = 60000;
@@ -22,13 +23,16 @@ export interface PreparedBrowserCommand {
22
23
  readonly generatedScreenshotPath?: string;
23
24
  }
24
25
  export declare function createBrowserSessionScope(runtime: AgentRuntime, sessionId: string): BrowserSessionScope;
26
+ export declare function createBrowserAttachmentScope(runtime: AgentRuntime, sessionId: string): BrowserSessionScope;
25
27
  export declare function prepareBrowserCommand(runtime: AgentRuntime, args: readonly string[]): PreparedBrowserCommand;
26
28
  export declare function runBrowserCli(runtime: AgentRuntime, invocation: AgentBrowserInvocation, args: readonly string[], scope: BrowserSessionScope, options?: {
27
29
  readonly signal?: AbortSignal;
28
30
  readonly timeoutMs?: number;
29
31
  readonly json?: boolean;
30
32
  readonly prepareScreenshot?: boolean;
33
+ readonly attached?: boolean;
34
+ readonly attachmentEndpoint?: string;
35
+ readonly internalAttachment?: boolean;
31
36
  }): Promise<BrowserCliResult>;
32
37
  export declare function runBrowserSkill(runtime: AgentRuntime, invocation: AgentBrowserInvocation, skill: string, full: boolean, signal?: AbortSignal, timeoutMs?: number): Promise<BrowserCliResult>;
33
- export declare function findBrowserCommand(args: readonly string[]): string | undefined;
34
38
  //# sourceMappingURL=cli.d.ts.map