@anweat/dsh-browser 0.1.4 → 0.1.6

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.
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Bounded, auditable Playwright recipes for model-generated browser flows.
3
+ * Recipes deliberately expose named operations instead of arbitrary JavaScript.
4
+ * @module dsh-browser/automation
5
+ */
6
+ const READ_ONLY_ACTIONS = new Set(['wait', 'extract', 'assert', 'screenshot']);
7
+ function finite(value, fallback, min, max, label) {
8
+ const resolved = value ?? fallback;
9
+ if (!Number.isFinite(resolved) || resolved < min || resolved > max)
10
+ throw new Error(label + ' must be between ' + min + ' and ' + max);
11
+ return resolved;
12
+ }
13
+ function selector(value) {
14
+ if (!value || value.length > 500)
15
+ throw new Error('selector must contain 1 to 500 characters');
16
+ return value;
17
+ }
18
+ function shortText(value, label, max = 20_000) {
19
+ if (value === undefined || value.length === 0 || value.length > max)
20
+ throw new Error(label + ' must contain 1 to ' + max + ' characters');
21
+ return value;
22
+ }
23
+ export function validateRecipe(steps) {
24
+ if (steps.length < 1 || steps.length > 25)
25
+ throw new Error('recipe must contain between 1 and 25 steps');
26
+ for (const step of steps) {
27
+ switch (step.type) {
28
+ case 'wait': {
29
+ finite(step.timeoutMs, 15_000, 0, 30_000, 'wait timeoutMs');
30
+ if (step.condition === 'selector')
31
+ selector(step.value);
32
+ else if (step.condition === 'text')
33
+ shortText(step.value, 'wait text', 2_000);
34
+ else if (step.condition === 'time')
35
+ finite(step.waitMs ?? Number(step.value ?? 0), 0, 0, 10_000, 'wait waitMs');
36
+ break;
37
+ }
38
+ case 'click':
39
+ selector(step.selector);
40
+ finite(step.timeoutMs, 15_000, 1, 30_000, 'click timeoutMs');
41
+ break;
42
+ case 'fill':
43
+ case 'type':
44
+ selector(step.selector);
45
+ shortText(step.value, step.type + ' value');
46
+ finite(step.timeoutMs, 15_000, 1, 30_000, step.type + ' timeoutMs');
47
+ break;
48
+ case 'press':
49
+ shortText(step.key, 'key', 100);
50
+ if (step.selector !== undefined)
51
+ selector(step.selector);
52
+ break;
53
+ case 'select':
54
+ selector(step.selector);
55
+ shortText(step.value, 'select value', 2_000);
56
+ break;
57
+ case 'check':
58
+ case 'hover':
59
+ selector(step.selector);
60
+ break;
61
+ case 'scroll':
62
+ finite(step.deltaY, 2_000, -20_000, 20_000, 'scroll deltaY');
63
+ finite(step.waitMs, 400, 0, 5_000, 'scroll waitMs');
64
+ break;
65
+ case 'extract':
66
+ if (step.selector !== undefined)
67
+ selector(step.selector);
68
+ finite(step.limit, 100, 1, 500, 'extract limit');
69
+ if (step.mode === 'attribute')
70
+ shortText(step.attribute, 'attribute', 100);
71
+ break;
72
+ case 'assert':
73
+ if (step.selector === undefined && step.text === undefined)
74
+ throw new Error('assert requires selector or text');
75
+ if (step.selector !== undefined)
76
+ selector(step.selector);
77
+ if (step.text !== undefined)
78
+ shortText(step.text, 'assert text', 2_000);
79
+ finite(step.timeoutMs, 15_000, 1, 30_000, 'assert timeoutMs');
80
+ break;
81
+ case 'screenshot':
82
+ break;
83
+ default:
84
+ throw new Error('unsupported recipe step');
85
+ }
86
+ }
87
+ }
88
+ export function recipeNeedsApproval(steps) {
89
+ return steps.some(step => !READ_ONLY_ACTIONS.has(step.type));
90
+ }
91
+ function cap(value, max = 50_000) {
92
+ return value.length <= max ? value : value.slice(0, max) + '\n…(truncated)';
93
+ }
94
+ export async function runRecipe(page, steps, captureScreenshot, signal) {
95
+ validateRecipe(steps);
96
+ const results = [];
97
+ for (let index = 0; index < steps.length; index += 1) {
98
+ signal?.throwIfAborted();
99
+ const step = steps[index];
100
+ let value;
101
+ switch (step.type) {
102
+ case 'wait': {
103
+ const timeout = finite(step.timeoutMs, 15_000, 0, 30_000, 'wait timeoutMs');
104
+ if (step.condition === 'selector')
105
+ await page.locator(selector(step.value)).first().waitFor({ state: 'visible', timeout });
106
+ else if (step.condition === 'text')
107
+ await page.getByText(shortText(step.value, 'wait text', 2_000), { exact: false }).first().waitFor({ state: 'visible', timeout });
108
+ else if (step.condition === 'load')
109
+ await page.waitForLoadState('networkidle', { timeout });
110
+ else
111
+ await page.waitForTimeout(finite(step.waitMs ?? Number(step.value ?? 0), 0, 0, 10_000, 'wait waitMs'));
112
+ break;
113
+ }
114
+ case 'click':
115
+ await page.locator(selector(step.selector)).first().click({ timeout: step.timeoutMs ?? 15_000 });
116
+ break;
117
+ case 'fill':
118
+ await page.locator(selector(step.selector)).first().fill(step.value, { timeout: step.timeoutMs ?? 15_000 });
119
+ break;
120
+ case 'type':
121
+ await page.locator(selector(step.selector)).first().pressSequentially(step.value, { timeout: step.timeoutMs ?? 15_000 });
122
+ break;
123
+ case 'press':
124
+ if (step.selector)
125
+ await page.locator(selector(step.selector)).first().press(step.key);
126
+ else
127
+ await page.keyboard.press(step.key);
128
+ break;
129
+ case 'select':
130
+ await page.locator(selector(step.selector)).first().selectOption(step.value);
131
+ break;
132
+ case 'check': {
133
+ const target = page.locator(selector(step.selector)).first();
134
+ if (step.checked === false)
135
+ await target.uncheck();
136
+ else
137
+ await target.check();
138
+ break;
139
+ }
140
+ case 'hover':
141
+ await page.locator(selector(step.selector)).first().hover();
142
+ break;
143
+ case 'scroll':
144
+ await page.mouse.wheel(0, step.deltaY ?? 2_000);
145
+ await page.waitForTimeout(step.waitMs ?? 400);
146
+ break;
147
+ case 'extract': {
148
+ const target = page.locator(step.selector ?? 'body').first();
149
+ const mode = step.mode ?? 'text';
150
+ if (mode === 'text')
151
+ value = cap(await target.innerText());
152
+ else if (mode === 'html')
153
+ value = cap(await target.innerHTML());
154
+ else if (mode === 'attribute')
155
+ value = String(await target.getAttribute(shortText(step.attribute, 'attribute', 100)) ?? '');
156
+ else {
157
+ const rows = await target.locator('a[href]').evaluateAll((anchors, limit) => anchors.slice(0, limit).map(anchor => ({
158
+ text: String(anchor.textContent ?? '').trim(),
159
+ url: String(anchor.href ?? ''),
160
+ })), step.limit ?? 100);
161
+ value = cap(JSON.stringify(rows));
162
+ }
163
+ break;
164
+ }
165
+ case 'assert': {
166
+ const timeout = step.timeoutMs ?? 15_000;
167
+ if (step.selector)
168
+ await page.locator(selector(step.selector)).first().waitFor({ state: 'visible', timeout });
169
+ if (step.text)
170
+ await page.getByText(step.text, { exact: false }).first().waitFor({ state: 'visible', timeout });
171
+ break;
172
+ }
173
+ case 'screenshot':
174
+ value = await captureScreenshot();
175
+ break;
176
+ }
177
+ results.push({ step: index + 1, action: step.type, ok: true, ...value !== undefined ? { value } : {} });
178
+ }
179
+ return results;
180
+ }
181
+ //# sourceMappingURL=automation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation.js","sourceRoot":"","sources":["../src/automation.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,8 @@
20
20
  */
