autokap 1.0.8 → 1.1.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/assets/skill/OPCODE-REFERENCE.md +29 -1
- package/assets/skill/SKILL.md +2 -1
- package/dist/auth-capture.js +35 -2
- package/dist/billing-operation-logging.d.ts +4 -3
- package/dist/billing-operation-logging.js +3 -2
- package/dist/browser.d.ts +10 -10
- package/dist/browser.js +32 -28
- package/dist/capture-encryption.d.ts +3 -1
- package/dist/capture-encryption.js +21 -6
- package/dist/capture-strategy.js +3 -2
- package/dist/cli-config.d.ts +2 -1
- package/dist/cli-config.js +51 -2
- package/dist/cli-contract.d.ts +5 -1
- package/dist/cli-contract.js +7 -1
- package/dist/cli-runner-local.js +16 -3
- package/dist/cli-runner.js +165 -18
- package/dist/cli.js +25 -19
- package/dist/clip-begin-frame-recorder.d.ts +44 -0
- package/dist/clip-begin-frame-recorder.js +250 -0
- package/dist/clip-capture-backend.d.ts +25 -0
- package/dist/clip-capture-backend.js +189 -0
- package/dist/clip-capture-loop.d.ts +61 -0
- package/dist/clip-capture-loop.js +111 -0
- package/dist/clip-frame-recorder.d.ts +63 -0
- package/dist/clip-frame-recorder.js +305 -0
- package/dist/clip-postprocess.d.ts +31 -2
- package/dist/clip-postprocess.js +174 -57
- package/dist/clip-runtime.d.ts +18 -0
- package/dist/clip-runtime.js +67 -0
- package/dist/clip-scale.d.ts +10 -0
- package/dist/clip-scale.js +21 -0
- package/dist/clip-screencast-recorder.d.ts +42 -0
- package/dist/clip-screencast-recorder.js +242 -0
- package/dist/clip-sidecar.d.ts +54 -0
- package/dist/clip-sidecar.js +208 -0
- package/dist/cost-logging.d.ts +1 -1
- package/dist/env-validation.js +38 -4
- package/dist/execution-schema.d.ts +690 -360
- package/dist/execution-schema.js +98 -42
- package/dist/execution-types.d.ts +53 -3
- package/dist/execution-types.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/llm-healer.d.ts +2 -10
- package/dist/llm-healer.js +109 -62
- package/dist/llm-provider.js +3 -0
- package/dist/opcode-actions.js +13 -0
- package/dist/opcode-runner.js +21 -12
- package/dist/program-signing.d.ts +1094 -0
- package/dist/program-signing.js +140 -0
- package/dist/provider-config.d.ts +5 -0
- package/dist/provider-config.js +28 -1
- package/dist/recovery-chain.js +40 -16
- package/dist/server-credit-usage.d.ts +1 -1
- package/dist/types.d.ts +8 -2
- package/dist/web-playwright-local.d.ts +31 -1
- package/dist/web-playwright-local.js +207 -37
- package/package.json +12 -2
package/dist/execution-schema.js
CHANGED
|
@@ -21,7 +21,7 @@ export const PostconditionSpecSchema = z.object({
|
|
|
21
21
|
text: z.string().optional(),
|
|
22
22
|
threshold: z.number().min(0).max(1).optional(),
|
|
23
23
|
waitMs: z.number().int().positive().optional(),
|
|
24
|
-
}).superRefine((value, ctx) => {
|
|
24
|
+
}).strict().superRefine((value, ctx) => {
|
|
25
25
|
if (value.type === 'route_matches' && !value.pattern) {
|
|
26
26
|
ctx.addIssue({
|
|
27
27
|
code: z.ZodIssueCode.custom,
|
|
@@ -51,7 +51,7 @@ export const RecoveryPolicySchema = z.object({
|
|
|
51
51
|
useAltInteraction: z.boolean(),
|
|
52
52
|
allowReload: z.boolean(),
|
|
53
53
|
allowHealer: z.boolean(),
|
|
54
|
-
});
|
|
54
|
+
}).strict();
|
|
55
55
|
// ── Opcode base fields ──────────────────────────────────────────────
|
|
56
56
|
const opcodeBase = {
|
|
57
57
|
description: z.string().min(1),
|
|
@@ -68,7 +68,7 @@ const opcodeBase = {
|
|
|
68
68
|
const StrictUrlSchema = z.string().min(1).refine((value) => {
|
|
69
69
|
try {
|
|
70
70
|
const parsed = new URL(value);
|
|
71
|
-
return Boolean(parsed.host);
|
|
71
|
+
return (parsed.protocol === 'http:' || parsed.protocol === 'https:') && Boolean(parsed.host);
|
|
72
72
|
}
|
|
73
73
|
catch {
|
|
74
74
|
return false;
|
|
@@ -81,22 +81,22 @@ const NavigateOpcodeSchema = z.object({
|
|
|
81
81
|
kind: z.literal('NAVIGATE'),
|
|
82
82
|
...opcodeBase,
|
|
83
83
|
url: StrictUrlSchema,
|
|
84
|
-
});
|
|
84
|
+
}).strict();
|
|
85
85
|
const DismissOverlaysOpcodeSchema = z.object({
|
|
86
86
|
kind: z.literal('DISMISS_OVERLAYS'),
|
|
87
87
|
...opcodeBase,
|
|
88
|
-
});
|
|
88
|
+
}).strict();
|
|
89
89
|
const AssertRouteOpcodeSchema = z.object({
|
|
90
90
|
kind: z.literal('ASSERT_ROUTE'),
|
|
91
91
|
...opcodeBase,
|
|
92
92
|
urlPattern: z.string().min(1),
|
|
93
|
-
});
|
|
93
|
+
}).strict();
|
|
94
94
|
const AssertSurfaceOpcodeSchema = z.object({
|
|
95
95
|
kind: z.literal('ASSERT_SURFACE'),
|
|
96
96
|
...opcodeBase,
|
|
97
97
|
selectors: z.array(z.string().min(1)).min(1),
|
|
98
98
|
matchAll: z.boolean(),
|
|
99
|
-
});
|
|
99
|
+
}).strict();
|
|
100
100
|
const SemanticTargetSchema = z.object({
|
|
101
101
|
text: z.string().optional(),
|
|
102
102
|
role: z.string().optional(),
|
|
@@ -104,7 +104,7 @@ const SemanticTargetSchema = z.object({
|
|
|
104
104
|
near: z.string().optional(),
|
|
105
105
|
placeholder: z.string().optional(),
|
|
106
106
|
exact: z.boolean().optional(),
|
|
107
|
-
}).refine((value) => Boolean(value.text || value.role || value.label || value.near || value.placeholder), 'semantic targets need at least one identifying field');
|
|
107
|
+
}).strict().refine((value) => Boolean(value.text || value.role || value.label || value.near || value.placeholder), 'semantic targets need at least one identifying field');
|
|
108
108
|
const ClickOpcodeSchema = z.object({
|
|
109
109
|
kind: z.literal('CLICK'),
|
|
110
110
|
...opcodeBase,
|
|
@@ -113,7 +113,7 @@ const ClickOpcodeSchema = z.object({
|
|
|
113
113
|
button: z.enum(['right', 'middle']).optional(),
|
|
114
114
|
fingerprint: z.string().optional(),
|
|
115
115
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
116
|
-
});
|
|
116
|
+
}).strict();
|
|
117
117
|
const TypeOpcodeSchema = z.object({
|
|
118
118
|
kind: z.literal('TYPE'),
|
|
119
119
|
...opcodeBase,
|
|
@@ -124,19 +124,19 @@ const TypeOpcodeSchema = z.object({
|
|
|
124
124
|
clearFirst: z.boolean(),
|
|
125
125
|
fingerprint: z.string().optional(),
|
|
126
126
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
127
|
-
});
|
|
127
|
+
}).strict();
|
|
128
128
|
const PressKeyOpcodeSchema = z.object({
|
|
129
129
|
kind: z.literal('PRESS_KEY'),
|
|
130
130
|
...opcodeBase,
|
|
131
131
|
key: z.string().min(1),
|
|
132
|
-
});
|
|
132
|
+
}).strict();
|
|
133
133
|
const WaitForOpcodeSchema = z.object({
|
|
134
134
|
kind: z.literal('WAIT_FOR'),
|
|
135
135
|
...opcodeBase,
|
|
136
136
|
selector: z.string().min(1).optional(),
|
|
137
137
|
target: SemanticTargetSchema.optional(),
|
|
138
138
|
state: z.enum(['visible', 'attached']),
|
|
139
|
-
}).superRefine((value, ctx) => {
|
|
139
|
+
}).strict().superRefine((value, ctx) => {
|
|
140
140
|
if (!value.selector && !value.target) {
|
|
141
141
|
ctx.addIssue({
|
|
142
142
|
code: z.ZodIssueCode.custom,
|
|
@@ -149,7 +149,7 @@ const storageHintSchema = z.object({
|
|
|
149
149
|
storage: z.enum(['localStorage', 'sessionStorage', 'cookie']),
|
|
150
150
|
key: z.string().min(1),
|
|
151
151
|
value: z.string(),
|
|
152
|
-
});
|
|
152
|
+
}).strict();
|
|
153
153
|
const SetLocaleOpcodeSchema = z.object({
|
|
154
154
|
kind: z.literal('SET_LOCALE'),
|
|
155
155
|
...opcodeBase,
|
|
@@ -157,7 +157,7 @@ const SetLocaleOpcodeSchema = z.object({
|
|
|
157
157
|
method: z.enum(['browser_context', 'ui_interaction', 'storage']),
|
|
158
158
|
selector: z.string().optional(),
|
|
159
159
|
storageHints: z.array(storageHintSchema).optional(),
|
|
160
|
-
}).superRefine((value, ctx) => {
|
|
160
|
+
}).strict().superRefine((value, ctx) => {
|
|
161
161
|
if (value.method === 'ui_interaction' && !value.selector) {
|
|
162
162
|
ctx.addIssue({
|
|
163
163
|
code: z.ZodIssueCode.custom,
|
|
@@ -180,7 +180,7 @@ const SetThemeOpcodeSchema = z.object({
|
|
|
180
180
|
method: z.enum(['color_scheme', 'ui_interaction', 'storage']),
|
|
181
181
|
selector: z.string().optional(),
|
|
182
182
|
storageHints: z.array(storageHintSchema).optional(),
|
|
183
|
-
}).superRefine((value, ctx) => {
|
|
183
|
+
}).strict().superRefine((value, ctx) => {
|
|
184
184
|
if (value.method === 'ui_interaction' && !value.selector) {
|
|
185
185
|
ctx.addIssue({
|
|
186
186
|
code: z.ZodIssueCode.custom,
|
|
@@ -203,20 +203,20 @@ const ScrollOpcodeSchema = z.object({
|
|
|
203
203
|
amount: z.number().int().positive().optional(),
|
|
204
204
|
targetSelector: z.string().optional(),
|
|
205
205
|
target: SemanticTargetSchema.optional(),
|
|
206
|
-
});
|
|
206
|
+
}).strict();
|
|
207
207
|
const CaptureScreenshotOpcodeSchema = z.object({
|
|
208
208
|
kind: z.literal('CAPTURE_SCREENSHOT'),
|
|
209
209
|
...opcodeBase,
|
|
210
210
|
captureId: z.string().optional(),
|
|
211
211
|
captureName: z.string().optional(),
|
|
212
212
|
elementSelector: z.string().optional(),
|
|
213
|
-
});
|
|
213
|
+
}).strict();
|
|
214
214
|
const CaptureDomOpcodeSchema = z.object({
|
|
215
215
|
kind: z.literal('CAPTURE_DOM'),
|
|
216
216
|
...opcodeBase,
|
|
217
217
|
stateName: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, 'stateName must be kebab-case'),
|
|
218
218
|
selector: z.string().min(1).optional(),
|
|
219
|
-
});
|
|
219
|
+
}).strict();
|
|
220
220
|
const CaptureFragmentOpcodeSchema = z.object({
|
|
221
221
|
kind: z.literal('CAPTURE_FRAGMENT'),
|
|
222
222
|
...opcodeBase,
|
|
@@ -231,19 +231,19 @@ const CaptureFragmentOpcodeSchema = z.object({
|
|
|
231
231
|
triggerSelector: z.string().min(1).optional(),
|
|
232
232
|
mountStrategy: z.string().min(1).optional(),
|
|
233
233
|
mountTargetSelector: z.string().min(1).optional(),
|
|
234
|
-
});
|
|
234
|
+
}).strict();
|
|
235
235
|
const BeginClipOpcodeSchema = z.object({
|
|
236
236
|
kind: z.literal('BEGIN_CLIP'),
|
|
237
237
|
...opcodeBase,
|
|
238
238
|
clipId: z.string().optional(),
|
|
239
239
|
clipName: z.string().optional(),
|
|
240
|
-
});
|
|
240
|
+
}).strict();
|
|
241
241
|
const EndClipOpcodeSchema = z.object({
|
|
242
242
|
kind: z.literal('END_CLIP'),
|
|
243
243
|
...opcodeBase,
|
|
244
244
|
clipId: z.string().optional(),
|
|
245
245
|
clipName: z.string().optional(),
|
|
246
|
-
});
|
|
246
|
+
}).strict();
|
|
247
247
|
const HoverOpcodeSchema = z.object({
|
|
248
248
|
kind: z.literal('HOVER'),
|
|
249
249
|
...opcodeBase,
|
|
@@ -251,7 +251,7 @@ const HoverOpcodeSchema = z.object({
|
|
|
251
251
|
target: SemanticTargetSchema.optional(),
|
|
252
252
|
fingerprint: z.string().optional(),
|
|
253
253
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
254
|
-
});
|
|
254
|
+
}).strict();
|
|
255
255
|
const SelectOptionOpcodeSchema = z.object({
|
|
256
256
|
kind: z.literal('SELECT_OPTION'),
|
|
257
257
|
...opcodeBase,
|
|
@@ -262,7 +262,7 @@ const SelectOptionOpcodeSchema = z.object({
|
|
|
262
262
|
optionIndex: z.number().int().min(0).optional(),
|
|
263
263
|
fingerprint: z.string().optional(),
|
|
264
264
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
265
|
-
}).superRefine((value, ctx) => {
|
|
265
|
+
}).strict().superRefine((value, ctx) => {
|
|
266
266
|
if (value.optionLabel === undefined && value.optionValue === undefined && value.optionIndex === undefined) {
|
|
267
267
|
ctx.addIssue({
|
|
268
268
|
code: z.ZodIssueCode.custom,
|
|
@@ -278,7 +278,7 @@ const CheckOpcodeSchema = z.object({
|
|
|
278
278
|
checked: z.boolean(),
|
|
279
279
|
fingerprint: z.string().optional(),
|
|
280
280
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
281
|
-
});
|
|
281
|
+
}).strict();
|
|
282
282
|
const DoubleClickOpcodeSchema = z.object({
|
|
283
283
|
kind: z.literal('DOUBLE_CLICK'),
|
|
284
284
|
...opcodeBase,
|
|
@@ -286,6 +286,38 @@ const DoubleClickOpcodeSchema = z.object({
|
|
|
286
286
|
target: SemanticTargetSchema.optional(),
|
|
287
287
|
fingerprint: z.string().optional(),
|
|
288
288
|
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
289
|
+
}).strict();
|
|
290
|
+
const DragOpcodeSchema = z.object({
|
|
291
|
+
kind: z.literal('DRAG'),
|
|
292
|
+
...opcodeBase,
|
|
293
|
+
selector: z.string().min(1),
|
|
294
|
+
target: SemanticTargetSchema.optional(),
|
|
295
|
+
fingerprint: z.string().optional(),
|
|
296
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
297
|
+
toSelector: z.string().min(1).optional(),
|
|
298
|
+
toTarget: SemanticTargetSchema.optional(),
|
|
299
|
+
toSelectorAlternates: z.array(z.string().min(1)).optional(),
|
|
300
|
+
offset: z.object({
|
|
301
|
+
dx: z.number(),
|
|
302
|
+
dy: z.number(),
|
|
303
|
+
}).strict().optional(),
|
|
304
|
+
}).strict().superRefine((value, ctx) => {
|
|
305
|
+
const hasElementDest = Boolean(value.toSelector || value.toTarget);
|
|
306
|
+
const hasOffsetDest = Boolean(value.offset);
|
|
307
|
+
if (!hasElementDest && !hasOffsetDest) {
|
|
308
|
+
ctx.addIssue({
|
|
309
|
+
code: z.ZodIssueCode.custom,
|
|
310
|
+
message: 'DRAG requires a destination: provide `toSelector` / `toTarget` (element drag) or `offset` (relative drag)',
|
|
311
|
+
path: ['toSelector'],
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
if (hasElementDest && hasOffsetDest) {
|
|
315
|
+
ctx.addIssue({
|
|
316
|
+
code: z.ZodIssueCode.custom,
|
|
317
|
+
message: 'DRAG destination must be either an element (`toSelector` / `toTarget`) or an `offset`, not both',
|
|
318
|
+
path: ['offset'],
|
|
319
|
+
});
|
|
320
|
+
}
|
|
289
321
|
});
|
|
290
322
|
// ── Mock data opcodes (soft / non-blocking) ─────────────────────────
|
|
291
323
|
const CloneElementOpcodeSchema = z.object({
|
|
@@ -295,7 +327,7 @@ const CloneElementOpcodeSchema = z.object({
|
|
|
295
327
|
containerSelector: z.string().min(1),
|
|
296
328
|
count: z.number().int().min(1).max(500),
|
|
297
329
|
removeSource: z.boolean().optional(),
|
|
298
|
-
});
|
|
330
|
+
}).strict();
|
|
299
331
|
const InjectMockDataOpcodeSchema = z.object({
|
|
300
332
|
kind: z.literal('INJECT_MOCK_DATA'),
|
|
301
333
|
...opcodeBase,
|
|
@@ -309,11 +341,11 @@ const InjectMockDataOpcodeSchema = z.object({
|
|
|
309
341
|
slot: z.string().min(1),
|
|
310
342
|
selector: z.string().min(1),
|
|
311
343
|
attribute: z.string().min(1).optional(),
|
|
312
|
-
})).min(1).optional(),
|
|
344
|
+
}).strict()).min(1).optional(),
|
|
313
345
|
// Trigger fields
|
|
314
346
|
inputSelector: z.string().min(1).optional(),
|
|
315
347
|
triggerSelector: z.string().min(1).optional(),
|
|
316
|
-
}).superRefine((value, ctx) => {
|
|
348
|
+
}).strict().superRefine((value, ctx) => {
|
|
317
349
|
// The two delivery mechanisms are independent and additive. An opcode must
|
|
318
350
|
// declare AT LEAST ONE complete mechanism — typically both — but if only
|
|
319
351
|
// one is provided that's still valid.
|
|
@@ -363,14 +395,14 @@ const RemoveElementOpcodeSchema = z.object({
|
|
|
363
395
|
kind: z.literal('REMOVE_ELEMENT'),
|
|
364
396
|
...opcodeBase,
|
|
365
397
|
selector: z.string().min(1),
|
|
366
|
-
});
|
|
398
|
+
}).strict();
|
|
367
399
|
const SetAttributeOpcodeSchema = z.object({
|
|
368
400
|
kind: z.literal('SET_ATTRIBUTE'),
|
|
369
401
|
...opcodeBase,
|
|
370
402
|
selector: z.string().min(1),
|
|
371
403
|
attribute: z.string().min(1),
|
|
372
404
|
value: z.string(),
|
|
373
|
-
});
|
|
405
|
+
}).strict();
|
|
374
406
|
// ── Discriminated union ─────────────────────────────────────────────
|
|
375
407
|
export const ExecutionOpcodeSchema = z.discriminatedUnion('kind', [
|
|
376
408
|
NavigateOpcodeSchema,
|
|
@@ -393,6 +425,7 @@ export const ExecutionOpcodeSchema = z.discriminatedUnion('kind', [
|
|
|
393
425
|
SelectOptionOpcodeSchema,
|
|
394
426
|
CheckOpcodeSchema,
|
|
395
427
|
DoubleClickOpcodeSchema,
|
|
428
|
+
DragOpcodeSchema,
|
|
396
429
|
CloneElementOpcodeSchema,
|
|
397
430
|
InjectMockDataOpcodeSchema,
|
|
398
431
|
RemoveElementOpcodeSchema,
|
|
@@ -408,7 +441,7 @@ export const MockDataSlotSchema = z.object({
|
|
|
408
441
|
// descriptive label is safe here. See `inputTypeForHint()` in
|
|
409
442
|
// web/components/mock-data-editor.tsx.
|
|
410
443
|
hint: z.string().optional(),
|
|
411
|
-
});
|
|
444
|
+
}).strict();
|
|
412
445
|
export const MockDataRowSchema = z.record(z.string(), z.string());
|
|
413
446
|
export const MockDataGroupSchema = z.object({
|
|
414
447
|
name: z.string().min(1),
|
|
@@ -416,27 +449,48 @@ export const MockDataGroupSchema = z.object({
|
|
|
416
449
|
slots: z.array(MockDataSlotSchema).min(1),
|
|
417
450
|
defaultValues: z.array(MockDataRowSchema),
|
|
418
451
|
replaceExisting: z.boolean().optional(),
|
|
419
|
-
});
|
|
452
|
+
}).strict();
|
|
420
453
|
// ── Variant & precondition ──────────────────────────────────────────
|
|
421
454
|
export const VariantSpecSchema = z.object({
|
|
422
455
|
id: z.string().min(1),
|
|
423
456
|
viewport: z.object({
|
|
424
457
|
width: z.number().int().positive(),
|
|
425
458
|
height: z.number().int().positive(),
|
|
426
|
-
}),
|
|
459
|
+
}).strict(),
|
|
427
460
|
deviceScaleFactor: z.number().positive().optional(),
|
|
428
461
|
locale: z.string().optional(),
|
|
429
462
|
theme: z.enum(['light', 'dark']).optional(),
|
|
430
463
|
targetId: z.string().optional(),
|
|
431
464
|
targetLabel: z.string().optional(),
|
|
432
465
|
deviceFrame: z.string().optional(),
|
|
433
|
-
});
|
|
466
|
+
}).strict();
|
|
434
467
|
const cookieSchema = z.object({
|
|
435
468
|
name: z.string().min(1),
|
|
436
469
|
value: z.string(),
|
|
437
470
|
domain: z.string().min(1),
|
|
438
471
|
path: z.string().optional(),
|
|
439
|
-
});
|
|
472
|
+
}).strict();
|
|
473
|
+
const StorageStateCookieSchema = z.object({
|
|
474
|
+
name: z.string().min(1),
|
|
475
|
+
value: z.string(),
|
|
476
|
+
domain: z.string().min(1),
|
|
477
|
+
path: z.string().min(1),
|
|
478
|
+
expires: z.number(),
|
|
479
|
+
httpOnly: z.boolean(),
|
|
480
|
+
secure: z.boolean(),
|
|
481
|
+
sameSite: z.enum(['Strict', 'Lax', 'None']),
|
|
482
|
+
}).strict();
|
|
483
|
+
const StorageStateOriginSchema = z.object({
|
|
484
|
+
origin: StrictUrlSchema,
|
|
485
|
+
localStorage: z.array(z.object({
|
|
486
|
+
name: z.string().min(1),
|
|
487
|
+
value: z.string(),
|
|
488
|
+
}).strict()),
|
|
489
|
+
}).strict();
|
|
490
|
+
const StorageStateSchema = z.object({
|
|
491
|
+
cookies: z.array(StorageStateCookieSchema),
|
|
492
|
+
origins: z.array(StorageStateOriginSchema),
|
|
493
|
+
}).strict().refine((value) => value.cookies.length > 0 || value.origins.length > 0, 'storageState must contain at least one cookie or origin');
|
|
440
494
|
// `auth` enum removed: bootstrap is auto-detected from cookies / storageState /
|
|
441
495
|
// sessionStorage (injected into the browser context) and/or credentials
|
|
442
496
|
// (substituted into {{email}}/{{password}}/{{loginUrl}} placeholders inside
|
|
@@ -448,26 +502,26 @@ export const PreconditionSpecSchema = z.object({
|
|
|
448
502
|
email: z.string().optional(),
|
|
449
503
|
password: z.string().optional(),
|
|
450
504
|
loginUrl: z.string().optional(),
|
|
451
|
-
}).optional(),
|
|
452
|
-
storageState:
|
|
505
|
+
}).strict().optional(),
|
|
506
|
+
storageState: StorageStateSchema.optional(),
|
|
453
507
|
sessionStorage: z.record(z.string(), z.record(z.string(), z.string())).optional(),
|
|
454
508
|
cookies: z.array(cookieSchema).optional(),
|
|
455
|
-
});
|
|
509
|
+
}).strict();
|
|
456
510
|
// ── Artifact spec ───────────────────────────────────────────────────
|
|
457
511
|
export const ArtifactSpecSchema = z.object({
|
|
458
512
|
mediaMode: z.enum(['screenshot', 'clip', 'dom']),
|
|
459
513
|
format: z.object({
|
|
460
514
|
clipFormat: z.enum(['gif', 'mp4', 'both']).optional(),
|
|
461
515
|
screenshotFormat: z.enum(['png', 'jpeg']).optional(),
|
|
462
|
-
}).optional(),
|
|
516
|
+
}).strict().optional(),
|
|
463
517
|
cursorTheme: z.enum(['minimal', 'macos', 'windows']).optional(),
|
|
464
518
|
maxClipDurationSec: z.number().positive().optional(),
|
|
465
519
|
applyMockup: z.boolean().optional(),
|
|
466
520
|
applyStatusBar: z.boolean().optional(),
|
|
467
521
|
domOptions: z.object({
|
|
468
522
|
sanitize: z.boolean().optional(),
|
|
469
|
-
}).optional(),
|
|
470
|
-
});
|
|
523
|
+
}).strict().optional(),
|
|
524
|
+
}).strict();
|
|
471
525
|
// ── Full program ────────────────────────────────────────────────────
|
|
472
526
|
export const ExecutionProgramSchema = z.object({
|
|
473
527
|
presetId: z.string().min(1),
|
|
@@ -485,15 +539,17 @@ export const ExecutionProgramSchema = z.object({
|
|
|
485
539
|
compiledAt: z.string().datetime(),
|
|
486
540
|
compiledWith: z.string().optional(),
|
|
487
541
|
mockDataGroups: z.array(MockDataGroupSchema).optional(),
|
|
488
|
-
});
|
|
542
|
+
}).strict();
|
|
489
543
|
// ── Healer patch ────────────────────────────────────────────────────
|
|
490
544
|
export const HealerPatchSchema = z.object({
|
|
491
545
|
opcodeIndex: z.number().int().min(0),
|
|
492
546
|
originalOpcode: ExecutionOpcodeSchema,
|
|
493
547
|
replacementOpcodes: z.array(ExecutionOpcodeSchema).min(1).max(3),
|
|
548
|
+
patchType: z.literal('selector_patch').optional(),
|
|
549
|
+
interactionMode: z.enum(['default', 'keyboard', 'js_dispatch', 'coordinates']).optional(),
|
|
494
550
|
reason: z.string().min(1),
|
|
495
551
|
patchedAt: z.string().datetime(),
|
|
496
|
-
});
|
|
552
|
+
}).strict();
|
|
497
553
|
// ── Typed parse helpers ─────────────────────────────────────────────
|
|
498
554
|
export function parseProgram(data) {
|
|
499
555
|
return ExecutionProgramSchema.parse(data);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { AKTree, BrowserStorageState, BrowserSessionStorageState, VideoCursorTheme, VideoPageSignals } from './types.js';
|
|
8
8
|
/** Sentinel value that resolves to the current variant's locale or theme at runtime */
|
|
9
9
|
export declare const VARIANT_PLACEHOLDER: "$variant";
|
|
10
|
-
export declare const OPCODE_KINDS: readonly ["NAVIGATE", "DISMISS_OVERLAYS", "ASSERT_ROUTE", "ASSERT_SURFACE", "CLICK", "TYPE", "PRESS_KEY", "WAIT_FOR", "SET_LOCALE", "SET_THEME", "SCROLL", "CAPTURE_SCREENSHOT", "CAPTURE_DOM", "CAPTURE_FRAGMENT", "BEGIN_CLIP", "END_CLIP", "HOVER", "SELECT_OPTION", "CHECK", "DOUBLE_CLICK", "CLONE_ELEMENT", "INJECT_MOCK_DATA", "REMOVE_ELEMENT", "SET_ATTRIBUTE"];
|
|
10
|
+
export declare const OPCODE_KINDS: readonly ["NAVIGATE", "DISMISS_OVERLAYS", "ASSERT_ROUTE", "ASSERT_SURFACE", "CLICK", "TYPE", "PRESS_KEY", "WAIT_FOR", "SET_LOCALE", "SET_THEME", "SCROLL", "CAPTURE_SCREENSHOT", "CAPTURE_DOM", "CAPTURE_FRAGMENT", "BEGIN_CLIP", "END_CLIP", "HOVER", "SELECT_OPTION", "CHECK", "DOUBLE_CLICK", "DRAG", "CLONE_ELEMENT", "INJECT_MOCK_DATA", "REMOVE_ELEMENT", "SET_ATTRIBUTE"];
|
|
11
11
|
export type OpcodeKind = (typeof OPCODE_KINDS)[number];
|
|
12
12
|
/**
|
|
13
13
|
* Soft opcodes are non-blocking — if their action or postcondition fails at
|
|
@@ -94,7 +94,7 @@ export interface RecoveryPolicy {
|
|
|
94
94
|
useAltInteraction: boolean;
|
|
95
95
|
/** Reload the page and retry from last checkpoint. Default: false */
|
|
96
96
|
allowReload: boolean;
|
|
97
|
-
/** Allow LLM healer as last resort. Default:
|
|
97
|
+
/** Allow LLM healer as last resort. Default: false */
|
|
98
98
|
allowHealer: boolean;
|
|
99
99
|
}
|
|
100
100
|
export declare const DEFAULT_RECOVERY_POLICY: RecoveryPolicy;
|
|
@@ -356,6 +356,35 @@ export interface DoubleClickOpcode extends OpcodeBase {
|
|
|
356
356
|
fingerprint?: string;
|
|
357
357
|
selectorAlternates?: string[];
|
|
358
358
|
}
|
|
359
|
+
/**
|
|
360
|
+
* Drag an element from point A to point B with an animated cursor.
|
|
361
|
+
* During clip recordings, the cursor overlay glides from source to
|
|
362
|
+
* destination along a Bezier curve with press/release visual feedback.
|
|
363
|
+
*
|
|
364
|
+
* Destination is either another element (`toSelector` / `toTarget`) or a
|
|
365
|
+
* relative `offset` from the source center — use the offset form for
|
|
366
|
+
* sliders, canvas drawing, or any drag whose end point isn't a DOM node.
|
|
367
|
+
*/
|
|
368
|
+
export interface DragOpcode extends OpcodeBase {
|
|
369
|
+
kind: 'DRAG';
|
|
370
|
+
/** CSS selector of the source element (the one being dragged) */
|
|
371
|
+
selector: string;
|
|
372
|
+
/** Semantic fallback for the source element */
|
|
373
|
+
target?: SemanticTarget;
|
|
374
|
+
fingerprint?: string;
|
|
375
|
+
selectorAlternates?: string[];
|
|
376
|
+
/** CSS selector of the drop target element (mutually exclusive with `offset`) */
|
|
377
|
+
toSelector?: string;
|
|
378
|
+
/** Semantic fallback for the drop target */
|
|
379
|
+
toTarget?: SemanticTarget;
|
|
380
|
+
/** Alternative destination selectors tried in order */
|
|
381
|
+
toSelectorAlternates?: string[];
|
|
382
|
+
/** Absolute pixel offset from the source center. Use when the drop point isn't a DOM element (sliders, canvas). */
|
|
383
|
+
offset?: {
|
|
384
|
+
dx: number;
|
|
385
|
+
dy: number;
|
|
386
|
+
};
|
|
387
|
+
}
|
|
359
388
|
/**
|
|
360
389
|
* Duplicate a template element N times into a container. **Soft / non-blocking.**
|
|
361
390
|
* If the source or container selector is missing, the opcode is skipped and
|
|
@@ -452,7 +481,7 @@ export interface SetAttributeOpcode extends OpcodeBase {
|
|
|
452
481
|
/** Attribute value */
|
|
453
482
|
value: string;
|
|
454
483
|
}
|
|
455
|
-
export type ExecutionOpcode = NavigateOpcode | DismissOverlaysOpcode | AssertRouteOpcode | AssertSurfaceOpcode | ClickOpcode | TypeOpcode | PressKeyOpcode | WaitForOpcode | SetLocaleOpcode | SetThemeOpcode | ScrollOpcode | CaptureScreenshotOpcode | CaptureDomOpcode | CaptureFragmentOpcode | BeginClipOpcode | EndClipOpcode | HoverOpcode | SelectOptionOpcode | CheckOpcode | DoubleClickOpcode | CloneElementOpcode | InjectMockDataOpcode | RemoveElementOpcode | SetAttributeOpcode;
|
|
484
|
+
export type ExecutionOpcode = NavigateOpcode | DismissOverlaysOpcode | AssertRouteOpcode | AssertSurfaceOpcode | ClickOpcode | TypeOpcode | PressKeyOpcode | WaitForOpcode | SetLocaleOpcode | SetThemeOpcode | ScrollOpcode | CaptureScreenshotOpcode | CaptureDomOpcode | CaptureFragmentOpcode | BeginClipOpcode | EndClipOpcode | HoverOpcode | SelectOptionOpcode | CheckOpcode | DoubleClickOpcode | DragOpcode | CloneElementOpcode | InjectMockDataOpcode | RemoveElementOpcode | SetAttributeOpcode;
|
|
456
485
|
export interface VariantSpec {
|
|
457
486
|
id: string;
|
|
458
487
|
viewport: {
|
|
@@ -580,6 +609,10 @@ export interface HealerPatch {
|
|
|
580
609
|
originalOpcode: ExecutionOpcode;
|
|
581
610
|
/** The replacement opcode(s). Usually 1, max 3. */
|
|
582
611
|
replacementOpcodes: ExecutionOpcode[];
|
|
612
|
+
/** Bounded patch type used by the healer. */
|
|
613
|
+
patchType?: 'selector_patch';
|
|
614
|
+
/** Optional interaction mode requested by the healer. */
|
|
615
|
+
interactionMode?: 'default' | 'keyboard' | 'js_dispatch' | 'coordinates';
|
|
583
616
|
/** Why the healer made this change */
|
|
584
617
|
reason: string;
|
|
585
618
|
/** Timestamp */
|
|
@@ -837,6 +870,23 @@ export interface RuntimeAdapter {
|
|
|
837
870
|
}): Promise<void>;
|
|
838
871
|
check?(selector: string, checked: boolean): Promise<void>;
|
|
839
872
|
doubleClick?(selector: string): Promise<void>;
|
|
873
|
+
/**
|
|
874
|
+
* Drag the source element from point A to point B with an animated cursor
|
|
875
|
+
* when a clip is recording. Destination is either another element
|
|
876
|
+
* (`toSelector` / `toTarget`) or an `offset` from the source center.
|
|
877
|
+
*/
|
|
878
|
+
drag?(opts: {
|
|
879
|
+
selector?: string;
|
|
880
|
+
target?: SemanticTarget;
|
|
881
|
+
selectorAlternates?: string[];
|
|
882
|
+
toSelector?: string;
|
|
883
|
+
toTarget?: SemanticTarget;
|
|
884
|
+
toSelectorAlternates?: string[];
|
|
885
|
+
offset?: {
|
|
886
|
+
dx: number;
|
|
887
|
+
dy: number;
|
|
888
|
+
};
|
|
889
|
+
}): Promise<void>;
|
|
840
890
|
/** Clone an element N times into a container. Throws if either selector misses. */
|
|
841
891
|
cloneElement?(opts: {
|
|
842
892
|
sourceSelector: string;
|
package/dist/execution-types.js
CHANGED
|
@@ -28,6 +28,7 @@ export const OPCODE_KINDS = [
|
|
|
28
28
|
'SELECT_OPTION',
|
|
29
29
|
'CHECK',
|
|
30
30
|
'DOUBLE_CLICK',
|
|
31
|
+
'DRAG',
|
|
31
32
|
'CLONE_ELEMENT',
|
|
32
33
|
'INJECT_MOCK_DATA',
|
|
33
34
|
'REMOVE_ELEMENT',
|
|
@@ -53,7 +54,7 @@ export const DEFAULT_RECOVERY_POLICY = {
|
|
|
53
54
|
useSelectorMemory: true,
|
|
54
55
|
useAltInteraction: true,
|
|
55
56
|
allowReload: false,
|
|
56
|
-
allowHealer:
|
|
57
|
+
allowHealer: false,
|
|
57
58
|
};
|
|
58
59
|
// ── Artifact spec ───────────────────────────────────────────────────
|
|
59
60
|
export const MEDIA_MODES = ['screenshot', 'clip', 'dom'];
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export { DEFAULT_RECOVERY_POLICY, DEFAULT_CIRCUIT_BREAKER, VARIANT_PLACEHOLDER,
|
|
|
3
3
|
export { ExecutionProgramSchema, ExecutionOpcodeSchema, parseProgram, parseOpcode, safeParseProgramResult, MockDataSlotSchema, MockDataRowSchema, MockDataGroupSchema, } from './execution-schema.js';
|
|
4
4
|
export { callLLM } from './llm-provider.js';
|
|
5
5
|
export type { LLMProviderConfig, LLMCallResult } from './llm-provider.js';
|
|
6
|
+
export { normalizeAllowedOrigins, normalizeHttpOrigin, signExecutionProgramEnvelope, verifySignedExecutionProgramEnvelope, } from './program-signing.js';
|
|
7
|
+
export type { ProgramSecurityMetadata, SignedExecutionProgramEnvelope, } from './program-signing.js';
|
|
6
8
|
export { generateAltText } from './alt-text.js';
|
|
7
9
|
export type { AltTextResult, AltTextContext } from './alt-text.js';
|
|
8
10
|
export { logger, setOnLog, setOnScreenshot, emitScreenshot } from './logger.js';
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { DEFAULT_RECOVERY_POLICY, DEFAULT_CIRCUIT_BREAKER, VARIANT_PLACEHOLDER,
|
|
|
6
6
|
export { ExecutionProgramSchema, ExecutionOpcodeSchema, parseProgram, parseOpcode, safeParseProgramResult, MockDataSlotSchema, MockDataRowSchema, MockDataGroupSchema, } from './execution-schema.js';
|
|
7
7
|
// ── LLM-backed helpers (OpenAI, no browser) ─────────────────────────
|
|
8
8
|
export { callLLM } from './llm-provider.js';
|
|
9
|
+
export { normalizeAllowedOrigins, normalizeHttpOrigin, signExecutionProgramEnvelope, verifySignedExecutionProgramEnvelope, } from './program-signing.js';
|
|
9
10
|
export { generateAltText } from './alt-text.js';
|
|
10
11
|
// ── Shared utilities ────────────────────────────────────────────────
|
|
11
12
|
export { logger, setOnLog, setOnScreenshot, emitScreenshot } from './logger.js';
|
package/dist/llm-healer.d.ts
CHANGED
|
@@ -3,15 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Last-resort recovery: when all deterministic strategies fail,
|
|
5
5
|
* the healer asks an LLM to analyze the current page state and
|
|
6
|
-
* produce a
|
|
7
|
-
*
|
|
8
|
-
* Constraints:
|
|
9
|
-
* - Cannot change the preset's intention
|
|
10
|
-
* - Cannot change variant order
|
|
11
|
-
* - Cannot invent new capture targets
|
|
12
|
-
* - Cannot skip the failed opcode's postcondition
|
|
13
|
-
* - Max 1 LLM call per healing attempt
|
|
14
|
-
* - Max 3 healing attempts per run
|
|
6
|
+
* produce a bounded selector patch.
|
|
15
7
|
*/
|
|
16
8
|
import type { ExecutionOpcode, HealerPatch } from './execution-types.js';
|
|
17
9
|
import type { LLMCallResult } from './llm-provider.js';
|
|
@@ -49,7 +41,7 @@ export interface HealerLLMProvider {
|
|
|
49
41
|
}>;
|
|
50
42
|
}
|
|
51
43
|
/**
|
|
52
|
-
* The LLM Healer — a constrained agent that repairs failed
|
|
44
|
+
* The LLM Healer — a constrained agent that repairs failed selectors.
|
|
53
45
|
*/
|
|
54
46
|
export declare class LLMHealer {
|
|
55
47
|
private llmProvider;
|