@anweat/dsh-browser 0.1.11 → 0.1.13-alpha.1

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/cordis.patch.yml CHANGED
@@ -1,26 +1,26 @@
1
- # dsh-browser bundle patch — installs the browser runtime as one more row over
2
- # the active profile. Install with:
3
- # dsh plugin --profile <name> add @anweat/dsh-browser
4
- # then boot the profile (the web profile has HMR disabled, so a restart applies it).
5
- #
6
- # Login state: prefer named `authProfiles` with explicit `allowedDomains` (see
7
- # README). `storageStatePath` remains as a legacy global fallback.
8
- - insert:
9
- - id: browser
10
- name: '@anweat/dsh-browser'
11
- config:
12
- automationMode: standard
13
- browserRuntime: playwright
14
- channel: chromium
15
- headless: true
16
- opencliEnabled: true
17
- usagePolicy:
18
- minDelayMs: 750
19
- maxConcurrency: 2
20
- burst: 3
21
- maxPagesPerRun: 20
22
- maxDepth: 2
23
- retryLimit: 2
24
- backoffBaseMs: 1000
25
- cooldownMs: 30000
26
- verbose: false
1
+ # dsh-browser bundle patch — installs the browser runtime as one more row over
2
+ # the active profile. Install with:
3
+ # dsh plugin --profile <name> add @anweat/dsh-browser
4
+ # then boot the profile (the web profile has HMR disabled, so a restart applies it).
5
+ #
6
+ # Login state: prefer named `authProfiles` with explicit `allowedDomains` (see
7
+ # README). `storageStatePath` remains as a legacy global fallback.
8
+ - insert:
9
+ - id: browser
10
+ name: '@anweat/dsh-browser'
11
+ config:
12
+ automationMode: standard
13
+ browserRuntime: playwright
14
+ channel: chromium
15
+ headless: true
16
+ opencliEnabled: true
17
+ usagePolicy:
18
+ minDelayMs: 750
19
+ maxConcurrency: 2
20
+ burst: 3
21
+ maxPagesPerRun: 20
22
+ maxDepth: 2
23
+ retryLimit: 2
24
+ backoffBaseMs: 1000
25
+ cooldownMs: 30000
26
+ verbose: false
@@ -2,7 +2,7 @@
2
2
  import { recipeNeedsApproval } from "./automation.js";
3
3
  import { validateUserscript } from "./scripts.js";
4
4
  import { isBrowserToolExposed } from "./freedom.js";
5
- const DIRECT_INTERACTIONS = new Set(['browser_click', 'browser_type', 'browser_scroll']);
5
+ const DIRECT_INTERACTIONS = new Set(['browser_click', 'browser_type', 'browser_hover', 'browser_scroll']);
6
6
  const WEB_LOCAL_MUTATIONS = new Set(['web_cache_clear']);