21
21
  import { type CliResult } from './deps.ts';
22
22
  import type { ResolvedConfig } from './config.ts';
23
+ import { type BrowserRecipeStep, type RecipeStepResult } from './automation.ts';
24
+ import { type UserscriptValidation } from './scripts.ts';
23
25
  export interface RenderRule {
24
26
  hostname: string;
25
27
  contentSelectors: string[];
@@ -56,27 +58,46 @@ export interface InteractiveState {
56
58
  text: string;
57
59
  screenshotPath?: string;
58
60
  }
61
+ export interface RecipeRunResult extends InteractiveState {
62
+ steps: RecipeStepResult[];
63
+ }
64
+ export interface ScriptRunResult {
65
+ url: string;
66
+ name: string;
67
+ sha256: string;
68
+ capabilities: string[];
69
+ resultJson: string;
70
+ truncated: boolean;
71
+ }
59
72
  export declare class BrowserService {
60
73
  private readonly config;
61
74
  private browser;
62
75
  private launching?;
63
76
  private activeContext;
64
77
  private activePage;
78
+ private activeProfile?;
79
+ private activeRulePack?;
80
+ private readonly authProfiles;
65
81
  constructor(config: ResolvedConfig);
66
82
  available(): boolean;
67
83
  private ensure;
68
84
  /** Run `playwright install chromium` from the bundled playwright CLI. */
69
85
  installChromium(): Promise<CliResult>;
70
86
  private transientContext;
87
+ private persistAndClose;
71
88
  render(url: string, rules: readonly RenderRule[], opts?: {
72
89
  signal?: AbortSignal;
73
90
  maxChars?: number;
74
91
  waitMs?: number;
92
+ authProfile?: string;
93
+ rulePack?: string;
75
94
  }): Promise<RenderResult>;
76
95
  snapshot(url: string, rules: readonly RenderRule[], opts: {
77
96
  signal?: AbortSignal;
78
97
  outDir: string;
79
98
  maxChars?: number;
99
+ authProfile?: string;
100
+ rulePack?: string;
80
101
  }): Promise<SnapshotResult>;
81
102
  searchResults(url: string, spec: PlatformSpec, opts?: {
82
103
  signal?: AbortSignal;
@@ -88,17 +109,42 @@ export declare class BrowserService {
88
109
  domain: string;
89
110
  path: string;
90
111
  }[];
112
+ authProfile?: string;
113
+ rulePack?: string;
91
114
  }): Promise<SearchItem[]>;
92
115
  opencliAvailable(): boolean;
93
116
  opencli(args: string[], opts?: {
94
117
  timeoutMs?: number;
95
118
  signal?: AbortSignal;
96
119
  }): Promise<CliResult>;
120
+ opencliDoctor(signal?: AbortSignal): Promise<CliResult>;
121
+ scriptCatalog(): {
122
+ id: string;
123
+ name: string;
124
+ description: string;
125
+ sha256: string;
126
+ }[];
127
+ validateUserscript(source: string, targetUrl?: string): UserscriptValidation;
128
+ private runScript;
129
+ runBuiltinScript(url: string, id: string, opts?: {
130
+ signal?: AbortSignal;
131
+ timeoutMs?: number;
132
+ authProfile?: string;
133
+ rulePack?: string;
134
+ }): Promise<ScriptRunResult>;
135
+ runUserscript(url: string, source: string, opts?: {
136
+ signal?: AbortSignal;
137
+ timeoutMs?: number;
138
+ authProfile?: string;
139
+ rulePack?: string;
140
+ }): Promise<ScriptRunResult>;
97
141
  private ensureActivePage;
98
142
  private captureScreenshot;
99
143
  private readState;
100
144
  open(url: string, opts?: {
101
145
  waitMs?: number;
146
+ authProfile?: string;
147
+ rulePack?: string;
102
148
  }): Promise<InteractiveState>;
103
149
  click(selector: string, opts?: {
104
150
  timeoutMs?: number;
@@ -114,6 +160,13 @@ export declare class BrowserService {
114
160
  screenshot(): Promise<{
115
161
  path: string;
116
162
  }>;
163
+ recipe(steps: readonly BrowserRecipeStep[], opts?: {
164
+ url?: string;
165
+ waitMs?: number;
166
+ authProfile?: string;
167
+ rulePack?: string;
168
+ signal?: AbortSignal;
169
+ }): Promise<RecipeRunResult>;
117
170
  closePage(): Promise<void>;
118
171
  status(): Promise<{
119
172
  enabled: boolean;
@@ -121,7 +174,17 @@ export declare class BrowserService {
121
174
  headless: boolean;
122
175
  opencliEnabled: boolean;
123
176
  chromiumInstalled: boolean;
177
+ authProfiles: {
178
+ id: string;
179
+ allowedDomains: string[];
180
+ persistState: boolean;
181
+ }[];
182
+ rulePacks: string[];
183
+ builtinScripts: string[];
184
+ externalUserscriptsRequireApproval: true;
185
+ mutatingRecipesRequireApproval: true;
124
186
  activeUrl?: string;
187
+ activeAuthProfile?: string;
125
188
  }>;
126
189
  close(): Promise<void>;
127
190
  }