auspex 0.4.3 → 0.5.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.
Files changed (47) hide show
  1. package/dist/agent/agent.d.ts.map +1 -1
  2. package/dist/agent/agent.js +12 -0
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/loop.d.ts.map +1 -1
  5. package/dist/agent/loop.js +16 -2
  6. package/dist/agent/loop.js.map +1 -1
  7. package/dist/config/schema.d.ts +10 -4
  8. package/dist/config/schema.d.ts.map +1 -1
  9. package/dist/config/schema.js +2 -0
  10. package/dist/config/schema.js.map +1 -1
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/llm/client.d.ts +6 -1
  16. package/dist/llm/client.d.ts.map +1 -1
  17. package/dist/llm/client.js +2 -2
  18. package/dist/llm/client.js.map +1 -1
  19. package/dist/llm/prompt.d.ts +7 -2
  20. package/dist/llm/prompt.d.ts.map +1 -1
  21. package/dist/llm/prompt.js +31 -2
  22. package/dist/llm/prompt.js.map +1 -1
  23. package/dist/macro/build.d.ts +4 -0
  24. package/dist/macro/build.d.ts.map +1 -0
  25. package/dist/macro/build.js +23 -0
  26. package/dist/macro/build.js.map +1 -0
  27. package/dist/macro/index.d.ts +5 -0
  28. package/dist/macro/index.d.ts.map +1 -0
  29. package/dist/macro/index.js +5 -0
  30. package/dist/macro/index.js.map +1 -0
  31. package/dist/macro/replay.d.ts +26 -0
  32. package/dist/macro/replay.d.ts.map +1 -0
  33. package/dist/macro/replay.js +121 -0
  34. package/dist/macro/replay.js.map +1 -0
  35. package/dist/macro/schema.d.ts +440 -0
  36. package/dist/macro/schema.d.ts.map +1 -0
  37. package/dist/macro/schema.js +24 -0
  38. package/dist/macro/schema.js.map +1 -0
  39. package/dist/macro/serialize.d.ts +4 -0
  40. package/dist/macro/serialize.d.ts.map +1 -0
  41. package/dist/macro/serialize.js +20 -0
  42. package/dist/macro/serialize.js.map +1 -0
  43. package/dist/security/action-validator.d.ts +2 -2
  44. package/dist/types.d.ts +9 -0
  45. package/dist/types.d.ts.map +1 -1
  46. package/package.json +2 -1
  47. package/readme.md +55 -0