7
7
  export function browserPolicyDecision(name, args, mode = 'standard') {
8
8
  if (!isBrowserToolExposed(name, mode) && name.startsWith('browser_')) {
@@ -21,6 +21,30 @@ export function browserPolicyDecision(name, args, mode = 'standard') {
21
21
  return { kind: 'allow' };
22
22
  return { kind: 'ask', reason: 'Install Playwright Chromium into the shared browser cache' };
23
23
  }
24
+ if (name === 'browser_set_files') {
25
+ const files = Array.isArray(args?.files)
26
+ ? args.files.filter(value => typeof value === 'string')
27
+ : [];
28
+ if (files.length === 0)
29
+ return { kind: 'deny', reason: 'browser_set_files requires one or more absolute file paths' };
30
+ if (mode === 'read-only')
31
+ return { kind: 'deny', reason: `Local file upload is disabled by automationMode=${mode}` };
32
+ if (mode === 'unrestricted')
33
+ return { kind: 'allow' };
34
+ return { kind: 'ask', reason: 'Read local files and expose them to the current website upload control: ' + files.slice(0, 5).join(', ') };
35
+ }
36
+ if (name === 'browser_evaluate') {
37
+ const expression = args?.expression;
38
+ if (typeof expression !== 'string' || !expression.trim())
39
+ return { kind: 'deny', reason: 'browser_evaluate requires a JavaScript expression' };
40
+ if (expression.length > 20_000)
41
+ return { kind: 'deny', reason: 'browser_evaluate expression exceeds 20,000 characters' };
42
+ if (mode === 'read-only')
43
+ return { kind: 'deny', reason: `Page JavaScript execution is disabled by automationMode=${mode}` };
44
+ if (mode === 'unrestricted')
45
+ return { kind: 'allow' };
46
+ return { kind: 'ask', reason: 'Run JavaScript with the current page origin and login state; it may access page storage, non-HttpOnly cookies, and browser-permitted network APIs' };
47
+ }
24
48
  if (name === 'browser_userscript_run') {
25
49
  const input = args;
26
50
  if (typeof input.source !== 'string' || typeof input.url !== 'string')
@@ -1 +1 @@
1
- {"version":3,"file":"approval-policy.js","sourceRoot":"","sources":["../src/approval-policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approval-policy.js","sourceRoot":"","sources":["../src/approval-policy.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,15 @@
1
1
  /** Loopback-only Host RPC for the automation asset review UI. */
2
2
  import { executeAutomationAsset } from "./automation-execution.js";
3
- const CHANNEL = '/dsh-browser-assets';
3
+ const CHANNEL = '/api';
4
+ const PREFIX = 'dsh-browser-assets';
5
+ const ENDPOINTS = ['snapshot', 'get', 'save', 'summarize', 'dismiss', 'validate', 'test', 'status'];
6
+ function failure(rpcId, message) {
7
+ return Response.json({
8
+ type: 'server-response',
9
+ rpcId,
10
+ result: { ok: false, error: { code: 'gateway/bad-request', message, details: {} } },
11
+ });
12
+ }
4
13
  function record(payload) {
5
14
  if (!payload || typeof payload !== 'object' || Array.isArray(payload))
6
15
  throw new Error('request payload must be an object');
@@ -17,7 +26,7 @@ function stringField(payload, name) {
17
26
  export function registerAutomationAssetRpc(ctx, store, service) {
18
27
  ctx.inject(['connection'], (connectionCtx) => {
19
28
  const connection = connectionCtx.connection;
20
- const dispose = connection.rpc.handle(CHANNEL, async (endpoint, rawPayload) => {
29
+ const handler = async (endpoint, rawPayload) => {
21
30
  try {
22
31
  const payload = record(rawPayload);
23
32
  let value;
@@ -49,15 +58,47 @@ export function registerAutomationAssetRpc(ctx, store, service) {
49
58
  case 'status':
50
59
  value = store.setStatus(stringField(payload, 'id'), stringField(payload, 'status'));
51
60
  break;
52
- default: return { ok: false, error: { code: 'not-found', message: `unknown automation asset endpoint: ${endpoint}` } };
61
+ default: return { ok: false, error: { code: 'not-found', message: `unknown automation asset endpoint: ${endpoint}`, details: {} } };
53
62
  }
54
63
  return { ok: true, value };
55
64
  }
56
65
  catch (error) {
57
- return { ok: false, error: { code: 'bad-request', message: String(error instanceof Error ? error.message : error).slice(0, 500) } };
66
+ return { ok: false, error: { code: 'bad-request', message: String(error instanceof Error ? error.message : error).slice(0, 500), details: {} } };
58
67
  }
59
- }, { authority: 'loopback' });
60
- connectionCtx.effect(() => dispose, 'dsh-browser: automation asset RPC');
68
+ };
69
+ for (const endpoint of ENDPOINTS) {
70
+ const method = `${PREFIX}/${endpoint}`;
71
+ connectionCtx.effect(() => connection.fetch.register({
72
+ path: `${CHANNEL}/${method}`,
73
+ methods: ['POST'],
74
+ requestBody: 'buffered',
75
+ fetch: async (request) => {
76
+ let body;
77
+ try {
78
+ body = await request.json();
79
+ }
80
+ catch {
81
+ return new Response('body is not JSON', { status: 400 });
82
+ }
83
+ const rpcId = typeof body === 'object' && body !== null
84
+ && typeof body.rpcId === 'string'
85
+ ? body.rpcId
86
+ : 'invalid-request';
87
+ if (typeof body !== 'object' || body === null
88
+ || body.type !== 'client-request'
89
+ || body.method !== method) {
90
+ return failure(rpcId, 'invalid RPC request');
91
+ }
92
+ try {
93
+ const result = await handler(endpoint, body.payload, request.signal);
94
+ return Response.json({ type: 'server-response', rpcId, result });
95
+ }
96
+ catch (error) {
97
+ return failure(rpcId, String(error instanceof Error ? error.message : error).slice(0, 500));
98
+ }
99
+ },
100
+ }), `dsh-browser: ${method} RPC route`);
101
+ }
61
102
  });
62
103
  }
63
104
  //# sourceMappingURL=automation-assets-rpc.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"automation-assets-rpc.js","sourceRoot":"","sources":["../src/automation-assets-rpc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"automation-assets-rpc.js","sourceRoot":"","sources":["../src/automation-assets-rpc.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAMjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAElE,MAAM,OAAO,GAAG,MAAM,CAAA;AACtB,MAAM,MAAM,GAAG,oBAAoB,CAAA;AACnC,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAA;AAE5G,SAAS,OAAO,CAAC,KAAa,EAAE,OAAe;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,iBAAiB;QACvB,KAAK;QACL,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE;KACpF,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,OAAgB;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAC3H,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC1G,OAAO,OAAkC,CAAA;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,OAAgC,EAAE,IAAY;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6BAA6B,CAAC,CAAA;IAC9H,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,GAAY,EAAE,KAA2B,EAAE,OAAuB;IAC3G,GAAG,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE;QAC3C,MAAM,UAAU,GAAI,aAWlB,CAAC,UAAU,CAAA;QACb,MAAM,OAAO,GAAyB,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE;YACnE,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;gBAClC,IAAI,KAAc,CAAA;gBAClB,QAAQ,QAAQ,EAAE,CAAC;oBACjB,KAAK,UAAU;wBAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;wBAAC,MAAK;oBAChD,KAAK,KAAK;wBAAE,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC;wBAAC,MAAK;oBACxE,KAAK,MAAM;wBAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAA0E,CAAC,CAAC;wBAAC,MAAK;oBAC/H,KAAK,WAAW;wBAAE,KAAK,GAAG,KAAK,CAAC,kBAAkB,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;wBAAC,MAAK;oBACrF,KAAK,SAAS;wBAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;wBAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;wBAAC,MAAK;oBACnG,KAAK,UAAU;wBAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;wBAAC,MAAK;oBAC1E,KAAK,MAAM,CAAC,CAAC,CAAC;wBACZ,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;wBAC7I,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;wBACpB,MAAK;oBACP,CAAC;oBACD,KAAK,QAAQ;wBAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,QAAQ,CAA0B,CAAC,CAAC;wBAAC,MAAK;oBAClI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,sCAAsC,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAAA;gBAC9I,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAsB,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAAA;YAC3J,CAAC;QACH,CAAC,CAAA;QACD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAA;YACtC,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACnD,IAAI,EAAE,GAAG,OAAO,IAAI,MAAM,EAAE;gBAC5B,OAAO,EAAE,CAAC,MAAM,CAAC;gBACjB,WAAW,EAAE,UAAU;gBACvB,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;oBACvB,IAAI,IAAa,CAAA;oBACjB,IAAI,CAAC;wBACH,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAA;oBAC7B,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO,IAAI,QAAQ,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;oBAC1D,CAAC;oBACD,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;2BAClD,OAAQ,IAA4B,CAAC,KAAK,KAAK,QAAQ;wBAC1D,CAAC,CAAE,IAA0B,CAAC,KAAK;wBACnC,CAAC,CAAC,iBAAiB,CAAA;oBACrB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;2BACvC,IAA2B,CAAC,IAAI,KAAK,gBAAgB;2BACrD,IAA6B,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;wBACtD,OAAO,OAAO,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAA;oBAC9C,CAAC;oBACD,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAG,IAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;wBAC/F,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;oBAClE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;oBAC7F,CAAC;gBACH,CAAC;aACF,CAAC,EAAE,gBAAgB,MAAM,YAAY,CAAC,CAAA;QACzC,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -9,7 +9,7 @@
9
9
  * web-search-pro's former PlaywrightManager (rules-aware page extraction and
10
10
  * platform search-page list extraction run in the page itself).
11
11
  * - opencli(...) runs the bundled @jackwener/opencli (no global CLI).
12
- * - The interactive surface (open/click/type/scroll/read/screenshot/closePage)
12
+ * - The interactive surface (open/click/type/hover/setFiles/evaluate/scroll/read/screenshot/closePage)
13
13
  * drives ONE persistent context+page, giving the model multi-step browsing.
14
14
  *
15
15
  * The page-side extractors are raw JS strings, not closures: tsx/esbuild would
@@ -72,6 +72,16 @@ export interface ScriptRunResult {
72
72
  resultJson: string;
73
73
  truncated: boolean;
74
74
  }
75
+ export interface EvaluateResult {
76
+ url: string;
77
+ resultJson: string;
78
+ truncated: boolean;
79
+ capabilities: string[];
80
+ warnings: string[];
81
+ }
82
+ export interface FileUploadResult extends InteractiveState {
83
+ files: string[];
84
+ }
75
85
  export interface CrawlPage {
76
86
  url: string;
77
87
  title: string;
@@ -110,6 +120,8 @@ export interface BrowserStatus {
110
120
  directInteractionPolicy: 'deny' | 'ask' | 'allow';
111
121
  mutatingRecipePolicy: 'deny' | 'ask' | 'allow';
112
122
  externalUserscriptPolicy: 'deny' | 'ask' | 'allow';
123
+ pageEvaluatePolicy: 'deny' | 'ask' | 'allow';
124
+ fileUploadPolicy: 'deny' | 'ask' | 'allow';
113
125
  opencliRunPolicy: 'deny' | 'ask' | 'allow';
114
126
  chromiumInstalled: boolean;
115
127
  chromiumExecutablePath?: string;
@@ -225,6 +237,16 @@ export declare class BrowserService {
225
237
  type(selector: string, text: string, opts?: {
226
238
  timeoutMs?: number;
227
239
  }): Promise<InteractiveState>;
240
+ hover(selector: string, opts?: {
241
+ timeoutMs?: number;
242
+ waitMs?: number;
243
+ }): Promise<InteractiveState>;
244
+ setFiles(selector: string, files: readonly string[], opts?: {
245
+ timeoutMs?: number;
246
+ }): Promise<FileUploadResult>;
247
+ evaluate(expression: string, opts?: {
248
+ timeoutMs?: number;
249
+ }): Promise<EvaluateResult>;
228
250
  scroll(deltaY: number, opts?: {
229
251
  waitMs?: number;
230
252
  }): Promise<InteractiveState>;
@@ -9,7 +9,7 @@
9
9
  * web-search-pro's former PlaywrightManager (rules-aware page extraction and
10
10
  * platform search-page list extraction run in the page itself).
11
11
  * - opencli(...) runs the bundled @jackwener/opencli (no global CLI).
12
- * - The interactive surface (open/click/type/scroll/read/screenshot/closePage)
12
+ * - The interactive surface (open/click/type/hover/setFiles/evaluate/scroll/read/screenshot/closePage)
13
13
  * drives ONE persistent context+page, giving the model multi-step browsing.
14
14
  *
15
15
  * The page-side extractors are raw JS strings, not closures: tsx/esbuild would
@@ -30,66 +30,66 @@ import { configuredBrowserTools } from "./freedom.js";
30
30
  import { filterOpencliCatalog, parseOpencliCatalog } from "./opencli-catalog.js";
31
31
  import { UsageGovernor } from "./usage-policy.js";
32
32
  /** Rules-aware content extractor (runs in the page). */
33
- const EXTRACTOR_FN = `(ruleList) => {
34
- const doc = document
35
- const title = doc.title ? doc.title.trim() : ''
36
- let host = ''
37
- try { host = location.hostname } catch (e) {}
38
- const norm = (h) => { const x = h.toLowerCase(); return x.startsWith('www.') ? x.slice(4) : x }
39
- let rule = null
40
- for (const r of ruleList) {
41
- const rh = norm(r.hostname)
42
- if (host === rh || host.endsWith('.' + rh)) rule = r
43
- }
44
- const pick = (selectors) => {
45
- for (const sel of selectors) {
46
- try {
47
- const el = doc.querySelector(sel)
48
- if (el && (el.textContent || '').trim().length > 40) return el
49
- } catch (e) {}
50
- }
51
- return null
52
- }
53
- const content = rule ? pick(rule.contentSelectors) : (pick(['article', 'main', '[role="main"]']) || doc.body)
54
- if (content && rule && rule.removeSelectors) {
55
- for (const sel of rule.removeSelectors) {
56
- try { content.querySelectorAll(sel).forEach((el) => el.remove()) } catch (e) {}
57
- }
58
- }
59
- const text = content ? (content.innerText || content.textContent || '') : ''
60
- return { title, text, html: doc.documentElement.outerHTML.slice(0, 2000000), usedRule: rule ? rule.hostname : null }
33
+ const EXTRACTOR_FN = `(ruleList) => {
34
+ const doc = document
35
+ const title = doc.title ? doc.title.trim() : ''
36
+ let host = ''
37
+ try { host = location.hostname } catch (e) {}
38
+ const norm = (h) => { const x = h.toLowerCase(); return x.startsWith('www.') ? x.slice(4) : x }
39
+ let rule = null
40
+ for (const r of ruleList) {
41
+ const rh = norm(r.hostname)
42
+ if (host === rh || host.endsWith('.' + rh)) rule = r
43
+ }
44
+ const pick = (selectors) => {
45
+ for (const sel of selectors) {
46
+ try {
47
+ const el = doc.querySelector(sel)
48
+ if (el && (el.textContent || '').trim().length > 40) return el
49
+ } catch (e) {}
50
+ }
51
+ return null
52
+ }
53
+ const content = rule ? pick(rule.contentSelectors) : (pick(['article', 'main', '[role="main"]']) || doc.body)
54
+ if (content && rule && rule.removeSelectors) {
55
+ for (const sel of rule.removeSelectors) {
56
+ try { content.querySelectorAll(sel).forEach((el) => el.remove()) } catch (e) {}
57
+ }
58
+ }
59
+ const text = content ? (content.innerText || content.textContent || '') : ''
60
+ return { title, text, html: doc.documentElement.outerHTML.slice(0, 2000000), usedRule: rule ? rule.hostname : null }
61
61
  }`;
62
62
  /** Platform search-page list extractor (runs in the page). */
63
- const LIST_EXTRACTOR = `(spec) => {
64
- const items = []
65
- const nodes = document.querySelectorAll(spec.item)
66
- for (let i = 0; i < nodes.length && items.length < 20; i++) {
67
- const el = nodes[i]
68
- const titleEl = spec.title ? el.querySelector(spec.title) : null
69
- const linkEl = spec.link ? el.querySelector(spec.link) : null
70
- const textEl = spec.text ? el.querySelector(spec.text) : null
71
- const title = (titleEl ? titleEl.textContent : el.textContent || '').trim().replace(/\\s+/g, ' ')
72
- let url = linkEl ? (linkEl.href || linkEl.getAttribute('href') || '') : ''
73
- if (url && url.startsWith('/')) url = location.origin + url
74
- if (!url && linkEl === null && titleEl) { const a = titleEl.closest ? titleEl.closest('a') : null; if (a) url = a.href }
75
- const snippet = textEl ? (textEl.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 300) : ''
76
- if (!url || !title || title.length < 2) continue
77
- items.push({ url, title, snippet })
78
- }
79
- return items
63
+ const LIST_EXTRACTOR = `(spec) => {
64
+ const items = []
65
+ const nodes = document.querySelectorAll(spec.item)
66
+ for (let i = 0; i < nodes.length && items.length < 20; i++) {
67
+ const el = nodes[i]
68
+ const titleEl = spec.title ? el.querySelector(spec.title) : null
69
+ const linkEl = spec.link ? el.querySelector(spec.link) : null
70
+ const textEl = spec.text ? el.querySelector(spec.text) : null
71
+ const title = (titleEl ? titleEl.textContent : el.textContent || '').trim().replace(/\\s+/g, ' ')
72
+ let url = linkEl ? (linkEl.href || linkEl.getAttribute('href') || '') : ''
73
+ if (url && url.startsWith('/')) url = location.origin + url
74
+ if (!url && linkEl === null && titleEl) { const a = titleEl.closest ? titleEl.closest('a') : null; if (a) url = a.href }
75
+ const snippet = textEl ? (textEl.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 300) : ''
76
+ if (!url || !title || title.length < 2) continue
77
+ items.push({ url, title, snippet })
78
+ }
79
+ return items
80
80
  }`;
81
- const CRAWL_EXTRACTOR = `(maxChars) => {
82
- const root = document.querySelector('article, main, [role="main"]') || document.body
83
- const text = ((root && (root.innerText || root.textContent)) || '').replace(/\\n{3,}/g, '\\n\\n').trim().slice(0, maxChars)
84
- const links = []
85
- for (const anchor of document.querySelectorAll('a[href]')) {
86
- try {
87
- const url = new URL(anchor.href, location.href)
88
- if ((url.protocol === 'http:' || url.protocol === 'https:') && !links.includes(url.href)) links.push(url.href)
89
- if (links.length >= 500) break
90
- } catch (e) {}
91
- }
92
- return { title: document.title || '', text, links }
81
+ const CRAWL_EXTRACTOR = `(maxChars) => {
82
+ const root = document.querySelector('article, main, [role="main"]') || document.body
83
+ const text = ((root && (root.innerText || root.textContent)) || '').replace(/\\n{3,}/g, '\\n\\n').trim().slice(0, maxChars)
84
+ const links = []
85
+ for (const anchor of document.querySelectorAll('a[href]')) {
86
+ try {
87
+ const url = new URL(anchor.href, location.href)
88
+ if ((url.protocol === 'http:' || url.protocol === 'https:') && !links.includes(url.href)) links.push(url.href)
89
+ if (links.length >= 500) break
90
+ } catch (e) {}
91
+ }
92
+ return { title: document.title || '', text, links }
93
93
  }`;
94
94
  function uid() {
95
95
  return crypto.randomUUID();
@@ -611,6 +611,69 @@ export class BrowserService {
611
611
  await page.fill(selector, text);
612
612
  return this.readState(page, false);
613
613
  }
614
+ async hover(selector, opts = {}) {
615
+ const page = await this.ensureActivePage();
616
+ const timeoutMs = opts.timeoutMs ?? 15_000;
617
+ const waitMs = Math.min(Math.max(opts.waitMs ?? 300, 0), timeoutMs);
618
+ await page.waitForSelector(selector, { timeout: timeoutMs });
619
+ await page.hover(selector);
620
+ await page.waitForTimeout(waitMs);
621
+ return this.readState(page, true);
622
+ }
623
+ async setFiles(selector, files, opts = {}) {
624
+ if (files.length === 0 || files.length > 20)
625
+ throw new Error('browser_set_files requires 1 to 20 files');
626
+ const resolved = files.map(file => {
627
+ if (!path.isAbsolute(file))
628
+ throw new Error('browser_set_files requires absolute file paths: ' + file);
629
+ const real = fs.realpathSync(file);
630
+ if (!fs.statSync(real).isFile())
631
+ throw new Error('browser_set_files path is not a file: ' + file);
632
+ return real;
633
+ });
634
+ const totalBytes = resolved.reduce((total, file) => total + fs.statSync(file).size, 0);
635
+ if (totalBytes > 512 * 1024 * 1024)
636
+ throw new Error('browser_set_files total upload size exceeds 512 MiB');
637
+ const page = await this.ensureActivePage();
638
+ await page.waitForSelector(selector, { timeout: opts.timeoutMs ?? 15_000 });
639
+ await page.setInputFiles(selector, resolved);
640
+ return { ...await this.readState(page, true), files: resolved.map(file => path.basename(file)) };
641
+ }
642
+ async evaluate(expression, opts = {}) {
643
+ const source = expression.trim();
644
+ if (!source)
645
+ throw new Error('browser_evaluate requires a JavaScript expression');
646
+ if (source.length > 20_000)
647
+ throw new Error('browser_evaluate expression exceeds 20,000 characters');
648
+ const page = await this.ensureActivePage();
649
+ const timeoutMs = Math.min(Math.max(opts.timeoutMs ?? 15_000, 1_000), 30_000);
650
+ let timer;
651
+ const timeout = new Promise((_resolve, reject) => {
652
+ timer = setTimeout(() => {
653
+ void this.closePage();
654
+ reject(new Error('browser_evaluate timed out after ' + timeoutMs + 'ms; the active page was closed'));
655
+ }, timeoutMs);
656
+ });
657
+ try {
658
+ const script = `(async () => {\nconst value = await (${source}\n);\nconst json = JSON.stringify(value);\nif (json === undefined) throw new Error('expression result is not JSON-serializable');\nreturn { resultJson: json.slice(0, 100000), truncated: json.length > 100000 };\n})()`;
659
+ const result = await Promise.race([page.evaluate(script), timeout]);
660
+ return {
661
+ url: page.url(),
662
+ resultJson: result.resultJson,
663
+ truncated: result.truncated,
664
+ capabilities: ['dom', 'page-javascript', 'page-network', 'page-storage'],
665
+ warnings: [
666
+ 'The expression runs with the current page origin and login state. It can mutate the page, access non-HttpOnly cookies and browser storage, and issue requests allowed by the browser.',
667
+ 'Use this capability according to the target site rules and applicable requirements. The caller/operator is responsible for that decision; dsh-browser only executes approved browser operations.',
668
+ 'The expression has no Node.js or direct host-filesystem access. Downloads are not persisted or returned by this tool.',
669
+ ],
670
+ };
671
+ }
672
+ finally {
673
+ if (timer)
674
+ clearTimeout(timer);
675
+ }
676
+ }
614
677
  async scroll(deltaY, opts = {}) {
615
678
  const page = await this.ensureActivePage();
616
679
  await page.mouse?.wheel(0, deltaY || 2000).catch(() => { });
@@ -711,6 +774,8 @@ export class BrowserService {
711
774
  directInteractionPolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'standard' ? 'ask' : 'allow',
712
775
  mutatingRecipePolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'standard' ? 'ask' : 'allow',
713
776
  externalUserscriptPolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'unrestricted' ? 'allow' : 'ask',
777
+ pageEvaluatePolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'unrestricted' ? 'allow' : 'ask',
778
+ fileUploadPolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'unrestricted' ? 'allow' : 'ask',
714
779
  opencliRunPolicy: !this.config.enabled || this.config.automationMode === 'read-only' ? 'deny' : this.config.automationMode === 'unrestricted' ? 'allow' : 'ask',
715
780
  chromiumInstalled,
716
781
  ...chromiumExecutablePath ? { chromiumExecutablePath } : {},