@phi-code-admin/browser 1.0.1 → 1.0.2
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/index.d.ts +21 -2
- package/dist/index.js +59 -18
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -30,11 +30,21 @@ export declare function closeAll(): Promise<void>;
|
|
|
30
30
|
export interface CreateTabResult {
|
|
31
31
|
tabId: string;
|
|
32
32
|
userId: string;
|
|
33
|
+
sessionKey: string;
|
|
33
34
|
url?: string;
|
|
34
35
|
}
|
|
35
|
-
/**
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Open a new browser tab. Returns the tab id used by the other tools.
|
|
38
|
+
*
|
|
39
|
+
* The camofox-browser REST contract requires every tab to be associated
|
|
40
|
+
* with a `userId` (logical user) AND a `sessionKey` (logical session
|
|
41
|
+
* inside that user — used to group tabs that should share cookies /
|
|
42
|
+
* fingerprints / proxies). Phi-code's chat agents only need one of each,
|
|
43
|
+
* so both default to a constant sentinel when omitted.
|
|
44
|
+
*/
|
|
45
|
+
export declare function createTab(options?: {
|
|
37
46
|
userId?: string;
|
|
47
|
+
sessionKey?: string;
|
|
38
48
|
url?: string;
|
|
39
49
|
viewport?: {
|
|
40
50
|
width: number;
|
|
@@ -56,6 +66,7 @@ export declare function navigate(options: {
|
|
|
56
66
|
url: string;
|
|
57
67
|
tabId?: string;
|
|
58
68
|
userId?: string;
|
|
69
|
+
sessionKey?: string;
|
|
59
70
|
waitUntil?: "load" | "domcontentloaded" | "networkidle";
|
|
60
71
|
timeoutMs?: number;
|
|
61
72
|
}): Promise<NavigateResult>;
|
|
@@ -65,6 +76,7 @@ export declare function navigate(options: {
|
|
|
65
76
|
*/
|
|
66
77
|
export declare function snapshot(options: {
|
|
67
78
|
tabId: string;
|
|
79
|
+
userId?: string;
|
|
68
80
|
}): Promise<unknown>;
|
|
69
81
|
export interface ExtractResult {
|
|
70
82
|
url?: string;
|
|
@@ -82,6 +94,7 @@ export interface ExtractResult {
|
|
|
82
94
|
export declare function extract(options: {
|
|
83
95
|
tabId?: string;
|
|
84
96
|
userId?: string;
|
|
97
|
+
sessionKey?: string;
|
|
85
98
|
url?: string;
|
|
86
99
|
mode?: "readability" | "html" | "text";
|
|
87
100
|
}): Promise<ExtractResult>;
|
|
@@ -93,6 +106,7 @@ export interface ScreenshotResult {
|
|
|
93
106
|
/** Capture a screenshot of the given tab as a base64-encoded PNG. */
|
|
94
107
|
export declare function screenshot(options: {
|
|
95
108
|
tabId: string;
|
|
109
|
+
userId?: string;
|
|
96
110
|
fullPage?: boolean;
|
|
97
111
|
clip?: {
|
|
98
112
|
x: number;
|
|
@@ -110,10 +124,12 @@ export declare function search(options: {
|
|
|
110
124
|
query: string;
|
|
111
125
|
engine?: "google" | "duckduckgo" | "bing";
|
|
112
126
|
userId?: string;
|
|
127
|
+
sessionKey?: string;
|
|
113
128
|
}): Promise<ExtractResult>;
|
|
114
129
|
/** Click an element by ref (from `snapshot`) or CSS selector. */
|
|
115
130
|
export declare function click(options: {
|
|
116
131
|
tabId: string;
|
|
132
|
+
userId?: string;
|
|
117
133
|
ref?: string;
|
|
118
134
|
selector?: string;
|
|
119
135
|
button?: "left" | "right" | "middle";
|
|
@@ -123,6 +139,7 @@ export declare function click(options: {
|
|
|
123
139
|
/** Type text into a focused element (or one targeted via ref/selector). */
|
|
124
140
|
export declare function type(options: {
|
|
125
141
|
tabId: string;
|
|
142
|
+
userId?: string;
|
|
126
143
|
text: string;
|
|
127
144
|
ref?: string;
|
|
128
145
|
selector?: string;
|
|
@@ -134,6 +151,7 @@ export declare function type(options: {
|
|
|
134
151
|
/** Scroll the page or a specific element by ref. */
|
|
135
152
|
export declare function scroll(options: {
|
|
136
153
|
tabId: string;
|
|
154
|
+
userId?: string;
|
|
137
155
|
direction: "up" | "down" | "left" | "right";
|
|
138
156
|
ref?: string;
|
|
139
157
|
pixels?: number;
|
|
@@ -143,6 +161,7 @@ export declare function scroll(options: {
|
|
|
143
161
|
/** Close a single tab. The underlying browser context is kept warm. */
|
|
144
162
|
export declare function closeTab(options: {
|
|
145
163
|
tabId: string;
|
|
164
|
+
userId?: string;
|
|
146
165
|
}): Promise<{
|
|
147
166
|
tabId: string;
|
|
148
167
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ let serverProcess = null;
|
|
|
26
26
|
let serverPort = null;
|
|
27
27
|
let bootPromise = null;
|
|
28
28
|
const DEFAULT_USER_ID = "phi-default";
|
|
29
|
+
const DEFAULT_SESSION_KEY = "phi-default-session";
|
|
29
30
|
const HEALTH_TIMEOUT_MS = 30_000;
|
|
30
31
|
const HEALTH_POLL_INTERVAL_MS = 250;
|
|
31
32
|
async function findAvailablePort() {
|
|
@@ -243,16 +244,25 @@ async function request(pathname, options = {}) {
|
|
|
243
244
|
clearTimeout(timeout);
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
|
-
/**
|
|
247
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Open a new browser tab. Returns the tab id used by the other tools.
|
|
249
|
+
*
|
|
250
|
+
* The camofox-browser REST contract requires every tab to be associated
|
|
251
|
+
* with a `userId` (logical user) AND a `sessionKey` (logical session
|
|
252
|
+
* inside that user — used to group tabs that should share cookies /
|
|
253
|
+
* fingerprints / proxies). Phi-code's chat agents only need one of each,
|
|
254
|
+
* so both default to a constant sentinel when omitted.
|
|
255
|
+
*/
|
|
256
|
+
export async function createTab(options = {}) {
|
|
248
257
|
const userId = options.userId ?? DEFAULT_USER_ID;
|
|
249
|
-
const
|
|
258
|
+
const sessionKey = options.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
259
|
+
const body = { userId, sessionKey };
|
|
250
260
|
if (options.url)
|
|
251
261
|
body.url = options.url;
|
|
252
262
|
if (options.viewport)
|
|
253
263
|
body.viewport = options.viewport;
|
|
254
264
|
const res = await request("/tabs", { method: "POST", body });
|
|
255
|
-
return { tabId: res.tabId, userId, url: options.url };
|
|
265
|
+
return { tabId: res.tabId, userId, sessionKey, url: options.url };
|
|
256
266
|
}
|
|
257
267
|
/**
|
|
258
268
|
* Navigate the given tab (or a freshly opened one) to a URL.
|
|
@@ -262,11 +272,19 @@ export async function createTab(options) {
|
|
|
262
272
|
export async function navigate(options) {
|
|
263
273
|
let tabId = options.tabId;
|
|
264
274
|
if (!tabId) {
|
|
265
|
-
const tab = await createTab({
|
|
275
|
+
const tab = await createTab({
|
|
276
|
+
userId: options.userId,
|
|
277
|
+
sessionKey: options.sessionKey,
|
|
278
|
+
url: options.url,
|
|
279
|
+
});
|
|
266
280
|
tabId = tab.tabId;
|
|
267
281
|
return { tabId, url: options.url };
|
|
268
282
|
}
|
|
269
|
-
const body = {
|
|
283
|
+
const body = {
|
|
284
|
+
userId: options.userId ?? DEFAULT_USER_ID,
|
|
285
|
+
sessionKey: options.sessionKey ?? DEFAULT_SESSION_KEY,
|
|
286
|
+
url: options.url,
|
|
287
|
+
};
|
|
270
288
|
if (options.waitUntil)
|
|
271
289
|
body.waitUntil = options.waitUntil;
|
|
272
290
|
if (options.timeoutMs)
|
|
@@ -279,7 +297,9 @@ export async function navigate(options) {
|
|
|
279
297
|
* Refs returned here can be used with `click`/`type`/`scroll`.
|
|
280
298
|
*/
|
|
281
299
|
export async function snapshot(options) {
|
|
282
|
-
|
|
300
|
+
const userId = options.userId ?? DEFAULT_USER_ID;
|
|
301
|
+
const qs = `?userId=${encodeURIComponent(userId)}`;
|
|
302
|
+
return await request(`/tabs/${encodeURIComponent(options.tabId)}/snapshot${qs}`);
|
|
283
303
|
}
|
|
284
304
|
/**
|
|
285
305
|
* Extract the readable content of the current page (Readability-style).
|
|
@@ -292,32 +312,45 @@ export async function extract(options) {
|
|
|
292
312
|
if (!options.url) {
|
|
293
313
|
throw new Error("extract() requires either tabId or url");
|
|
294
314
|
}
|
|
295
|
-
const tab = await createTab({
|
|
315
|
+
const tab = await createTab({
|
|
316
|
+
userId: options.userId,
|
|
317
|
+
sessionKey: options.sessionKey,
|
|
318
|
+
url: options.url,
|
|
319
|
+
});
|
|
296
320
|
tabId = tab.tabId;
|
|
297
321
|
// Wait for the navigation to settle before extracting.
|
|
298
322
|
await request(`/tabs/${encodeURIComponent(tabId)}/wait`, {
|
|
299
323
|
method: "POST",
|
|
300
|
-
body: { event: "load" },
|
|
324
|
+
body: { userId: options.userId ?? DEFAULT_USER_ID, event: "load" },
|
|
301
325
|
}).catch(() => { });
|
|
302
326
|
}
|
|
303
327
|
else if (options.url) {
|
|
304
|
-
await navigate({
|
|
328
|
+
await navigate({
|
|
329
|
+
tabId,
|
|
330
|
+
url: options.url,
|
|
331
|
+
userId: options.userId,
|
|
332
|
+
sessionKey: options.sessionKey,
|
|
333
|
+
});
|
|
305
334
|
}
|
|
306
335
|
const res = await request(`/tabs/${encodeURIComponent(tabId)}/extract`, {
|
|
307
336
|
method: "POST",
|
|
308
|
-
body: {
|
|
337
|
+
body: {
|
|
338
|
+
userId: options.userId ?? DEFAULT_USER_ID,
|
|
339
|
+
sessionKey: options.sessionKey ?? DEFAULT_SESSION_KEY,
|
|
340
|
+
mode: options.mode ?? "readability",
|
|
341
|
+
},
|
|
309
342
|
});
|
|
310
343
|
return res;
|
|
311
344
|
}
|
|
312
345
|
/** Capture a screenshot of the given tab as a base64-encoded PNG. */
|
|
313
346
|
export async function screenshot(options) {
|
|
314
347
|
const query = new URLSearchParams();
|
|
348
|
+
query.set("userId", options.userId ?? DEFAULT_USER_ID);
|
|
315
349
|
if (options.fullPage)
|
|
316
350
|
query.set("fullPage", "1");
|
|
317
351
|
if (options.clip)
|
|
318
352
|
query.set("clip", JSON.stringify(options.clip));
|
|
319
|
-
const
|
|
320
|
-
const res = await request(`/tabs/${encodeURIComponent(options.tabId)}/screenshot${qs ? `?${qs}` : ""}`);
|
|
353
|
+
const res = await request(`/tabs/${encodeURIComponent(options.tabId)}/screenshot?${query.toString()}`);
|
|
321
354
|
return {
|
|
322
355
|
tabId: options.tabId,
|
|
323
356
|
mimeType: res.mimeType ?? "image/png",
|
|
@@ -336,14 +369,14 @@ export async function search(options) {
|
|
|
336
369
|
: engine === "bing"
|
|
337
370
|
? `https://www.bing.com/search?q=${encodeURIComponent(options.query)}`
|
|
338
371
|
: `https://duckduckgo.com/?q=${encodeURIComponent(options.query)}`;
|
|
339
|
-
return await extract({ url, userId: options.userId });
|
|
372
|
+
return await extract({ url, userId: options.userId, sessionKey: options.sessionKey });
|
|
340
373
|
}
|
|
341
374
|
/** Click an element by ref (from `snapshot`) or CSS selector. */
|
|
342
375
|
export async function click(options) {
|
|
343
376
|
if (!options.ref && !options.selector) {
|
|
344
377
|
throw new Error("click() requires `ref` or `selector`");
|
|
345
378
|
}
|
|
346
|
-
const body = {};
|
|
379
|
+
const body = { userId: options.userId ?? DEFAULT_USER_ID };
|
|
347
380
|
if (options.ref)
|
|
348
381
|
body.ref = options.ref;
|
|
349
382
|
if (options.selector)
|
|
@@ -358,7 +391,10 @@ export async function click(options) {
|
|
|
358
391
|
}
|
|
359
392
|
/** Type text into a focused element (or one targeted via ref/selector). */
|
|
360
393
|
export async function type(options) {
|
|
361
|
-
const body = {
|
|
394
|
+
const body = {
|
|
395
|
+
userId: options.userId ?? DEFAULT_USER_ID,
|
|
396
|
+
text: options.text,
|
|
397
|
+
};
|
|
362
398
|
if (options.ref)
|
|
363
399
|
body.ref = options.ref;
|
|
364
400
|
if (options.selector)
|
|
@@ -375,7 +411,10 @@ export async function type(options) {
|
|
|
375
411
|
}
|
|
376
412
|
/** Scroll the page or a specific element by ref. */
|
|
377
413
|
export async function scroll(options) {
|
|
378
|
-
const body = {
|
|
414
|
+
const body = {
|
|
415
|
+
userId: options.userId ?? DEFAULT_USER_ID,
|
|
416
|
+
direction: options.direction,
|
|
417
|
+
};
|
|
379
418
|
if (options.ref)
|
|
380
419
|
body.ref = options.ref;
|
|
381
420
|
if (options.pixels)
|
|
@@ -388,7 +427,9 @@ export async function scroll(options) {
|
|
|
388
427
|
}
|
|
389
428
|
/** Close a single tab. The underlying browser context is kept warm. */
|
|
390
429
|
export async function closeTab(options) {
|
|
391
|
-
|
|
430
|
+
const userId = options.userId ?? DEFAULT_USER_ID;
|
|
431
|
+
const qs = `?userId=${encodeURIComponent(userId)}`;
|
|
432
|
+
await request(`/tabs/${encodeURIComponent(options.tabId)}${qs}`, { method: "DELETE" });
|
|
392
433
|
return { tabId: options.tabId };
|
|
393
434
|
}
|
|
394
435
|
/** List all open tabs for a user. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phi-code-admin/browser",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Phi-code browser automation API: lazy-start the bundled Camoufox + camofox-browser server and expose 10 high-level tools (navigate, extract, screenshot, click, type, scroll, snapshot, search, close_tab, list_tabs) as plain ES module functions. Zero external dependencies at runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|