@@ -0,0 +1,26 @@
1
+ import type { LaunchOptions } from "playwright";
2
+ import type { Page } from "playwright-core";
3
+ import type { CookieParam, ProxyConfig } from "../types.js";
4
+ import type { AuspexMacro, MacroReplayOptions, MacroReplayResult } from "./schema.js";
5
+ /** Same knobs as `Auspex` browser runs: stealth launch + context + `replayMacro`. */
6
+ export interface MacroReplayLaunchOptions extends MacroReplayOptions {
7
+ proxy?: ProxyConfig;
8
+ cookies?: CookieParam[];
9
+ extraHTTPHeaders?: Record<string, string>;
10
+ viewport?: {
11
+ width: number;
12
+ height: number;
13
+ };
14
+ locale?: string;
15
+ timezoneId?: string;
16
+ userAgent?: string;
17
+ /** Merged into `launchStealthBrowser` (e.g. `{ headless: false }`) */
18
+ browserLaunchOptions?: LaunchOptions;
19
+ }
20
+ /**
21
+ * Launches stealth Chromium, creates a context (aligned with the agent defaults), runs
22
+ * {@link replayMacro}, then closes browser resources. Use when you do not already hold a `Page`.
23
+ */
24
+ export declare function replayMacroWithBrowser(macro: AuspexMacro, options?: MacroReplayLaunchOptions): Promise<MacroReplayResult>;
25
+ export declare function replayMacro(page: Page, macro: AuspexMacro, options?: MacroReplayOptions): Promise<MacroReplayResult>;
26
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/macro/replay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAK5C,OAAO,KAAK,EAAe,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQtF,qFAAqF;AACrF,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,aAAa,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA+C5B;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA+D5B"}
@@ -0,0 +1,121 @@
1
+ import { launchStealthBrowser, STEALTH_INIT_SCRIPT, CHROME_UA } from "../browser/stealth.js";
2
+ import { DEFAULTS } from "../config/defaults.js";
3
+ import { executeAction } from "../browser/executor.js";
4
+ import { validateUrl } from "../security/url-validator.js";
5
+ /**
6
+ * Matches `runAgentLoop`: no inter-step `actionDelayMs` after `wait`/`goto` (intrinsic timing)
7
+ * or after `search` (same as `continue` before the delay block in the agent).
8
+ */
9
+ const SKIP_INTER_STEP_DELAY_AFTER = new Set(["wait", "goto", "search"]);
10
+ /**
11
+ * Launches stealth Chromium, creates a context (aligned with the agent defaults), runs
12
+ * {@link replayMacro}, then closes browser resources. Use when you do not already hold a `Page`.
13
+ */
14
+ export async function replayMacroWithBrowser(macro, options = {}) {
15
+ const launchOpts = { ...options.browserLaunchOptions };
16
+ if (options.proxy) {
17
+ launchOpts.proxy = {
18
+ server: options.proxy.server,
19
+ username: options.proxy.username,
20
+ password: options.proxy.password,
21
+ };
22
+ }
23
+ const browser = await launchStealthBrowser(launchOpts);
24
+ try {
25
+ const contextOptions = {
26
+ userAgent: options.userAgent ?? CHROME_UA,
27
+ viewport: options.viewport ?? { width: 1920, height: 1080 },
28
+ locale: options.locale ?? "pt-BR",
29
+ timezoneId: options.timezoneId ?? "America/Sao_Paulo",
30
+ extraHTTPHeaders: options.extraHTTPHeaders,
31
+ };
32
+ const context = await browser.newContext(contextOptions);
33
+ if (options.cookies && options.cookies.length > 0) {
34
+ const host = new URL(macro.startUrl).hostname;
35
+ await context.addCookies(options.cookies.map((c) => ({
36
+ name: c.name,
37
+ value: c.value,
38
+ domain: c.domain ?? host,
39
+ path: c.path ?? "/",
40
+ httpOnly: c.httpOnly,
41
+ secure: c.secure,
42
+ sameSite: c.sameSite,
43
+ expires: c.expires,
44
+ })));
45
+ }
46
+ await context.addInitScript(STEALTH_INIT_SCRIPT);
47
+ const page = await context.newPage();
48
+ try {
49
+ return await replayMacro(page, macro, options);
50
+ }
51
+ finally {
52
+ await context.close().catch(() => { });
53
+ }
54
+ }
55
+ finally {
56
+ await browser.close().catch(() => { });
57
+ }
58
+ }
59
+ export async function replayMacro(page, macro, options = {}) {
60
+ const urlOptions = {
61
+ allowedDomains: options.allowedDomains,
62
+ blockedDomains: options.blockedDomains,
63
+ };
64
+ const actionDelayMs = options.actionDelayMs ?? DEFAULTS.actionDelayMs;
65
+ const gotoTimeoutMs = options.gotoTimeoutMs ?? DEFAULTS.gotoTimeoutMs;
66
+ const signal = options.signal;
67
+ const needsSearch = macro.steps.some((s) => s.type === "search");
68
+ if (needsSearch && !options.searxngClient) {
69
+ return {
70
+ status: "error",
71
+ error: "macro.steps contains search but searxngClient was not provided",
72
+ };
73
+ }
74
+ const dismissDialog = (dialog) => dialog.dismiss().catch(() => { });
75
+ page.on("dialog", dismissDialog);
76
+ try {
77
+ try {
78
+ await validateUrl(macro.startUrl, urlOptions);
79
+ await page.goto(macro.startUrl, { waitUntil: "domcontentloaded", timeout: gotoTimeoutMs });
80
+ }
81
+ catch (err) {
82
+ const msg = err instanceof Error ? err.message : String(err);
83
+ return { status: "error", error: `Initial navigation failed: ${msg}` };
84
+ }
85
+ for (const step of macro.steps) {
86
+ if (signal?.aborted) {
87
+ return { status: "error", error: "Aborted by user" };
88
+ }
89
+ if (step.type === "search") {
90
+ const client = options.searxngClient;
91
+ if (!client) {
92
+ return { status: "error", error: "searxngClient required for search step" };
93
+ }
94
+ try {
95
+ await client.search(step.query, 5);
96
+ }
97
+ catch (err) {
98
+ const msg = err instanceof Error ? err.message : String(err);
99
+ return { status: "error", error: `search failed: ${msg}` };
100
+ }
101
+ }
102
+ else {
103
+ try {
104
+ await executeAction(page, step, urlOptions);
105
+ }
106
+ catch (err) {
107
+ const msg = err instanceof Error ? err.message : String(err);
108
+ return { status: "error", error: `step ${step.type} failed: ${msg}` };
109
+ }
110
+ }
111
+ if (!SKIP_INTER_STEP_DELAY_AFTER.has(step.type) && actionDelayMs > 0) {
112
+ await page.waitForTimeout(actionDelayMs);
113
+ }
114
+ }
115
+ return { status: "ok" };
116
+ }
117
+ finally {
118
+ page.off("dialog", dismissDialog);
119
+ }
120
+ }
121
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/macro/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,440 @@
1
+ import { z } from "zod";
2
+ import type { SearXNGClient } from "../search/searxng-client.js";
3
+ export declare const macroStepSchema: z.ZodEffects<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
4
+ type: z.ZodLiteral<"search">;
5
+ query: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ type: "search";
8
+ query: string;
9
+ }, {
10
+ type: "search";
11
+ query: string;
12
+ }>, z.ZodObject<{
13
+ type: z.ZodLiteral<"click">;
14
+ selector: z.ZodEffects<z.ZodString, string, string>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ type: "click";
17
+ selector: string;
18
+ }, {
19
+ type: "click";
20
+ selector: string;
21
+ }>, z.ZodObject<{
22
+ type: z.ZodLiteral<"type">;
23
+ selector: z.ZodEffects<z.ZodString, string, string>;
24
+ text: z.ZodString;
25
+ }, "strip", z.ZodTypeAny, {
26
+ type: "type";
27
+ selector: string;
28
+ text: string;
29
+ }, {
30
+ type: "type";
31
+ selector: string;
32
+ text: string;
33
+ }>, z.ZodObject<{
34
+ type: z.ZodLiteral<"select">;
35
+ selector: z.ZodEffects<z.ZodString, string, string>;
36
+ value: z.ZodString;
37
+ }, "strip", z.ZodTypeAny, {
38
+ type: "select";
39
+ value: string;
40
+ selector: string;
41
+ }, {
42
+ type: "select";
43
+ value: string;
44
+ selector: string;
45
+ }>, z.ZodObject<{
46
+ type: z.ZodLiteral<"pressKey">;
47
+ key: z.ZodEnum<["Enter", "Tab", "Escape", "Backspace", "Delete", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", "Space", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"]>;
48
+ }, "strip", z.ZodTypeAny, {
49
+ type: "pressKey";
50
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
51
+ }, {
52
+ type: "pressKey";
53
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
54
+ }>, z.ZodObject<{
55
+ type: z.ZodLiteral<"hover">;
56
+ selector: z.ZodEffects<z.ZodString, string, string>;
57
+ }, "strip", z.ZodTypeAny, {
58
+ type: "hover";
59
+ selector: string;
60
+ }, {
61
+ type: "hover";
62
+ selector: string;
63
+ }>, z.ZodObject<{
64
+ type: z.ZodLiteral<"goto">;
65
+ url: z.ZodString;
66
+ }, "strip", z.ZodTypeAny, {
67
+ type: "goto";
68
+ url: string;
69
+ }, {
70
+ type: "goto";
71
+ url: string;
72
+ }>, z.ZodObject<{
73
+ type: z.ZodLiteral<"wait">;
74
+ ms: z.ZodNumber;
75
+ }, "strip", z.ZodTypeAny, {
76
+ type: "wait";
77
+ ms: number;
78
+ }, {
79
+ type: "wait";
80
+ ms: number;
81
+ }>, z.ZodObject<{
82
+ type: z.ZodLiteral<"scroll">;
83
+ direction: z.ZodEnum<["up", "down"]>;
84
+ amount: z.ZodOptional<z.ZodNumber>;
85
+ }, "strip", z.ZodTypeAny, {
86
+ type: "scroll";
87
+ direction: "up" | "down";
88
+ amount?: number | undefined;
89
+ }, {
90
+ type: "scroll";
91
+ direction: "up" | "down";
92
+ amount?: number | undefined;
93
+ }>, z.ZodObject<{
94
+ type: z.ZodLiteral<"done">;
95
+ result: z.ZodString;
96
+ }, "strip", z.ZodTypeAny, {
97
+ type: "done";
98
+ result: string;
99
+ }, {
100
+ type: "done";
101
+ result: string;
102
+ }>]>, {
103
+ type: "search";
104
+ query: string;
105
+ } | {
106
+ type: "click";
107
+ selector: string;
108
+ } | {
109
+ type: "type";
110
+ selector: string;
111
+ text: string;
112
+ } | {
113
+ type: "select";
114
+ value: string;
115
+ selector: string;
116
+ } | {
117
+ type: "pressKey";
118
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
119
+ } | {
120
+ type: "hover";
121
+ selector: string;
122
+ } | {
123
+ type: "goto";
124
+ url: string;
125
+ } | {
126
+ type: "wait";
127
+ ms: number;
128
+ } | {
129
+ type: "scroll";
130
+ direction: "up" | "down";
131
+ amount?: number | undefined;
132
+ } | {
133
+ type: "done";
134
+ result: string;
135
+ }, {
136
+ type: "search";
137
+ query: string;
138
+ } | {
139
+ type: "click";
140
+ selector: string;
141
+ } | {
142
+ type: "type";
143
+ selector: string;
144
+ text: string;
145
+ } | {
146
+ type: "select";
147
+ value: string;
148
+ selector: string;
149
+ } | {
150
+ type: "pressKey";
151
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
152
+ } | {
153
+ type: "hover";
154
+ selector: string;
155
+ } | {
156
+ type: "goto";
157
+ url: string;
158
+ } | {
159
+ type: "wait";
160
+ ms: number;
161
+ } | {
162
+ type: "scroll";
163
+ direction: "up" | "down";
164
+ amount?: number | undefined;
165
+ } | {
166
+ type: "done";
167
+ result: string;
168
+ }>;
169
+ export declare const auspexMacroSchema: z.ZodObject<{
170
+ version: z.ZodLiteral<1>;
171
+ startUrl: z.ZodString;
172
+ sourceTier: z.ZodEnum<["http", "playwright"]>;
173
+ steps: z.ZodArray<z.ZodEffects<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
174
+ type: z.ZodLiteral<"search">;
175
+ query: z.ZodString;
176
+ }, "strip", z.ZodTypeAny, {
177
+ type: "search";
178
+ query: string;
179
+ }, {
180
+ type: "search";
181
+ query: string;
182
+ }>, z.ZodObject<{
183
+ type: z.ZodLiteral<"click">;
184
+ selector: z.ZodEffects<z.ZodString, string, string>;
185
+ }, "strip", z.ZodTypeAny, {
186
+ type: "click";
187
+ selector: string;
188
+ }, {
189
+ type: "click";
190
+ selector: string;
191
+ }>, z.ZodObject<{
192
+ type: z.ZodLiteral<"type">;
193
+ selector: z.ZodEffects<z.ZodString, string, string>;
194
+ text: z.ZodString;
195
+ }, "strip", z.ZodTypeAny, {
196
+ type: "type";
197
+ selector: string;
198
+ text: string;
199
+ }, {
200
+ type: "type";
201
+ selector: string;
202
+ text: string;
203
+ }>, z.ZodObject<{
204
+ type: z.ZodLiteral<"select">;
205
+ selector: z.ZodEffects<z.ZodString, string, string>;
206
+ value: z.ZodString;
207
+ }, "strip", z.ZodTypeAny, {
208
+ type: "select";
209
+ value: string;
210
+ selector: string;
211
+ }, {
212
+ type: "select";
213
+ value: string;
214
+ selector: string;
215
+ }>, z.ZodObject<{
216
+ type: z.ZodLiteral<"pressKey">;
217
+ key: z.ZodEnum<["Enter", "Tab", "Escape", "Backspace", "Delete", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", "Space", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"]>;
218
+ }, "strip", z.ZodTypeAny, {
219
+ type: "pressKey";
220
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
221
+ }, {
222
+ type: "pressKey";
223
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
224
+ }>, z.ZodObject<{
225
+ type: z.ZodLiteral<"hover">;
226
+ selector: z.ZodEffects<z.ZodString, string, string>;
227
+ }, "strip", z.ZodTypeAny, {
228
+ type: "hover";
229
+ selector: string;
230
+ }, {
231
+ type: "hover";
232
+ selector: string;
233
+ }>, z.ZodObject<{
234
+ type: z.ZodLiteral<"goto">;
235
+ url: z.ZodString;
236
+ }, "strip", z.ZodTypeAny, {
237
+ type: "goto";
238
+ url: string;
239
+ }, {
240
+ type: "goto";
241
+ url: string;
242
+ }>, z.ZodObject<{
243
+ type: z.ZodLiteral<"wait">;
244
+ ms: z.ZodNumber;
245
+ }, "strip", z.ZodTypeAny, {
246
+ type: "wait";
247
+ ms: number;
248
+ }, {
249
+ type: "wait";
250
+ ms: number;
251
+ }>, z.ZodObject<{
252
+ type: z.ZodLiteral<"scroll">;
253
+ direction: z.ZodEnum<["up", "down"]>;
254
+ amount: z.ZodOptional<z.ZodNumber>;
255
+ }, "strip", z.ZodTypeAny, {
256
+ type: "scroll";
257
+ direction: "up" | "down";
258
+ amount?: number | undefined;
259
+ }, {
260
+ type: "scroll";
261
+ direction: "up" | "down";
262
+ amount?: number | undefined;
263
+ }>, z.ZodObject<{
264
+ type: z.ZodLiteral<"done">;
265
+ result: z.ZodString;
266
+ }, "strip", z.ZodTypeAny, {
267
+ type: "done";
268
+ result: string;
269
+ }, {
270
+ type: "done";
271
+ result: string;
272
+ }>]>, {
273
+ type: "search";
274
+ query: string;
275
+ } | {
276
+ type: "click";
277
+ selector: string;
278
+ } | {
279
+ type: "type";
280
+ selector: string;
281
+ text: string;
282
+ } | {
283
+ type: "select";
284
+ value: string;
285
+ selector: string;
286
+ } | {
287
+ type: "pressKey";
288
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
289
+ } | {
290
+ type: "hover";
291
+ selector: string;
292
+ } | {
293
+ type: "goto";
294
+ url: string;
295
+ } | {
296
+ type: "wait";
297
+ ms: number;
298
+ } | {
299
+ type: "scroll";
300
+ direction: "up" | "down";
301
+ amount?: number | undefined;
302
+ } | {
303
+ type: "done";
304
+ result: string;
305
+ }, {
306
+ type: "search";
307
+ query: string;
308
+ } | {
309
+ type: "click";
310
+ selector: string;
311
+ } | {
312
+ type: "type";
313
+ selector: string;
314
+ text: string;
315
+ } | {
316
+ type: "select";
317
+ value: string;
318
+ selector: string;
319
+ } | {
320
+ type: "pressKey";
321
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
322
+ } | {
323
+ type: "hover";
324
+ selector: string;
325
+ } | {
326
+ type: "goto";
327
+ url: string;
328
+ } | {
329
+ type: "wait";
330
+ ms: number;
331
+ } | {
332
+ type: "scroll";
333
+ direction: "up" | "down";
334
+ amount?: number | undefined;
335
+ } | {
336
+ type: "done";
337
+ result: string;
338
+ }>, "many">;
339
+ capturedResult: z.ZodOptional<z.ZodString>;
340
+ }, "strip", z.ZodTypeAny, {
341
+ version: 1;
342
+ startUrl: string;
343
+ sourceTier: "http" | "playwright";
344
+ steps: ({
345
+ type: "search";
346
+ query: string;
347
+ } | {
348
+ type: "click";
349
+ selector: string;
350
+ } | {
351
+ type: "type";
352
+ selector: string;
353
+ text: string;
354
+ } | {
355
+ type: "select";
356
+ value: string;
357
+ selector: string;
358
+ } | {
359
+ type: "pressKey";
360
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
361
+ } | {
362
+ type: "hover";
363
+ selector: string;
364
+ } | {
365
+ type: "goto";
366
+ url: string;
367
+ } | {
368
+ type: "wait";
369
+ ms: number;
370
+ } | {
371
+ type: "scroll";
372
+ direction: "up" | "down";
373
+ amount?: number | undefined;
374
+ } | {
375
+ type: "done";
376
+ result: string;
377
+ })[];
378
+ capturedResult?: string | undefined;
379
+ }, {
380
+ version: 1;
381
+ startUrl: string;
382
+ sourceTier: "http" | "playwright";
383
+ steps: ({
384
+ type: "search";
385
+ query: string;
386
+ } | {
387
+ type: "click";
388
+ selector: string;
389
+ } | {
390
+ type: "type";
391
+ selector: string;
392
+ text: string;
393
+ } | {
394
+ type: "select";
395
+ value: string;
396
+ selector: string;
397
+ } | {
398
+ type: "pressKey";
399
+ key: "Enter" | "Tab" | "Escape" | "Backspace" | "Delete" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End" | "PageUp" | "PageDown" | "Space" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12";
400
+ } | {
401
+ type: "hover";
402
+ selector: string;
403
+ } | {
404
+ type: "goto";
405
+ url: string;
406
+ } | {
407
+ type: "wait";
408
+ ms: number;
409
+ } | {
410
+ type: "scroll";
411
+ direction: "up" | "down";
412
+ amount?: number | undefined;
413
+ } | {
414
+ type: "done";
415
+ result: string;
416
+ })[];
417
+ capturedResult?: string | undefined;
418
+ }>;
419
+ export type AuspexMacro = z.infer<typeof auspexMacroSchema>;
420
+ export declare class MacroParseError extends Error {
421
+ constructor(message: string);
422
+ }
423
+ export type MacroReplayStatus = "ok" | "error";
424
+ export interface MacroReplayResult {
425
+ status: MacroReplayStatus;
426
+ error?: string;
427
+ }
428
+ export interface MacroReplayOptions {
429
+ allowedDomains?: string[];
430
+ blockedDomains?: string[];
431
+ /** Delay in ms after each step except `wait`, `goto`, and `search` (matches the agent loop). Default: 500 */
432
+ actionDelayMs?: number;
433
+ /** Timeout for `page.goto` of `startUrl` and per-step `goto`. Default: 15000 */
434
+ gotoTimeoutMs?: number;
435
+ /** Required when `macro.steps` contains `type: "search"` */
436
+ searxngClient?: SearXNGClient;
437
+ /** Passed through for replay (not stored in macro) */
438
+ signal?: AbortSignal;
439
+ }
440
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/macro/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAO1B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6GAA6G;IAC7G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,sDAAsD;IACtD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import { actionSchema } from "../security/action-validator.js";
3
+ export const macroStepSchema = actionSchema.superRefine((val, ctx) => {
4
+ if (val.type === "done") {
5
+ ctx.addIssue({
6
+ code: z.ZodIssueCode.custom,
7
+ message: "Macro step cannot be type done",
8
+ });
9
+ }
10
+ });
11
+ export const auspexMacroSchema = z.object({
12
+ version: z.literal(1),
13
+ startUrl: z.string().url(),
14
+ sourceTier: z.enum(["http", "playwright"]),
15
+ steps: z.array(macroStepSchema),
16
+ capturedResult: z.string().optional(),
17
+ });
18
+ export class MacroParseError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = "MacroParseError";
22
+ }
23
+ }
24
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/macro/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAG/D,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,gCAAgC;SAC1C,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC1B,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IAC/B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAIH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import { type AuspexMacro } from "./schema.js";
2
+ export declare function macroToJsonString(macro: AuspexMacro): string;
3
+ export declare function parseMacroJson(json: string): AuspexMacro;
4
+ //# sourceMappingURL=serialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/macro/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAEnF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAaxD"}
@@ -0,0 +1,20 @@
1
+ import { MacroParseError, auspexMacroSchema } from "./schema.js";
2
+ export function macroToJsonString(macro) {
3
+ return JSON.stringify(macro);
4
+ }
5
+ export function parseMacroJson(json) {
6
+ let parsed;
7
+ try {
8
+ parsed = JSON.parse(json);
9
+ }
10
+ catch {
11
+ throw new MacroParseError("Invalid JSON");
12
+ }
13
+ const r = auspexMacroSchema.safeParse(parsed);
14
+ if (!r.success) {
15
+ const msg = r.error.issues.map((i) => i.message).join("; ");
16
+ throw new MacroParseError(msg || "Invalid macro");
17
+ }
18
+ return r.data;
19
+ }
20
+ //# sourceMappingURL=serialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/macro/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAEnF,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IAClD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,CAAC,GAAG,iBAAiB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,CAAC;AAChB,CAAC"}