@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.
- package/dist/attach/AttachController.d.ts +183 -0
- package/dist/attach/AttachController.d.ts.map +1 -0
- package/dist/attach/AttachController.js +283 -0
- package/dist/attach/AttachController.js.map +1 -0
- package/dist/attach/__tests__/AttachController.test.d.ts +2 -0
- package/dist/attach/__tests__/AttachController.test.d.ts.map +1 -0
- package/dist/attach/__tests__/AttachController.test.js +278 -0
- package/dist/attach/__tests__/AttachController.test.js.map +1 -0
- package/dist/attach/__tests__/attach-primitives.test.d.ts +2 -0
- package/dist/attach/__tests__/attach-primitives.test.d.ts.map +1 -0
- package/dist/attach/__tests__/attach-primitives.test.js +158 -0
- package/dist/attach/__tests__/attach-primitives.test.js.map +1 -0
- package/dist/attach/__tests__/jxa-args.test.d.ts +2 -0
- package/dist/attach/__tests__/jxa-args.test.d.ts.map +1 -0
- package/dist/attach/__tests__/jxa-args.test.js +37 -0
- package/dist/attach/__tests__/jxa-args.test.js.map +1 -0
- package/dist/attach/__tests__/pack-registration.test.d.ts +2 -0
- package/dist/attach/__tests__/pack-registration.test.d.ts.map +1 -0
- package/dist/attach/__tests__/pack-registration.test.js +34 -0
- package/dist/attach/__tests__/pack-registration.test.js.map +1 -0
- package/dist/attach/__tests__/tools.test.d.ts +2 -0
- package/dist/attach/__tests__/tools.test.d.ts.map +1 -0
- package/dist/attach/__tests__/tools.test.js +155 -0
- package/dist/attach/__tests__/tools.test.js.map +1 -0
- package/dist/attach/backends/__tests__/raw-cdp.test.d.ts +2 -0
- package/dist/attach/backends/__tests__/raw-cdp.test.d.ts.map +1 -0
- package/dist/attach/backends/__tests__/raw-cdp.test.js +133 -0
- package/dist/attach/backends/__tests__/raw-cdp.test.js.map +1 -0
- package/dist/attach/backends/jxa.d.ts +39 -0
- package/dist/attach/backends/jxa.d.ts.map +1 -0
- package/dist/attach/backends/jxa.js +188 -0
- package/dist/attach/backends/jxa.js.map +1 -0
- package/dist/attach/backends/raw-cdp.d.ts +53 -0
- package/dist/attach/backends/raw-cdp.d.ts.map +1 -0
- package/dist/attach/backends/raw-cdp.js +216 -0
- package/dist/attach/backends/raw-cdp.js.map +1 -0
- package/dist/attach/daemon/__tests__/client.test.d.ts +2 -0
- package/dist/attach/daemon/__tests__/client.test.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/client.test.js +58 -0
- package/dist/attach/daemon/__tests__/client.test.js.map +1 -0
- package/dist/attach/daemon/__tests__/daemon-lock.test.d.ts +2 -0
- package/dist/attach/daemon/__tests__/daemon-lock.test.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/daemon-lock.test.js +72 -0
- package/dist/attach/daemon/__tests__/daemon-lock.test.js.map +1 -0
- package/dist/attach/daemon/__tests__/daemon-loop.integration.test.d.ts +2 -0
- package/dist/attach/daemon/__tests__/daemon-loop.integration.test.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/daemon-loop.integration.test.js +102 -0
- package/dist/attach/daemon/__tests__/daemon-loop.integration.test.js.map +1 -0
- package/dist/attach/daemon/__tests__/harness.d.ts +44 -0
- package/dist/attach/daemon/__tests__/harness.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/harness.js +96 -0
- package/dist/attach/daemon/__tests__/harness.js.map +1 -0
- package/dist/attach/daemon/__tests__/protocol.test.d.ts +2 -0
- package/dist/attach/daemon/__tests__/protocol.test.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/protocol.test.js +71 -0
- package/dist/attach/daemon/__tests__/protocol.test.js.map +1 -0
- package/dist/attach/daemon/__tests__/runner.test.d.ts +2 -0
- package/dist/attach/daemon/__tests__/runner.test.d.ts.map +1 -0
- package/dist/attach/daemon/__tests__/runner.test.js +67 -0
- package/dist/attach/daemon/__tests__/runner.test.js.map +1 -0
- package/dist/attach/daemon/client.d.ts +64 -0
- package/dist/attach/daemon/client.d.ts.map +1 -0
- package/dist/attach/daemon/client.js +120 -0
- package/dist/attach/daemon/client.js.map +1 -0
- package/dist/attach/daemon/daemon-lock.d.ts +19 -0
- package/dist/attach/daemon/daemon-lock.d.ts.map +1 -0
- package/dist/attach/daemon/daemon-lock.js +87 -0
- package/dist/attach/daemon/daemon-lock.js.map +1 -0
- package/dist/attach/daemon/daemon-main.d.ts +6 -0
- package/dist/attach/daemon/daemon-main.d.ts.map +1 -0
- package/dist/attach/daemon/daemon-main.js +80 -0
- package/dist/attach/daemon/daemon-main.js.map +1 -0
- package/dist/attach/daemon/daemon.d.ts +52 -0
- package/dist/attach/daemon/daemon.d.ts.map +1 -0
- package/dist/attach/daemon/daemon.js +264 -0
- package/dist/attach/daemon/daemon.js.map +1 -0
- package/dist/attach/daemon/index.d.ts +12 -0
- package/dist/attach/daemon/index.d.ts.map +1 -0
- package/dist/attach/daemon/index.js +30 -0
- package/dist/attach/daemon/index.js.map +1 -0
- package/dist/attach/daemon/protocol.d.ts +69 -0
- package/dist/attach/daemon/protocol.d.ts.map +1 -0
- package/dist/attach/daemon/protocol.js +108 -0
- package/dist/attach/daemon/protocol.js.map +1 -0
- package/dist/attach/daemon/runner.d.ts +64 -0
- package/dist/attach/daemon/runner.d.ts.map +1 -0
- package/dist/attach/daemon/runner.js +60 -0
- package/dist/attach/daemon/runner.js.map +1 -0
- package/dist/attach/daemon/surface.d.ts +31 -0
- package/dist/attach/daemon/surface.d.ts.map +1 -0
- package/dist/attach/daemon/surface.js +89 -0
- package/dist/attach/daemon/surface.js.map +1 -0
- package/dist/attach/devtools-port.d.ts +37 -0
- package/dist/attach/devtools-port.d.ts.map +1 -0
- package/dist/attach/devtools-port.js +50 -0
- package/dist/attach/devtools-port.js.map +1 -0
- package/dist/attach/errors.d.ts +38 -0
- package/dist/attach/errors.d.ts.map +1 -0
- package/dist/attach/errors.js +72 -0
- package/dist/attach/errors.js.map +1 -0
- package/dist/attach/lease.d.ts +43 -0
- package/dist/attach/lease.d.ts.map +1 -0
- package/dist/attach/lease.js +92 -0
- package/dist/attach/lease.js.map +1 -0
- package/dist/attach/singleton-lock.d.ts +21 -0
- package/dist/attach/singleton-lock.d.ts.map +1 -0
- package/dist/attach/singleton-lock.js +30 -0
- package/dist/attach/singleton-lock.js.map +1 -0
- package/dist/attach/state.d.ts +31 -0
- package/dist/attach/state.d.ts.map +1 -0
- package/dist/attach/state.js +78 -0
- package/dist/attach/state.js.map +1 -0
- package/dist/attach/tools.d.ts +208 -0
- package/dist/attach/tools.d.ts.map +1 -0
- package/dist/attach/tools.js +195 -0
- package/dist/attach/tools.js.map +1 -0
- package/dist/attach/url-policy.d.ts +41 -0
- package/dist/attach/url-policy.d.ts.map +1 -0
- package/dist/attach/url-policy.js +59 -0
- package/dist/attach/url-policy.js.map +1 -0
- package/dist/attach.d.ts +18 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +34 -0
- package/dist/attach.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/package.json +22 -7
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const vitest_1 = require("vitest");
|
|
37
|
+
const node_fs_1 = require("node:fs");
|
|
38
|
+
const node_os_1 = require("node:os");
|
|
39
|
+
const node_path_1 = require("node:path");
|
|
40
|
+
const AttachController_js_1 = require("../AttachController.js");
|
|
41
|
+
const tools_js_1 = require("../tools.js");
|
|
42
|
+
function backend() {
|
|
43
|
+
return {
|
|
44
|
+
kind: 'jxa',
|
|
45
|
+
async connect() { },
|
|
46
|
+
async disconnectTransport() { },
|
|
47
|
+
async claimAgentTab() {
|
|
48
|
+
return 'w1 t1';
|
|
49
|
+
},
|
|
50
|
+
async probeIdentity() {
|
|
51
|
+
return 'Inbox - johnny@example.com - Gmail';
|
|
52
|
+
},
|
|
53
|
+
async gotoTab(_t, url) {
|
|
54
|
+
return url;
|
|
55
|
+
},
|
|
56
|
+
async readTab() {
|
|
57
|
+
return 'PAGE BODY TEXT';
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
let controller;
|
|
62
|
+
(0, vitest_1.beforeEach)(() => {
|
|
63
|
+
const leaseFile = (0, node_path_1.join)((0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'attach-tools-')), 'attach.lease');
|
|
64
|
+
controller = new AttachController_js_1.AttachController({ backend: backend(), leaseFile, expectedIdentity: 'johnny@example.com' });
|
|
65
|
+
});
|
|
66
|
+
(0, vitest_1.describe)('attach tools', () => {
|
|
67
|
+
(0, vitest_1.it)('exposes exactly the six ids and no eval/js tool', () => {
|
|
68
|
+
(0, vitest_1.expect)(tools_js_1.ATTACH_TOOL_IDS).toEqual([
|
|
69
|
+
'browser_attach_status',
|
|
70
|
+
'browser_attach_claim',
|
|
71
|
+
'browser_attach_goto',
|
|
72
|
+
'browser_attach_read',
|
|
73
|
+
'browser_attach_release',
|
|
74
|
+
'browser_attach_control',
|
|
75
|
+
]);
|
|
76
|
+
(0, vitest_1.expect)(tools_js_1.ATTACH_TOOL_IDS).not.toContain('browser_attach_eval');
|
|
77
|
+
(0, vitest_1.expect)((0, tools_js_1.createAttachTools)(controller)).toHaveLength(6);
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.it)('control tool pauses, resumes, and toggles dry-run at runtime', async () => {
|
|
80
|
+
const ctl = new tools_js_1.AttachControlTool(controller);
|
|
81
|
+
await new tools_js_1.AttachClaimTool(controller).execute();
|
|
82
|
+
(0, vitest_1.expect)((await ctl.execute({ action: 'pause' })).data.paused).toBe(true);
|
|
83
|
+
(0, vitest_1.expect)((await ctl.execute({ action: 'resume' })).data.paused).toBe(false);
|
|
84
|
+
(0, vitest_1.expect)((await ctl.execute({ action: 'dry_run_on' })).data.dryRun).toBe(true);
|
|
85
|
+
(0, vitest_1.expect)((await ctl.execute({ action: 'dry_run_off' })).data.dryRun).toBe(false);
|
|
86
|
+
(0, vitest_1.expect)((await ctl.execute({ action: 'status' })).data.leaseHeld).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
(0, vitest_1.it)('status and read are non-side-effecting; claim/goto/release are side-effecting', () => {
|
|
89
|
+
(0, vitest_1.expect)(new tools_js_1.AttachStatusTool(controller).hasSideEffects).toBe(false);
|
|
90
|
+
(0, vitest_1.expect)(new tools_js_1.AttachReadTool(controller).hasSideEffects).toBe(false);
|
|
91
|
+
(0, vitest_1.expect)(new tools_js_1.AttachClaimTool(controller).hasSideEffects).toBe(true);
|
|
92
|
+
(0, vitest_1.expect)(new tools_js_1.AttachGotoTool(controller).hasSideEffects).toBe(true);
|
|
93
|
+
(0, vitest_1.expect)(new tools_js_1.AttachReleaseTool(controller).hasSideEffects).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.it)('runs the full claim → goto → read → release envelope', async () => {
|
|
96
|
+
(0, vitest_1.expect)((await new tools_js_1.AttachClaimTool(controller).execute()).success).toBe(true);
|
|
97
|
+
const goto = await new tools_js_1.AttachGotoTool(controller).execute({ url: 'https://founderscard.com/home' });
|
|
98
|
+
(0, vitest_1.expect)(goto).toMatchObject({ success: true, data: { url: 'https://founderscard.com/home' } });
|
|
99
|
+
const read = await new tools_js_1.AttachReadTool(controller).execute({});
|
|
100
|
+
(0, vitest_1.expect)(read.data).toMatchObject({ untrusted: true, text: 'PAGE BODY TEXT' });
|
|
101
|
+
const rel = await new tools_js_1.AttachReleaseTool(controller).execute();
|
|
102
|
+
(0, vitest_1.expect)(rel).toMatchObject({ success: true, data: { released: true } });
|
|
103
|
+
});
|
|
104
|
+
(0, vitest_1.it)('goto returns a structured error envelope (not a throw) on a blocked URL', async () => {
|
|
105
|
+
await new tools_js_1.AttachClaimTool(controller).execute();
|
|
106
|
+
const res = await new tools_js_1.AttachGotoTool(controller).execute({ url: 'file:///etc/passwd' });
|
|
107
|
+
(0, vitest_1.expect)(res.success).toBe(false);
|
|
108
|
+
(0, vitest_1.expect)(res.code).toBe('POLICY_BLOCKED');
|
|
109
|
+
});
|
|
110
|
+
(0, vitest_1.it)('status never throws even before a claim', async () => {
|
|
111
|
+
const res = await new tools_js_1.AttachStatusTool(controller).execute();
|
|
112
|
+
(0, vitest_1.expect)(res.success).toBe(true);
|
|
113
|
+
(0, vitest_1.expect)(res.data.leaseHeld).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
(0, vitest_1.describe)('tools over the daemon surface', () => {
|
|
117
|
+
(0, vitest_1.it)('browser_attach_* flows tool -> IPC -> daemon -> controller -> backend', async () => {
|
|
118
|
+
const { rmSync } = await Promise.resolve().then(() => __importStar(require('node:fs')));
|
|
119
|
+
const { DaemonAttachSurface } = await Promise.resolve().then(() => __importStar(require('../daemon/surface.js')));
|
|
120
|
+
const { AttachDaemonClient } = await Promise.resolve().then(() => __importStar(require('../daemon/client.js')));
|
|
121
|
+
const { daemonUnderTest } = await Promise.resolve().then(() => __importStar(require('../daemon/__tests__/harness.js')));
|
|
122
|
+
const { createAttachTools, ATTACH_TOOL_IDS } = await Promise.resolve().then(() => __importStar(require('../tools.js')));
|
|
123
|
+
const { dir, backend, run } = daemonUnderTest();
|
|
124
|
+
try {
|
|
125
|
+
const surface = new DaemonAttachSurface({ ipcDir: (0, node_path_1.join)(dir, 'ipc') });
|
|
126
|
+
const tools = createAttachTools(surface);
|
|
127
|
+
const byId = Object.fromEntries(tools.map((t) => [t.id, t]));
|
|
128
|
+
(0, vitest_1.expect)(Object.keys(byId).sort()).toEqual([...ATTACH_TOOL_IDS].sort()); // ids unchanged
|
|
129
|
+
(0, vitest_1.expect)(byId['browser_attach_read'].hasSideEffects).toBe(false);
|
|
130
|
+
(0, vitest_1.expect)(byId['browser_attach_status'].hasSideEffects).toBe(false);
|
|
131
|
+
(0, vitest_1.expect)((await byId['browser_attach_claim'].execute({})).success).toBe(true);
|
|
132
|
+
const nav = await byId['browser_attach_goto'].execute({ url: 'https://example.com/' });
|
|
133
|
+
(0, vitest_1.expect)(nav.success).toBe(true);
|
|
134
|
+
(0, vitest_1.expect)(backend.calls).toContain('goto:https://example.com/');
|
|
135
|
+
const read = await byId['browser_attach_read'].execute({});
|
|
136
|
+
(0, vitest_1.expect)(read.success).toBe(true);
|
|
137
|
+
(0, vitest_1.expect)(read.data.untrusted).toBe(true);
|
|
138
|
+
(0, vitest_1.expect)((await byId['browser_attach_release'].execute()).success).toBe(true);
|
|
139
|
+
await new AttachDaemonClient({ ipcDir: (0, node_path_1.join)(dir, 'ipc'), client: 'test-quit', pollMs: 25 }).quit();
|
|
140
|
+
await run;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
rmSync(dir, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
}, 60000);
|
|
146
|
+
(0, vitest_1.it)('the daemon surface exposes no eval anywhere on the tool path', async () => {
|
|
147
|
+
const { DaemonAttachSurface } = await Promise.resolve().then(() => __importStar(require('../daemon/surface.js')));
|
|
148
|
+
const surface = new DaemonAttachSurface({ ipcDir: (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'attach-noeval-')) });
|
|
149
|
+
const asRecord = surface;
|
|
150
|
+
(0, vitest_1.expect)(asRecord.evaluate).toBeUndefined();
|
|
151
|
+
(0, vitest_1.expect)(asRecord.eval).toBeUndefined();
|
|
152
|
+
(0, vitest_1.expect)(asRecord.extract).toBeUndefined();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../../src/attach/__tests__/tools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-cdp.test.d.ts","sourceRoot":"","sources":["../../../../src/attach/backends/__tests__/raw-cdp.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const ws_1 = require("ws");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_os_1 = require("node:os");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const raw_cdp_js_1 = require("../raw-cdp.js");
|
|
9
|
+
/** Minimal fake CDP browser endpoint: answers exactly the methods the backend may send. */
|
|
10
|
+
function fakeCdp(opts = {}) {
|
|
11
|
+
const wss = new ws_1.WebSocketServer({ port: 0, path: '/devtools/browser/fake' });
|
|
12
|
+
const seen = [];
|
|
13
|
+
const created = [];
|
|
14
|
+
const closed = [];
|
|
15
|
+
wss.on('connection', (sock) => {
|
|
16
|
+
sock.on('message', (buf) => {
|
|
17
|
+
const m = JSON.parse(String(buf));
|
|
18
|
+
seen.push(m.method);
|
|
19
|
+
if (opts.wedgeAfterConnect)
|
|
20
|
+
return; // never answer: simulates a zombie handshake
|
|
21
|
+
const reply = (result) => sock.send(JSON.stringify({ id: m.id, result }));
|
|
22
|
+
switch (m.method) {
|
|
23
|
+
case 'Target.getTargets':
|
|
24
|
+
return reply({ targetInfos: (opts.pages ?? []).map((p) => ({ ...p, type: 'page' })) });
|
|
25
|
+
case 'Target.createTarget': {
|
|
26
|
+
const targetId = `created-${created.length + 1}`;
|
|
27
|
+
created.push(targetId);
|
|
28
|
+
return reply({ targetId });
|
|
29
|
+
}
|
|
30
|
+
case 'Target.attachToTarget':
|
|
31
|
+
return reply({ sessionId: 'sess-1' });
|
|
32
|
+
case 'Target.closeTarget':
|
|
33
|
+
closed.push(m.params.targetId);
|
|
34
|
+
return reply({ success: true });
|
|
35
|
+
case 'Page.enable':
|
|
36
|
+
case 'Runtime.enable':
|
|
37
|
+
return reply({});
|
|
38
|
+
case 'Page.navigate':
|
|
39
|
+
return reply({ frameId: 'f1' });
|
|
40
|
+
case 'Runtime.evaluate':
|
|
41
|
+
return reply({
|
|
42
|
+
result: { value: m.params.expression.includes('location.href') ? 'https://example.com/' : 'evaluated' },
|
|
43
|
+
});
|
|
44
|
+
default:
|
|
45
|
+
return reply({});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
return { wss, seen, created, closed, port: () => wss.address().port };
|
|
50
|
+
}
|
|
51
|
+
/** Profile root whose DevToolsActivePort points at the fake server. */
|
|
52
|
+
function profileRootFor(port) {
|
|
53
|
+
const d = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'attach-prof-'));
|
|
54
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(d, 'DevToolsActivePort'), `${port}\n/devtools/browser/fake`);
|
|
55
|
+
return d;
|
|
56
|
+
}
|
|
57
|
+
const cleanup = [];
|
|
58
|
+
(0, vitest_1.afterEach)(() => {
|
|
59
|
+
for (const f of cleanup.splice(0))
|
|
60
|
+
f();
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.describe)('RawCdpBackend', () => {
|
|
63
|
+
(0, vitest_1.it)('attaches to exactly ONE created target and never closes foreign targets', async () => {
|
|
64
|
+
const srv = fakeCdp({
|
|
65
|
+
pages: [{ targetId: 'user-tab-1', url: 'https://mail.google.com/', title: 'Inbox - user@gmail.com - Gmail' }],
|
|
66
|
+
});
|
|
67
|
+
cleanup.push(() => srv.wss.close());
|
|
68
|
+
const prof = profileRootFor(srv.port());
|
|
69
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(prof, { recursive: true, force: true }));
|
|
70
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: prof, settleMs: 0 });
|
|
71
|
+
await be.connect();
|
|
72
|
+
const tab = await be.claimAgentTab();
|
|
73
|
+
(0, vitest_1.expect)(srv.created).toContain(tab);
|
|
74
|
+
(0, vitest_1.expect)(await be.gotoTab(tab, 'https://example.com/')).toBe('https://example.com/');
|
|
75
|
+
(0, vitest_1.expect)(await be.readTab(tab)).toBe('evaluated');
|
|
76
|
+
await be.disconnectTransport();
|
|
77
|
+
(0, vitest_1.expect)(srv.seen).not.toContain('Browser.close');
|
|
78
|
+
(0, vitest_1.expect)(srv.closed).toEqual([tab]); // ONLY our own created tab, ever
|
|
79
|
+
});
|
|
80
|
+
(0, vitest_1.it)('probeIdentity reads target metadata only (no attach, no navigation)', async () => {
|
|
81
|
+
const srv = fakeCdp({
|
|
82
|
+
pages: [{ targetId: 'user-tab-1', url: 'https://mail.google.com/mail/u/0', title: 'Inbox - user@gmail.com - Gmail' }],
|
|
83
|
+
});
|
|
84
|
+
cleanup.push(() => srv.wss.close());
|
|
85
|
+
const prof = profileRootFor(srv.port());
|
|
86
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(prof, { recursive: true, force: true }));
|
|
87
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: prof });
|
|
88
|
+
await be.connect();
|
|
89
|
+
const before = srv.seen.length;
|
|
90
|
+
const identity = await be.probeIdentity();
|
|
91
|
+
(0, vitest_1.expect)(identity).toContain('user@gmail.com');
|
|
92
|
+
(0, vitest_1.expect)(srv.seen.slice(before)).toEqual(['Target.getTargets']); // metadata only
|
|
93
|
+
await be.disconnectTransport();
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.it)('missing DevToolsActivePort throws CDP_UNAVAILABLE without any connection', async () => {
|
|
96
|
+
const d = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'attach-noprof-'));
|
|
97
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(d, { recursive: true, force: true }));
|
|
98
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: d });
|
|
99
|
+
await (0, vitest_1.expect)(be.connect()).rejects.toMatchObject({ code: 'CDP_UNAVAILABLE' });
|
|
100
|
+
});
|
|
101
|
+
(0, vitest_1.it)('malformed DevToolsActivePort throws STALE_PORT_FILE', async () => {
|
|
102
|
+
const d = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'attach-badprof-'));
|
|
103
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(d, { recursive: true, force: true }));
|
|
104
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(d, 'DevToolsActivePort'), 'garbage\n');
|
|
105
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: d });
|
|
106
|
+
await (0, vitest_1.expect)(be.connect()).rejects.toMatchObject({ code: 'STALE_PORT_FILE' });
|
|
107
|
+
});
|
|
108
|
+
(0, vitest_1.it)('a wedged endpoint times out with CDP_TIMEOUT instead of hanging', async () => {
|
|
109
|
+
const srv = fakeCdp({ wedgeAfterConnect: true });
|
|
110
|
+
cleanup.push(() => srv.wss.close());
|
|
111
|
+
const prof = profileRootFor(srv.port());
|
|
112
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(prof, { recursive: true, force: true }));
|
|
113
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: prof, commandTimeoutMs: 300 });
|
|
114
|
+
await be.connect();
|
|
115
|
+
await (0, vitest_1.expect)(be.claimAgentTab()).rejects.toMatchObject({ code: 'CDP_TIMEOUT' });
|
|
116
|
+
await be.disconnectTransport();
|
|
117
|
+
});
|
|
118
|
+
(0, vitest_1.it)('an unexpected transport drop fails pending commands and fires onUnexpectedClose once', async () => {
|
|
119
|
+
const srv = fakeCdp({ wedgeAfterConnect: true });
|
|
120
|
+
cleanup.push(() => srv.wss.close());
|
|
121
|
+
const prof = profileRootFor(srv.port());
|
|
122
|
+
cleanup.push(() => (0, node_fs_1.rmSync)(prof, { recursive: true, force: true }));
|
|
123
|
+
const be = new raw_cdp_js_1.RawCdpBackend({ profileRoot: prof, commandTimeoutMs: 5000 });
|
|
124
|
+
const drops = [];
|
|
125
|
+
be.onUnexpectedClose = (err) => drops.push(err.message);
|
|
126
|
+
await be.connect();
|
|
127
|
+
const inflight = be.claimAgentTab();
|
|
128
|
+
srv.wss.clients.forEach((c) => c.terminate());
|
|
129
|
+
await (0, vitest_1.expect)(inflight).rejects.toMatchObject({ code: 'CDP_UNAVAILABLE' });
|
|
130
|
+
(0, vitest_1.expect)(drops).toHaveLength(1);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=raw-cdp.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-cdp.test.js","sourceRoot":"","sources":["../../../../src/attach/backends/__tests__/raw-cdp.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AttachBackend } from '../AttachController.js';
|
|
2
|
+
/** Options for {@link JxaBackend}. */
|
|
3
|
+
export interface JxaBackendOptions {
|
|
4
|
+
/** Chrome profile root (defaults to the macOS default profile root). */
|
|
5
|
+
profileRoot?: string;
|
|
6
|
+
/** Identity probe URL (a page whose title reveals the signed-in account). */
|
|
7
|
+
identityProbeUrl?: string;
|
|
8
|
+
/** Per-exec timeout ms (default 40s). */
|
|
9
|
+
execTimeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build the exact osascript argv for a driver invocation. Pure + exported for
|
|
13
|
+
* unit tests: arguments pass as argv (never shell-interpolated). The driver
|
|
14
|
+
* receives `profileRoot` as its first arg, then the command and its args.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildJxaArgs(script: string, profileRoot: string, cmd: string, args: string[]): string[];
|
|
17
|
+
/** The embedded JXA driver source (written to a temp file at first use). */
|
|
18
|
+
export declare const JXA_DRIVER_SOURCE = "ObjC.import('Foundation');\nfunction chromePid(root) {\n const dest = $.NSFileManager.defaultManager.destinationOfSymbolicLinkAtPathError(root + '/SingletonLock', null);\n if (!dest || !dest.js) throw new Error('SingletonLock unreadable');\n return parseInt(dest.js.match(/-(\\d+)$/)[1], 10);\n}\nfunction run(argv) {\n const root = argv[0], cmd = argv[1];\n const c = Application(chromePid(root));\n c.includeStandardAdditions = false;\n const MARKER = '__agentos_attach_tab_v1__';\n if (cmd === 'claim') {\n for (const w of c.windows()) {\n for (const t of w.tabs()) {\n if (t.url() === 'about:blank') {\n try { c.execute(t, { javascript: 'window.name=' + JSON.stringify(MARKER) }); } catch (e) {}\n return w.id() + ' ' + t.id();\n }\n }\n }\n throw new Error('NO_BLANK_TAB: open a fresh tab (about:blank) in the target profile first');\n }\n const wid = argv[2], tid = argv[3];\n const w = c.windows().find((x) => String(x.id()) === String(wid));\n if (!w) throw new Error('window ' + wid + ' not found');\n const t = w.tabs().find((x) => String(x.id()) === String(tid));\n if (!t) throw new Error('tab ' + tid + ' not found in window ' + wid);\n if (cmd === 'goto') {\n t.url = argv[4];\n for (let i = 0; i < 80; i++) { delay(0.5); try { if (t.loading() === false) break; } catch (e) { break; } }\n delay(1);\n return t.url();\n }\n if (cmd === 'url') return t.url() + '\\n' + t.title();\n if (cmd === 'read') {\n const sel = argv[4] || 'body';\n const max = parseInt(argv[5] || '6000', 10);\n const js = '(document.querySelector(' + JSON.stringify(sel) + ')||document.body).innerText.slice(0,' + max + ')';\n const r = c.execute(t, { javascript: js });\n return typeof r === 'string' ? r : JSON.stringify(r);\n }\n throw new Error('unknown cmd ' + cmd);\n}\n";
|
|
19
|
+
/** macOS JXA transport backend. */
|
|
20
|
+
export declare class JxaBackend implements AttachBackend {
|
|
21
|
+
readonly kind: "jxa";
|
|
22
|
+
private readonly profileRoot;
|
|
23
|
+
private readonly identityProbeUrl;
|
|
24
|
+
private readonly execTimeoutMs;
|
|
25
|
+
private driverPath?;
|
|
26
|
+
private claimed?;
|
|
27
|
+
constructor(opts?: JxaBackendOptions);
|
|
28
|
+
/** Verify the SingletonLock resolves (Chrome is running) — no side effects. */
|
|
29
|
+
connect(): Promise<void>;
|
|
30
|
+
/** Nothing persistent to tear down: each op is a discrete osascript exec. */
|
|
31
|
+
disconnectTransport(): Promise<void>;
|
|
32
|
+
private driver;
|
|
33
|
+
private exec;
|
|
34
|
+
claimAgentTab(): Promise<string>;
|
|
35
|
+
probeIdentity(): Promise<string>;
|
|
36
|
+
gotoTab(tab: string, url: string): Promise<string>;
|
|
37
|
+
readTab(tab: string, selector?: string, maxChars?: number): Promise<string>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=jxa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jxa.d.ts","sourceRoot":"","sources":["../../../src/attach/backends/jxa.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAI5D,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEvG;AAED,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,00DA2C7B,CAAC;AAEF,mCAAmC;AACnC,qBAAa,UAAW,YAAW,aAAa;IAC9C,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAC,CAA+B;gBAEnC,IAAI,GAAE,iBAAsB;IAMxC,+EAA+E;IACzE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,6EAA6E;IACvE,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;YAI5B,MAAM;YAWN,IAAI;IAeZ,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKlD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAIlF"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.JxaBackend = exports.JXA_DRIVER_SOURCE = void 0;
|
|
37
|
+
exports.buildJxaArgs = buildJxaArgs;
|
|
38
|
+
/**
|
|
39
|
+
* @fileoverview JXA (macOS) attach backend.
|
|
40
|
+
*
|
|
41
|
+
* Drives the user's RUNNING Chrome through `osascript -l JavaScript`,
|
|
42
|
+
* addressing the application BY PID resolved from the profile root's
|
|
43
|
+
* `SingletonLock` symlink — bundle-name addressing is ambiguous when more than
|
|
44
|
+
* one Chrome instance runs (e.g. a devtools-mcp cache instance) and MUST NOT
|
|
45
|
+
* be used. Navigation and reads work on background tabs; nothing here focuses,
|
|
46
|
+
* creates windows beyond the agent tab, or closes anything.
|
|
47
|
+
*
|
|
48
|
+
* The embedded driver mirrors the field-proven `vca-jxa.js` contract:
|
|
49
|
+
* claim (marker-binds an about:blank tab), goto (poll `loading`), url, and a
|
|
50
|
+
* selector-scoped innerText read. Raw arbitrary page JS is deliberately NOT
|
|
51
|
+
* exposed (Codex spec review F2).
|
|
52
|
+
*
|
|
53
|
+
* @module browser-automation/attach/backends/jxa
|
|
54
|
+
*/
|
|
55
|
+
const node_child_process_1 = require("node:child_process");
|
|
56
|
+
const node_util_1 = require("node:util");
|
|
57
|
+
const node_os_1 = require("node:os");
|
|
58
|
+
const node_path_1 = require("node:path");
|
|
59
|
+
const node_fs_1 = require("node:fs");
|
|
60
|
+
const singleton_lock_js_1 = require("../singleton-lock.js");
|
|
61
|
+
const errors_js_1 = require("../errors.js");
|
|
62
|
+
const pExecFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
63
|
+
/**
|
|
64
|
+
* Build the exact osascript argv for a driver invocation. Pure + exported for
|
|
65
|
+
* unit tests: arguments pass as argv (never shell-interpolated). The driver
|
|
66
|
+
* receives `profileRoot` as its first arg, then the command and its args.
|
|
67
|
+
*/
|
|
68
|
+
function buildJxaArgs(script, profileRoot, cmd, args) {
|
|
69
|
+
return ['-l', 'JavaScript', script, profileRoot, cmd, ...args];
|
|
70
|
+
}
|
|
71
|
+
/** The embedded JXA driver source (written to a temp file at first use). */
|
|
72
|
+
exports.JXA_DRIVER_SOURCE = `ObjC.import('Foundation');
|
|
73
|
+
function chromePid(root) {
|
|
74
|
+
const dest = $.NSFileManager.defaultManager.destinationOfSymbolicLinkAtPathError(root + '/SingletonLock', null);
|
|
75
|
+
if (!dest || !dest.js) throw new Error('SingletonLock unreadable');
|
|
76
|
+
return parseInt(dest.js.match(/-(\\d+)$/)[1], 10);
|
|
77
|
+
}
|
|
78
|
+
function run(argv) {
|
|
79
|
+
const root = argv[0], cmd = argv[1];
|
|
80
|
+
const c = Application(chromePid(root));
|
|
81
|
+
c.includeStandardAdditions = false;
|
|
82
|
+
const MARKER = '__agentos_attach_tab_v1__';
|
|
83
|
+
if (cmd === 'claim') {
|
|
84
|
+
for (const w of c.windows()) {
|
|
85
|
+
for (const t of w.tabs()) {
|
|
86
|
+
if (t.url() === 'about:blank') {
|
|
87
|
+
try { c.execute(t, { javascript: 'window.name=' + JSON.stringify(MARKER) }); } catch (e) {}
|
|
88
|
+
return w.id() + ' ' + t.id();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw new Error('NO_BLANK_TAB: open a fresh tab (about:blank) in the target profile first');
|
|
93
|
+
}
|
|
94
|
+
const wid = argv[2], tid = argv[3];
|
|
95
|
+
const w = c.windows().find((x) => String(x.id()) === String(wid));
|
|
96
|
+
if (!w) throw new Error('window ' + wid + ' not found');
|
|
97
|
+
const t = w.tabs().find((x) => String(x.id()) === String(tid));
|
|
98
|
+
if (!t) throw new Error('tab ' + tid + ' not found in window ' + wid);
|
|
99
|
+
if (cmd === 'goto') {
|
|
100
|
+
t.url = argv[4];
|
|
101
|
+
for (let i = 0; i < 80; i++) { delay(0.5); try { if (t.loading() === false) break; } catch (e) { break; } }
|
|
102
|
+
delay(1);
|
|
103
|
+
return t.url();
|
|
104
|
+
}
|
|
105
|
+
if (cmd === 'url') return t.url() + '\\n' + t.title();
|
|
106
|
+
if (cmd === 'read') {
|
|
107
|
+
const sel = argv[4] || 'body';
|
|
108
|
+
const max = parseInt(argv[5] || '6000', 10);
|
|
109
|
+
const js = '(document.querySelector(' + JSON.stringify(sel) + ')||document.body).innerText.slice(0,' + max + ')';
|
|
110
|
+
const r = c.execute(t, { javascript: js });
|
|
111
|
+
return typeof r === 'string' ? r : JSON.stringify(r);
|
|
112
|
+
}
|
|
113
|
+
throw new Error('unknown cmd ' + cmd);
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
/** macOS JXA transport backend. */
|
|
117
|
+
class JxaBackend {
|
|
118
|
+
constructor(opts = {}) {
|
|
119
|
+
this.kind = 'jxa';
|
|
120
|
+
this.profileRoot = opts.profileRoot ?? (0, node_path_1.join)((0, node_os_1.homedir)(), 'Library/Application Support/Google/Chrome');
|
|
121
|
+
this.identityProbeUrl = opts.identityProbeUrl ?? 'https://mail.google.com/mail/u/0/';
|
|
122
|
+
this.execTimeoutMs = opts.execTimeoutMs ?? 40000;
|
|
123
|
+
}
|
|
124
|
+
/** Verify the SingletonLock resolves (Chrome is running) — no side effects. */
|
|
125
|
+
async connect() {
|
|
126
|
+
let target;
|
|
127
|
+
try {
|
|
128
|
+
target = (0, node_fs_1.readlinkSync)((0, node_path_1.join)(this.profileRoot, 'SingletonLock'));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
throw new errors_js_1.AttachError('CDP_UNAVAILABLE', 'no running Chrome found for the target profile root (SingletonLock absent)');
|
|
132
|
+
}
|
|
133
|
+
(0, singleton_lock_js_1.pidFromSingletonLock)(target); // throws on malformed
|
|
134
|
+
}
|
|
135
|
+
/** Nothing persistent to tear down: each op is a discrete osascript exec. */
|
|
136
|
+
async disconnectTransport() {
|
|
137
|
+
this.claimed = undefined;
|
|
138
|
+
}
|
|
139
|
+
async driver() {
|
|
140
|
+
if (this.driverPath)
|
|
141
|
+
return this.driverPath;
|
|
142
|
+
const { mkdtempSync, writeFileSync } = await Promise.resolve().then(() => __importStar(require('node:fs')));
|
|
143
|
+
const { tmpdir } = await Promise.resolve().then(() => __importStar(require('node:os')));
|
|
144
|
+
const dir = mkdtempSync((0, node_path_1.join)(tmpdir(), 'attach-jxa-'));
|
|
145
|
+
const file = (0, node_path_1.join)(dir, 'driver.js');
|
|
146
|
+
writeFileSync(file, exports.JXA_DRIVER_SOURCE);
|
|
147
|
+
this.driverPath = file;
|
|
148
|
+
return file;
|
|
149
|
+
}
|
|
150
|
+
async exec(cmd, args) {
|
|
151
|
+
const script = await this.driver();
|
|
152
|
+
const argv = buildJxaArgs(script, this.profileRoot, cmd, args);
|
|
153
|
+
try {
|
|
154
|
+
const { stdout } = await pExecFile('osascript', argv, { timeout: this.execTimeoutMs });
|
|
155
|
+
return stdout.trim();
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
159
|
+
throw new errors_js_1.AttachError(/turned off/i.test(msg) ? 'JS_DISABLED' : /not authorized/i.test(msg) ? 'ACCESSIBILITY_DENIED' : 'UNKNOWN', msg);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async claimAgentTab() {
|
|
163
|
+
const out = await this.exec('claim', []);
|
|
164
|
+
const [wid, tid] = out.split(/\s+/);
|
|
165
|
+
if (!wid || !tid)
|
|
166
|
+
throw new errors_js_1.AttachError('TAB_CLOSED', `claim returned malformed ids: "${out}"`);
|
|
167
|
+
this.claimed = { wid, tid };
|
|
168
|
+
return `${wid} ${tid}`;
|
|
169
|
+
}
|
|
170
|
+
async probeIdentity() {
|
|
171
|
+
// Claim first if needed so the probe never touches a user tab.
|
|
172
|
+
if (!this.claimed)
|
|
173
|
+
await this.claimAgentTab();
|
|
174
|
+
const { wid, tid } = this.claimed;
|
|
175
|
+
await this.exec('goto', [wid, tid, this.identityProbeUrl]);
|
|
176
|
+
return this.exec('url', [wid, tid]);
|
|
177
|
+
}
|
|
178
|
+
async gotoTab(tab, url) {
|
|
179
|
+
const [wid, tid] = tab.split(/\s+/);
|
|
180
|
+
return this.exec('goto', [wid, tid, url]);
|
|
181
|
+
}
|
|
182
|
+
async readTab(tab, selector, maxChars) {
|
|
183
|
+
const [wid, tid] = tab.split(/\s+/);
|
|
184
|
+
return this.exec('read', [wid, tid, selector ?? 'body', String(maxChars ?? 6000)]);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.JxaBackend = JxaBackend;
|
|
188
|
+
//# sourceMappingURL=jxa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jxa.js","sourceRoot":"","sources":["../../../src/attach/backends/jxa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AttachBackend } from '../AttachController.js';
|
|
2
|
+
/** Options for {@link RawCdpBackend}. */
|
|
3
|
+
export interface RawCdpBackendOptions {
|
|
4
|
+
/** Chrome profile root holding `DevToolsActivePort` (default: macOS default profile root). */
|
|
5
|
+
profileRoot?: string;
|
|
6
|
+
/** Identity probe: substring matched against page-target urls (default `mail.google.com`). */
|
|
7
|
+
identityProbeUrl?: string;
|
|
8
|
+
/** Post-navigation settle delay ms (default 1800; the daemon sets 0 and settles per op). */
|
|
9
|
+
settleMs?: number;
|
|
10
|
+
/** Per-CDP-command timeout ms (default 20000). */
|
|
11
|
+
commandTimeoutMs?: number;
|
|
12
|
+
/** ws open timeout ms (default 15000). */
|
|
13
|
+
connectTimeoutMs?: number;
|
|
14
|
+
/** Eval result size cap in serialized chars (default 512 * 1024). */
|
|
15
|
+
evalMaxChars?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Raw single-target CDP backend (see fileoverview for the contract).
|
|
19
|
+
*
|
|
20
|
+
* Never sends `Browser.close`; `Target.closeTarget` is only ever issued for
|
|
21
|
+
* the tab this instance created.
|
|
22
|
+
*/
|
|
23
|
+
export declare class RawCdpBackend implements AttachBackend {
|
|
24
|
+
readonly kind: "cdp";
|
|
25
|
+
private readonly opts;
|
|
26
|
+
private ws;
|
|
27
|
+
private nextId;
|
|
28
|
+
private readonly pending;
|
|
29
|
+
private sessionId;
|
|
30
|
+
private createdTargetId;
|
|
31
|
+
/** Invoked once when the transport drops unexpectedly (daemon schedules backoff reconnect). */
|
|
32
|
+
onUnexpectedClose: ((err: Error) => void) | null;
|
|
33
|
+
constructor(options?: RawCdpBackendOptions);
|
|
34
|
+
/** Open the ws to the browser endpoint. Creates/focuses NOTHING. Idempotent while connected. */
|
|
35
|
+
connect(): Promise<void>;
|
|
36
|
+
/** Close ONLY our created tab (if any), then the ws. Never `Browser.close`. */
|
|
37
|
+
disconnectTransport(): Promise<void>;
|
|
38
|
+
/** Create the agent tab, attach flattened to it alone, enable Page/Runtime on that session only. */
|
|
39
|
+
claimAgentTab(): Promise<string>;
|
|
40
|
+
/** Metadata-only identity read: matching page targets' titles/urls. No attach, no navigation. */
|
|
41
|
+
probeIdentity(): Promise<string>;
|
|
42
|
+
/** Navigate the agent tab, settle, return the landed URL. */
|
|
43
|
+
gotoTab(tab: string, url: string): Promise<string>;
|
|
44
|
+
/** innerText read, optional selector scope, capped. */
|
|
45
|
+
readTab(tab: string, selector?: string, maxChars?: number): Promise<string>;
|
|
46
|
+
/** Runtime.evaluate in the agent tab (optional backend capability used by extract/evaluate). */
|
|
47
|
+
evalInTab(tab: string, expression: string, timeoutMs?: number): Promise<unknown>;
|
|
48
|
+
private requireTab;
|
|
49
|
+
private onMessage;
|
|
50
|
+
private failAllPending;
|
|
51
|
+
private send;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=raw-cdp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-cdp.d.ts","sourceRoot":"","sources":["../../../src/attach/backends/raw-cdp.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAI5D,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,8FAA8F;IAC9F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAWD;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,aAAa;IACjD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IACtD,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,eAAe,CAAuB;IAC9C,+FAA+F;IAC/F,iBAAiB,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAE5C,OAAO,GAAE,oBAAyB;IAW9C,gGAAgG;IAC1F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD9B,+EAA+E;IACzE,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB1C,oGAAoG;IAC9F,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAatC,iGAAiG;IAC3F,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAUtC,6DAA6D;IACvD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOxD,uDAAuD;IACjD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ/E,gGAAgG;IAC1F,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBtF,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,IAAI;CAoBb"}
|