autokap 1.0.7 → 1.0.8
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/cursors/macos.svg +4 -0
- package/assets/cursors/windows.svg +15 -0
- package/assets/skill/OPCODE-REFERENCE.md +607 -0
- package/assets/skill/README.md +39 -0
- package/assets/skill/SKILL.md +453 -468
- package/assets/skill/STUDIO-SKILL.md +476 -0
- package/assets/skill/references/examples.md +104 -0
- package/assets/skill/references/interactive-demo.md +225 -0
- package/assets/skill/references/mock-data.md +178 -0
- package/dist/action-verifier.d.ts +29 -0
- package/dist/action-verifier.js +133 -0
- package/dist/agent-action-recovery.d.ts +45 -0
- package/dist/agent-action-recovery.js +370 -0
- package/dist/agent-message-utils.d.ts +21 -0
- package/dist/agent-message-utils.js +77 -0
- package/dist/agent-url-utils.d.ts +30 -0
- package/dist/agent-url-utils.js +138 -0
- package/dist/agent.d.ts +92 -8
- package/dist/agent.js +2936 -781
- package/dist/ak-tree.d.ts +39 -0
- package/dist/ak-tree.js +368 -0
- package/dist/alt-text.d.ts +26 -0
- package/dist/alt-text.js +55 -0
- package/dist/auth-capture.d.ts +17 -0
- package/dist/auth-capture.js +164 -0
- package/dist/benchmark.d.ts +59 -0
- package/dist/benchmark.js +135 -0
- package/dist/browser-bar.d.ts +14 -6
- package/dist/browser-bar.js +145 -8
- package/dist/browser-pool.d.ts +7 -0
- package/dist/browser-pool.js +15 -5
- package/dist/browser-utils.d.ts +31 -0
- package/dist/browser-utils.js +97 -0
- package/dist/browser.d.ts +51 -1
- package/dist/browser.js +1481 -31
- package/dist/capture-alt-text.js +2 -1
- package/dist/capture-language-preflight.js +14 -0
- package/dist/capture-llm-page-identity.js +22 -10
- package/dist/capture-page-identity.d.ts +5 -7
- package/dist/capture-page-identity.js +211 -78
- package/dist/capture-preset-credentials.d.ts +50 -0
- package/dist/capture-preset-credentials.js +127 -0
- package/dist/capture-request-plan.d.ts +2 -2
- package/dist/capture-request-plan.js +64 -16
- package/dist/capture-run-optimizer.js +48 -33
- package/dist/capture-selector-memory.d.ts +5 -0
- package/dist/capture-selector-memory.js +18 -0
- package/dist/capture-strategy.d.ts +36 -0
- package/dist/capture-strategy.js +95 -0
- package/dist/capture-studio-sync.d.ts +1 -0
- package/dist/capture-studio-sync.js +9 -3
- package/dist/capture-surface-contract.d.ts +36 -0
- package/dist/capture-surface-contract.js +299 -0
- package/dist/capture-transition-engine.d.ts +28 -0
- package/dist/capture-transition-engine.js +292 -0
- package/dist/capture-variant-state.d.ts +2 -0
- package/dist/capture-variant-state.js +26 -0
- package/dist/capture-verification.d.ts +35 -0
- package/dist/capture-verification.js +95 -0
- package/dist/capture-viewport-lock.d.ts +48 -0
- package/dist/capture-viewport-lock.js +74 -0
- package/dist/circuit-breaker.d.ts +42 -0
- package/dist/circuit-breaker.js +119 -0
- package/dist/cli-config.d.ts +8 -1
- package/dist/cli-config.js +62 -6
- package/dist/cli-contract.d.ts +15 -0
- package/dist/cli-contract.js +167 -0
- package/dist/cli-runner-local.d.ts +12 -0
- package/dist/cli-runner-local.js +102 -0
- package/dist/cli-runner.d.ts +34 -0
- package/dist/cli-runner.js +433 -0
- package/dist/cli-utils.d.ts +0 -1
- package/dist/cli-utils.js +2 -5
- package/dist/cli.js +1005 -267
- package/dist/clip-orchestrator.js +9 -2
- package/dist/clip-postprocess.js +25 -16
- package/dist/cookie-dismiss.d.ts +2 -0
- package/dist/cookie-dismiss.js +48 -13
- package/dist/cost-logging.d.ts +8 -0
- package/dist/cost-logging.js +160 -46
- package/dist/cost-resolution-monitor.d.ts +16 -0
- package/dist/cost-resolution-monitor.js +34 -0
- package/dist/credential-templates.js +2 -2
- package/dist/cursor-overlay-script.d.ts +6 -0
- package/dist/cursor-overlay-script.js +169 -0
- package/dist/dom-css-purger.d.ts +65 -0
- package/dist/dom-css-purger.js +333 -0
- package/dist/dom-font-inliner.d.ts +45 -0
- package/dist/dom-font-inliner.js +148 -0
- package/dist/dom-patch-resolver.d.ts +52 -0
- package/dist/dom-patch-resolver.js +242 -0
- package/dist/dom-serializer.d.ts +82 -0
- package/dist/dom-serializer.js +378 -0
- package/dist/element-capture.d.ts +1 -41
- package/dist/element-capture.js +202 -446
- package/dist/env-validation.d.ts +5 -0
- package/dist/env-validation.js +29 -0
- package/dist/execution-schema.d.ts +4423 -0
- package/dist/execution-schema.js +507 -0
- package/dist/execution-types.d.ts +886 -0
- package/dist/execution-types.js +65 -0
- package/dist/fonts-loader.d.ts +14 -0
- package/dist/fonts-loader.js +55 -0
- package/dist/hybrid-navigator.js +12 -12
- package/dist/index.d.ts +9 -6
- package/dist/index.js +10 -4
- package/dist/legacy/agent-action-recovery.d.ts +45 -0
- package/dist/legacy/agent-action-recovery.js +370 -0
- package/dist/legacy/agent-message-utils.d.ts +21 -0
- package/dist/legacy/agent-message-utils.js +77 -0
- package/dist/legacy/agent-url-utils.d.ts +30 -0
- package/dist/legacy/agent-url-utils.js +138 -0
- package/dist/legacy/agent.d.ts +226 -0
- package/dist/legacy/agent.js +6666 -0
- package/dist/legacy/clip-orchestrator.d.ts +148 -0
- package/dist/legacy/clip-orchestrator.js +957 -0
- package/dist/legacy/credential-templates.d.ts +5 -0
- package/dist/legacy/credential-templates.js +60 -0
- package/dist/legacy/hybrid-navigator.d.ts +138 -0
- package/dist/legacy/hybrid-navigator.js +468 -0
- package/dist/legacy/llm-usage.d.ts +17 -0
- package/dist/legacy/llm-usage.js +45 -0
- package/dist/legacy/prompt-cache.d.ts +10 -0
- package/dist/legacy/prompt-cache.js +24 -0
- package/dist/legacy/prompts.d.ts +175 -0
- package/dist/legacy/prompts.js +1038 -0
- package/dist/legacy/tools.d.ts +4 -0
- package/dist/legacy/tools.js +216 -0
- package/dist/legacy/video-agent.d.ts +143 -0
- package/dist/legacy/video-agent.js +4788 -0
- package/dist/legacy/video-observation.d.ts +36 -0
- package/dist/legacy/video-observation.js +192 -0
- package/dist/legacy/video-planner.d.ts +12 -0
- package/dist/legacy/video-planner.js +501 -0
- package/dist/legacy/video-prompts.d.ts +37 -0
- package/dist/legacy/video-prompts.js +569 -0
- package/dist/legacy/video-tools.d.ts +3 -0
- package/dist/legacy/video-tools.js +59 -0
- package/dist/legacy/video-variant-state.d.ts +29 -0
- package/dist/legacy/video-variant-state.js +80 -0
- package/dist/legacy/vision-model.d.ts +17 -0
- package/dist/legacy/vision-model.js +74 -0
- package/dist/llm-healer.d.ts +63 -0
- package/dist/llm-healer.js +166 -0
- package/dist/llm-provider.d.ts +29 -0
- package/dist/llm-provider.js +80 -0
- package/dist/logger.d.ts +6 -2
- package/dist/logger.js +15 -1
- package/dist/mockup-html.js +35 -25
- package/dist/mockup.d.ts +95 -2
- package/dist/mockup.js +427 -166
- package/dist/mouse-animation.d.ts +2 -2
- package/dist/mouse-animation.js +34 -20
- package/dist/opcode-actions.d.ts +42 -0
- package/dist/opcode-actions.js +511 -0
- package/dist/opcode-runner.d.ts +51 -0
- package/dist/opcode-runner.js +770 -0
- package/dist/openrouter-client.d.ts +40 -0
- package/dist/openrouter-client.js +16 -0
- package/dist/overlay-engine.d.ts +24 -0
- package/dist/overlay-engine.js +176 -0
- package/dist/postcondition.d.ts +16 -0
- package/dist/postcondition.js +269 -0
- package/dist/program-patcher.d.ts +25 -0
- package/dist/program-patcher.js +44 -0
- package/dist/prompts.d.ts +13 -5
- package/dist/prompts.js +224 -351
- package/dist/provider-config.d.ts +12 -0
- package/dist/provider-config.js +15 -0
- package/dist/recovery-chain.d.ts +37 -0
- package/dist/recovery-chain.js +350 -0
- package/dist/remote-browser.d.ts +28 -4
- package/dist/remote-browser.js +60 -5
- package/dist/safari-browser-bar.d.ts +15 -0
- package/dist/safari-browser-bar.js +95 -0
- package/dist/safari-toolbar-asset.d.ts +15 -0
- package/dist/safari-toolbar-asset.js +12 -0
- package/dist/security.d.ts +2 -1
- package/dist/security.js +49 -10
- package/dist/selector-resolver.d.ts +34 -0
- package/dist/selector-resolver.js +181 -0
- package/dist/semantic-resolver.d.ts +35 -0
- package/dist/semantic-resolver.js +161 -0
- package/dist/server-capture-runtime.d.ts +5 -3
- package/dist/server-capture-runtime.js +42 -95
- package/dist/server-credit-usage.d.ts +2 -2
- package/dist/server-project-webhooks.d.ts +15 -1
- package/dist/server-project-webhooks.js +34 -8
- package/dist/server-screenshot-watermark.js +27 -5
- package/dist/session-profile.js +164 -1
- package/dist/sf-pro-symbols.d.ts +1 -0
- package/dist/sf-pro-symbols.js +55 -0
- package/dist/skill-packaging.d.ts +28 -0
- package/dist/skill-packaging.js +169 -0
- package/dist/smart-wait.d.ts +27 -0
- package/dist/smart-wait.js +81 -0
- package/dist/status-bar-render.d.ts +20 -0
- package/dist/status-bar-render.js +410 -0
- package/dist/status-bar.d.ts +9 -0
- package/dist/status-bar.js +298 -14
- package/dist/svg-browser-bar.d.ts +33 -0
- package/dist/svg-browser-bar.js +206 -0
- package/dist/svg-status-bar.d.ts +36 -0
- package/dist/svg-status-bar.js +597 -0
- package/dist/svg-text.d.ts +61 -0
- package/dist/svg-text.js +118 -0
- package/dist/tools.js +89 -451
- package/dist/types.d.ts +240 -5
- package/dist/types.js +23 -1
- package/dist/v2/action-verifier.d.ts +29 -0
- package/dist/v2/action-verifier.js +133 -0
- package/dist/v2/alt-text.d.ts +26 -0
- package/dist/v2/alt-text.js +55 -0
- package/dist/v2/benchmark.d.ts +59 -0
- package/dist/v2/benchmark.js +135 -0
- package/dist/v2/capture-strategy.d.ts +30 -0
- package/dist/v2/capture-strategy.js +67 -0
- package/dist/v2/capture-verification.d.ts +35 -0
- package/dist/v2/capture-verification.js +95 -0
- package/dist/v2/circuit-breaker.d.ts +42 -0
- package/dist/v2/circuit-breaker.js +119 -0
- package/dist/v2/cli-runner-local.d.ts +11 -0
- package/dist/v2/cli-runner-local.js +91 -0
- package/dist/v2/cli-runner.d.ts +34 -0
- package/dist/v2/cli-runner.js +300 -0
- package/dist/v2/compiler-prompts.d.ts +27 -0
- package/dist/v2/compiler-prompts.js +123 -0
- package/dist/v2/compiler.d.ts +37 -0
- package/dist/v2/compiler.js +147 -0
- package/dist/v2/explorer.d.ts +41 -0
- package/dist/v2/explorer.js +56 -0
- package/dist/v2/index.d.ts +37 -0
- package/dist/v2/index.js +31 -0
- package/dist/v2/llm-healer.d.ts +62 -0
- package/dist/v2/llm-healer.js +166 -0
- package/dist/v2/llm-provider.d.ts +29 -0
- package/dist/v2/llm-provider.js +80 -0
- package/dist/v2/opcode-runner.d.ts +47 -0
- package/dist/v2/opcode-runner.js +634 -0
- package/dist/v2/overlay-engine.d.ts +24 -0
- package/dist/v2/overlay-engine.js +150 -0
- package/dist/v2/postcondition.d.ts +16 -0
- package/dist/v2/postcondition.js +249 -0
- package/dist/v2/program-patcher.d.ts +25 -0
- package/dist/v2/program-patcher.js +44 -0
- package/dist/v2/recovery-chain.d.ts +30 -0
- package/dist/v2/recovery-chain.js +368 -0
- package/dist/v2/schema.d.ts +2580 -0
- package/dist/v2/schema.js +295 -0
- package/dist/v2/selector-resolver.d.ts +34 -0
- package/dist/v2/selector-resolver.js +181 -0
- package/dist/v2/semantic-resolver.d.ts +35 -0
- package/dist/v2/semantic-resolver.js +161 -0
- package/dist/v2/smart-wait.d.ts +27 -0
- package/dist/v2/smart-wait.js +81 -0
- package/dist/v2/types.d.ts +444 -0
- package/dist/v2/types.js +19 -0
- package/dist/v2/web-playwright-local.d.ts +69 -0
- package/dist/v2/web-playwright-local.js +392 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/video-agent.js +18 -13
- package/dist/video-planner.js +2 -1
- package/dist/video-prompts.js +3 -3
- package/dist/web-playwright-local.d.ts +126 -0
- package/dist/web-playwright-local.js +819 -0
- package/dist/ws-auth.js +4 -1
- package/dist/ws-broadcast.d.ts +34 -0
- package/dist/ws-broadcast.js +85 -0
- package/dist/ws-connection-limits.d.ts +12 -0
- package/dist/ws-connection-limits.js +44 -0
- package/dist/ws-handler-utils.d.ts +32 -0
- package/dist/ws-handler-utils.js +139 -0
- package/dist/ws-handler.js +294 -164
- package/dist/ws-metrics-server.d.ts +9 -0
- package/dist/ws-metrics-server.js +31 -0
- package/dist/ws-server.js +41 -1
- package/package.json +51 -34
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Zod Validation Schemas
|
|
3
|
+
*
|
|
4
|
+
* Validates ExecutionProgram at compile output (server) and CLI input boundaries.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
// ── Postcondition ───────────────────────────────────────────────────
|
|
8
|
+
export const PostconditionSpecSchema = z.object({
|
|
9
|
+
type: z.enum([
|
|
10
|
+
'route_matches',
|
|
11
|
+
'element_visible',
|
|
12
|
+
'element_absent',
|
|
13
|
+
'text_contains',
|
|
14
|
+
'overlay_dismissed',
|
|
15
|
+
'screenshot_stable',
|
|
16
|
+
'any_change',
|
|
17
|
+
'always',
|
|
18
|
+
]),
|
|
19
|
+
pattern: z.string().optional(),
|
|
20
|
+
selector: z.string().optional(),
|
|
21
|
+
text: z.string().optional(),
|
|
22
|
+
threshold: z.number().min(0).max(1).optional(),
|
|
23
|
+
waitMs: z.number().int().positive().optional(),
|
|
24
|
+
}).superRefine((value, ctx) => {
|
|
25
|
+
if (value.type === 'route_matches' && !value.pattern) {
|
|
26
|
+
ctx.addIssue({
|
|
27
|
+
code: z.ZodIssueCode.custom,
|
|
28
|
+
message: 'route_matches postconditions require `pattern`',
|
|
29
|
+
path: ['pattern'],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (['element_visible', 'element_absent', 'text_contains'].includes(value.type) && !value.selector) {
|
|
33
|
+
ctx.addIssue({
|
|
34
|
+
code: z.ZodIssueCode.custom,
|
|
35
|
+
message: `${value.type} postconditions require \`selector\``,
|
|
36
|
+
path: ['selector'],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (value.type === 'text_contains' && !value.text) {
|
|
40
|
+
ctx.addIssue({
|
|
41
|
+
code: z.ZodIssueCode.custom,
|
|
42
|
+
message: 'text_contains postconditions require `text`',
|
|
43
|
+
path: ['text'],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// ── Recovery policy ─────────────────────────────────────────────────
|
|
48
|
+
export const RecoveryPolicySchema = z.object({
|
|
49
|
+
retries: z.number().int().min(0).max(10),
|
|
50
|
+
useSelectorMemory: z.boolean(),
|
|
51
|
+
useAltInteraction: z.boolean(),
|
|
52
|
+
allowReload: z.boolean(),
|
|
53
|
+
allowHealer: z.boolean(),
|
|
54
|
+
});
|
|
55
|
+
// ── Opcode base fields ──────────────────────────────────────────────
|
|
56
|
+
const opcodeBase = {
|
|
57
|
+
description: z.string().min(1),
|
|
58
|
+
postcondition: PostconditionSpecSchema,
|
|
59
|
+
recovery: RecoveryPolicySchema,
|
|
60
|
+
timeoutMs: z.number().int().positive(),
|
|
61
|
+
maxFailures: z.number().int().positive(),
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Strict URL validator: rejects schemes without a host (e.g. `"https://"`),
|
|
65
|
+
* which Zod's built-in `.url()` regex accepts but Playwright crashes on at
|
|
66
|
+
* navigation time. We use the WHATWG `URL` parser as the source of truth.
|
|
67
|
+
*/
|
|
68
|
+
const StrictUrlSchema = z.string().min(1).refine((value) => {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = new URL(value);
|
|
71
|
+
return Boolean(parsed.host);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}, {
|
|
77
|
+
message: 'Must be a fully-qualified URL with a host (e.g. "https://app.example.com/dashboard"), not a bare scheme like "https://"',
|
|
78
|
+
});
|
|
79
|
+
// ── Individual opcode schemas ───────────────────────────────────────
|
|
80
|
+
const NavigateOpcodeSchema = z.object({
|
|
81
|
+
kind: z.literal('NAVIGATE'),
|
|
82
|
+
...opcodeBase,
|
|
83
|
+
url: StrictUrlSchema,
|
|
84
|
+
});
|
|
85
|
+
const DismissOverlaysOpcodeSchema = z.object({
|
|
86
|
+
kind: z.literal('DISMISS_OVERLAYS'),
|
|
87
|
+
...opcodeBase,
|
|
88
|
+
});
|
|
89
|
+
const AssertRouteOpcodeSchema = z.object({
|
|
90
|
+
kind: z.literal('ASSERT_ROUTE'),
|
|
91
|
+
...opcodeBase,
|
|
92
|
+
urlPattern: z.string().min(1),
|
|
93
|
+
});
|
|
94
|
+
const AssertSurfaceOpcodeSchema = z.object({
|
|
95
|
+
kind: z.literal('ASSERT_SURFACE'),
|
|
96
|
+
...opcodeBase,
|
|
97
|
+
selectors: z.array(z.string().min(1)).min(1),
|
|
98
|
+
matchAll: z.boolean(),
|
|
99
|
+
});
|
|
100
|
+
const SemanticTargetSchema = z.object({
|
|
101
|
+
text: z.string().optional(),
|
|
102
|
+
role: z.string().optional(),
|
|
103
|
+
label: z.string().optional(),
|
|
104
|
+
near: z.string().optional(),
|
|
105
|
+
placeholder: z.string().optional(),
|
|
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');
|
|
108
|
+
const ClickOpcodeSchema = z.object({
|
|
109
|
+
kind: z.literal('CLICK'),
|
|
110
|
+
...opcodeBase,
|
|
111
|
+
selector: z.string().min(1),
|
|
112
|
+
target: SemanticTargetSchema.optional(),
|
|
113
|
+
button: z.enum(['right', 'middle']).optional(),
|
|
114
|
+
fingerprint: z.string().optional(),
|
|
115
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
116
|
+
});
|
|
117
|
+
const TypeOpcodeSchema = z.object({
|
|
118
|
+
kind: z.literal('TYPE'),
|
|
119
|
+
...opcodeBase,
|
|
120
|
+
selector: z.string().min(1),
|
|
121
|
+
target: SemanticTargetSchema.optional(),
|
|
122
|
+
text: z.string(),
|
|
123
|
+
textByLocale: z.record(z.string().min(1), z.string()).optional(),
|
|
124
|
+
clearFirst: z.boolean(),
|
|
125
|
+
fingerprint: z.string().optional(),
|
|
126
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
127
|
+
});
|
|
128
|
+
const PressKeyOpcodeSchema = z.object({
|
|
129
|
+
kind: z.literal('PRESS_KEY'),
|
|
130
|
+
...opcodeBase,
|
|
131
|
+
key: z.string().min(1),
|
|
132
|
+
});
|
|
133
|
+
const WaitForOpcodeSchema = z.object({
|
|
134
|
+
kind: z.literal('WAIT_FOR'),
|
|
135
|
+
...opcodeBase,
|
|
136
|
+
selector: z.string().min(1).optional(),
|
|
137
|
+
target: SemanticTargetSchema.optional(),
|
|
138
|
+
state: z.enum(['visible', 'attached']),
|
|
139
|
+
}).superRefine((value, ctx) => {
|
|
140
|
+
if (!value.selector && !value.target) {
|
|
141
|
+
ctx.addIssue({
|
|
142
|
+
code: z.ZodIssueCode.custom,
|
|
143
|
+
message: 'WAIT_FOR requires either `selector` or `target`',
|
|
144
|
+
path: ['selector'],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
const storageHintSchema = z.object({
|
|
149
|
+
storage: z.enum(['localStorage', 'sessionStorage', 'cookie']),
|
|
150
|
+
key: z.string().min(1),
|
|
151
|
+
value: z.string(),
|
|
152
|
+
});
|
|
153
|
+
const SetLocaleOpcodeSchema = z.object({
|
|
154
|
+
kind: z.literal('SET_LOCALE'),
|
|
155
|
+
...opcodeBase,
|
|
156
|
+
locale: z.string().min(1),
|
|
157
|
+
method: z.enum(['browser_context', 'ui_interaction', 'storage']),
|
|
158
|
+
selector: z.string().optional(),
|
|
159
|
+
storageHints: z.array(storageHintSchema).optional(),
|
|
160
|
+
}).superRefine((value, ctx) => {
|
|
161
|
+
if (value.method === 'ui_interaction' && !value.selector) {
|
|
162
|
+
ctx.addIssue({
|
|
163
|
+
code: z.ZodIssueCode.custom,
|
|
164
|
+
message: 'SET_LOCALE with `ui_interaction` requires `selector`',
|
|
165
|
+
path: ['selector'],
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (value.method === 'storage' && (!value.storageHints || value.storageHints.length === 0)) {
|
|
169
|
+
ctx.addIssue({
|
|
170
|
+
code: z.ZodIssueCode.custom,
|
|
171
|
+
message: 'SET_LOCALE with `storage` requires at least one `storageHints` entry',
|
|
172
|
+
path: ['storageHints'],
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
const SetThemeOpcodeSchema = z.object({
|
|
177
|
+
kind: z.literal('SET_THEME'),
|
|
178
|
+
...opcodeBase,
|
|
179
|
+
theme: z.enum(['light', 'dark', '$variant']),
|
|
180
|
+
method: z.enum(['color_scheme', 'ui_interaction', 'storage']),
|
|
181
|
+
selector: z.string().optional(),
|
|
182
|
+
storageHints: z.array(storageHintSchema).optional(),
|
|
183
|
+
}).superRefine((value, ctx) => {
|
|
184
|
+
if (value.method === 'ui_interaction' && !value.selector) {
|
|
185
|
+
ctx.addIssue({
|
|
186
|
+
code: z.ZodIssueCode.custom,
|
|
187
|
+
message: 'SET_THEME with `ui_interaction` requires `selector`',
|
|
188
|
+
path: ['selector'],
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (value.method === 'storage' && (!value.storageHints || value.storageHints.length === 0)) {
|
|
192
|
+
ctx.addIssue({
|
|
193
|
+
code: z.ZodIssueCode.custom,
|
|
194
|
+
message: 'SET_THEME with `storage` requires at least one `storageHints` entry',
|
|
195
|
+
path: ['storageHints'],
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
const ScrollOpcodeSchema = z.object({
|
|
200
|
+
kind: z.literal('SCROLL'),
|
|
201
|
+
...opcodeBase,
|
|
202
|
+
direction: z.enum(['up', 'down', 'left', 'right']),
|
|
203
|
+
amount: z.number().int().positive().optional(),
|
|
204
|
+
targetSelector: z.string().optional(),
|
|
205
|
+
target: SemanticTargetSchema.optional(),
|
|
206
|
+
});
|
|
207
|
+
const CaptureScreenshotOpcodeSchema = z.object({
|
|
208
|
+
kind: z.literal('CAPTURE_SCREENSHOT'),
|
|
209
|
+
...opcodeBase,
|
|
210
|
+
captureId: z.string().optional(),
|
|
211
|
+
captureName: z.string().optional(),
|
|
212
|
+
elementSelector: z.string().optional(),
|
|
213
|
+
});
|
|
214
|
+
const CaptureDomOpcodeSchema = z.object({
|
|
215
|
+
kind: z.literal('CAPTURE_DOM'),
|
|
216
|
+
...opcodeBase,
|
|
217
|
+
stateName: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, 'stateName must be kebab-case'),
|
|
218
|
+
selector: z.string().min(1).optional(),
|
|
219
|
+
});
|
|
220
|
+
const CaptureFragmentOpcodeSchema = z.object({
|
|
221
|
+
kind: z.literal('CAPTURE_FRAGMENT'),
|
|
222
|
+
...opcodeBase,
|
|
223
|
+
fragmentName: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, 'fragmentName must be kebab-case'),
|
|
224
|
+
// Variants let the same fragment be captured in multiple states (e.g.
|
|
225
|
+
// default / purple-bg / text-bottom). Defaults to `'default'` when omitted.
|
|
226
|
+
// Player swaps variants in place via parentNode.replaceChild so the
|
|
227
|
+
// surrounding DOM keeps its scroll position, focus, and sibling layout.
|
|
228
|
+
variantName: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, 'variantName must be kebab-case').optional(),
|
|
229
|
+
parentState: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, 'parentState must be kebab-case'),
|
|
230
|
+
selector: z.string().min(1),
|
|
231
|
+
triggerSelector: z.string().min(1).optional(),
|
|
232
|
+
mountStrategy: z.string().min(1).optional(),
|
|
233
|
+
mountTargetSelector: z.string().min(1).optional(),
|
|
234
|
+
});
|
|
235
|
+
const BeginClipOpcodeSchema = z.object({
|
|
236
|
+
kind: z.literal('BEGIN_CLIP'),
|
|
237
|
+
...opcodeBase,
|
|
238
|
+
clipId: z.string().optional(),
|
|
239
|
+
clipName: z.string().optional(),
|
|
240
|
+
});
|
|
241
|
+
const EndClipOpcodeSchema = z.object({
|
|
242
|
+
kind: z.literal('END_CLIP'),
|
|
243
|
+
...opcodeBase,
|
|
244
|
+
clipId: z.string().optional(),
|
|
245
|
+
clipName: z.string().optional(),
|
|
246
|
+
});
|
|
247
|
+
const HoverOpcodeSchema = z.object({
|
|
248
|
+
kind: z.literal('HOVER'),
|
|
249
|
+
...opcodeBase,
|
|
250
|
+
selector: z.string().min(1),
|
|
251
|
+
target: SemanticTargetSchema.optional(),
|
|
252
|
+
fingerprint: z.string().optional(),
|
|
253
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
254
|
+
});
|
|
255
|
+
const SelectOptionOpcodeSchema = z.object({
|
|
256
|
+
kind: z.literal('SELECT_OPTION'),
|
|
257
|
+
...opcodeBase,
|
|
258
|
+
selector: z.string().min(1),
|
|
259
|
+
target: SemanticTargetSchema.optional(),
|
|
260
|
+
optionLabel: z.string().optional(),
|
|
261
|
+
optionValue: z.string().optional(),
|
|
262
|
+
optionIndex: z.number().int().min(0).optional(),
|
|
263
|
+
fingerprint: z.string().optional(),
|
|
264
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
265
|
+
}).superRefine((value, ctx) => {
|
|
266
|
+
if (value.optionLabel === undefined && value.optionValue === undefined && value.optionIndex === undefined) {
|
|
267
|
+
ctx.addIssue({
|
|
268
|
+
code: z.ZodIssueCode.custom,
|
|
269
|
+
message: 'SELECT_OPTION requires at least one of optionLabel, optionValue, or optionIndex',
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
const CheckOpcodeSchema = z.object({
|
|
274
|
+
kind: z.literal('CHECK'),
|
|
275
|
+
...opcodeBase,
|
|
276
|
+
selector: z.string().min(1),
|
|
277
|
+
target: SemanticTargetSchema.optional(),
|
|
278
|
+
checked: z.boolean(),
|
|
279
|
+
fingerprint: z.string().optional(),
|
|
280
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
281
|
+
});
|
|
282
|
+
const DoubleClickOpcodeSchema = z.object({
|
|
283
|
+
kind: z.literal('DOUBLE_CLICK'),
|
|
284
|
+
...opcodeBase,
|
|
285
|
+
selector: z.string().min(1),
|
|
286
|
+
target: SemanticTargetSchema.optional(),
|
|
287
|
+
fingerprint: z.string().optional(),
|
|
288
|
+
selectorAlternates: z.array(z.string().min(1)).optional(),
|
|
289
|
+
});
|
|
290
|
+
// ── Mock data opcodes (soft / non-blocking) ─────────────────────────
|
|
291
|
+
const CloneElementOpcodeSchema = z.object({
|
|
292
|
+
kind: z.literal('CLONE_ELEMENT'),
|
|
293
|
+
...opcodeBase,
|
|
294
|
+
sourceSelector: z.string().min(1),
|
|
295
|
+
containerSelector: z.string().min(1),
|
|
296
|
+
count: z.number().int().min(1).max(500),
|
|
297
|
+
removeSource: z.boolean().optional(),
|
|
298
|
+
});
|
|
299
|
+
const InjectMockDataOpcodeSchema = z.object({
|
|
300
|
+
kind: z.literal('INJECT_MOCK_DATA'),
|
|
301
|
+
...opcodeBase,
|
|
302
|
+
groupName: z.string().min(1),
|
|
303
|
+
// Clone fields
|
|
304
|
+
containerSelector: z.string().min(1).optional(),
|
|
305
|
+
templateSelector: z.string().min(1).optional(),
|
|
306
|
+
count: z.number().int().min(1).max(500).optional(),
|
|
307
|
+
removeTemplate: z.boolean().optional(),
|
|
308
|
+
slotMappings: z.array(z.object({
|
|
309
|
+
slot: z.string().min(1),
|
|
310
|
+
selector: z.string().min(1),
|
|
311
|
+
attribute: z.string().min(1).optional(),
|
|
312
|
+
})).min(1).optional(),
|
|
313
|
+
// Trigger fields
|
|
314
|
+
inputSelector: z.string().min(1).optional(),
|
|
315
|
+
triggerSelector: z.string().min(1).optional(),
|
|
316
|
+
}).superRefine((value, ctx) => {
|
|
317
|
+
// The two delivery mechanisms are independent and additive. An opcode must
|
|
318
|
+
// declare AT LEAST ONE complete mechanism — typically both — but if only
|
|
319
|
+
// one is provided that's still valid.
|
|
320
|
+
const hasClone = Boolean(value.containerSelector && value.slotMappings && value.slotMappings.length > 0);
|
|
321
|
+
const hasTrigger = Boolean(value.inputSelector && value.triggerSelector);
|
|
322
|
+
if (!hasClone && !hasTrigger) {
|
|
323
|
+
ctx.addIssue({
|
|
324
|
+
code: z.ZodIssueCode.custom,
|
|
325
|
+
message: 'INJECT_MOCK_DATA must declare at least one mechanism: clone (containerSelector + slotMappings) and/or trigger (inputSelector + triggerSelector). Typically both should be provided.',
|
|
326
|
+
path: ['containerSelector'],
|
|
327
|
+
});
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
// Partial-clone validation: if some clone fields are present, they all must
|
|
331
|
+
// make sense together. removeTemplate is optional and defaults to false.
|
|
332
|
+
if (value.containerSelector && (!value.slotMappings || value.slotMappings.length === 0)) {
|
|
333
|
+
ctx.addIssue({
|
|
334
|
+
code: z.ZodIssueCode.custom,
|
|
335
|
+
message: 'INJECT_MOCK_DATA: when `containerSelector` is provided, at least one entry in `slotMappings` is required',
|
|
336
|
+
path: ['slotMappings'],
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (value.slotMappings && value.slotMappings.length > 0 && !value.containerSelector) {
|
|
340
|
+
ctx.addIssue({
|
|
341
|
+
code: z.ZodIssueCode.custom,
|
|
342
|
+
message: 'INJECT_MOCK_DATA: when `slotMappings` is provided, `containerSelector` is required',
|
|
343
|
+
path: ['containerSelector'],
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
// Partial-trigger validation: trigger is all-or-nothing.
|
|
347
|
+
if (value.inputSelector && !value.triggerSelector) {
|
|
348
|
+
ctx.addIssue({
|
|
349
|
+
code: z.ZodIssueCode.custom,
|
|
350
|
+
message: 'INJECT_MOCK_DATA: when `inputSelector` is provided, `triggerSelector` is required',
|
|
351
|
+
path: ['triggerSelector'],
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
if (value.triggerSelector && !value.inputSelector) {
|
|
355
|
+
ctx.addIssue({
|
|
356
|
+
code: z.ZodIssueCode.custom,
|
|
357
|
+
message: 'INJECT_MOCK_DATA: when `triggerSelector` is provided, `inputSelector` is required',
|
|
358
|
+
path: ['inputSelector'],
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
const RemoveElementOpcodeSchema = z.object({
|
|
363
|
+
kind: z.literal('REMOVE_ELEMENT'),
|
|
364
|
+
...opcodeBase,
|
|
365
|
+
selector: z.string().min(1),
|
|
366
|
+
});
|
|
367
|
+
const SetAttributeOpcodeSchema = z.object({
|
|
368
|
+
kind: z.literal('SET_ATTRIBUTE'),
|
|
369
|
+
...opcodeBase,
|
|
370
|
+
selector: z.string().min(1),
|
|
371
|
+
attribute: z.string().min(1),
|
|
372
|
+
value: z.string(),
|
|
373
|
+
});
|
|
374
|
+
// ── Discriminated union ─────────────────────────────────────────────
|
|
375
|
+
export const ExecutionOpcodeSchema = z.discriminatedUnion('kind', [
|
|
376
|
+
NavigateOpcodeSchema,
|
|
377
|
+
DismissOverlaysOpcodeSchema,
|
|
378
|
+
AssertRouteOpcodeSchema,
|
|
379
|
+
AssertSurfaceOpcodeSchema,
|
|
380
|
+
ClickOpcodeSchema,
|
|
381
|
+
TypeOpcodeSchema,
|
|
382
|
+
PressKeyOpcodeSchema,
|
|
383
|
+
WaitForOpcodeSchema,
|
|
384
|
+
SetLocaleOpcodeSchema,
|
|
385
|
+
SetThemeOpcodeSchema,
|
|
386
|
+
ScrollOpcodeSchema,
|
|
387
|
+
CaptureScreenshotOpcodeSchema,
|
|
388
|
+
CaptureDomOpcodeSchema,
|
|
389
|
+
CaptureFragmentOpcodeSchema,
|
|
390
|
+
BeginClipOpcodeSchema,
|
|
391
|
+
EndClipOpcodeSchema,
|
|
392
|
+
HoverOpcodeSchema,
|
|
393
|
+
SelectOptionOpcodeSchema,
|
|
394
|
+
CheckOpcodeSchema,
|
|
395
|
+
DoubleClickOpcodeSchema,
|
|
396
|
+
CloneElementOpcodeSchema,
|
|
397
|
+
InjectMockDataOpcodeSchema,
|
|
398
|
+
RemoveElementOpcodeSchema,
|
|
399
|
+
SetAttributeOpcodeSchema,
|
|
400
|
+
]);
|
|
401
|
+
// ── Mock data group ─────────────────────────────────────────────────
|
|
402
|
+
export const MockDataSlotSchema = z.object({
|
|
403
|
+
name: z.string().min(1),
|
|
404
|
+
description: z.string(),
|
|
405
|
+
// Free-form hint string. The dashboard editor recognizes a small set of
|
|
406
|
+
// canonical values (`text`, `number`, `image`, `color`, `date`, `url`)
|
|
407
|
+
// and falls back to a plain text input for everything else, so any
|
|
408
|
+
// descriptive label is safe here. See `inputTypeForHint()` in
|
|
409
|
+
// web/components/mock-data-editor.tsx.
|
|
410
|
+
hint: z.string().optional(),
|
|
411
|
+
});
|
|
412
|
+
export const MockDataRowSchema = z.record(z.string(), z.string());
|
|
413
|
+
export const MockDataGroupSchema = z.object({
|
|
414
|
+
name: z.string().min(1),
|
|
415
|
+
description: z.string(),
|
|
416
|
+
slots: z.array(MockDataSlotSchema).min(1),
|
|
417
|
+
defaultValues: z.array(MockDataRowSchema),
|
|
418
|
+
replaceExisting: z.boolean().optional(),
|
|
419
|
+
});
|
|
420
|
+
// ── Variant & precondition ──────────────────────────────────────────
|
|
421
|
+
export const VariantSpecSchema = z.object({
|
|
422
|
+
id: z.string().min(1),
|
|
423
|
+
viewport: z.object({
|
|
424
|
+
width: z.number().int().positive(),
|
|
425
|
+
height: z.number().int().positive(),
|
|
426
|
+
}),
|
|
427
|
+
deviceScaleFactor: z.number().positive().optional(),
|
|
428
|
+
locale: z.string().optional(),
|
|
429
|
+
theme: z.enum(['light', 'dark']).optional(),
|
|
430
|
+
targetId: z.string().optional(),
|
|
431
|
+
targetLabel: z.string().optional(),
|
|
432
|
+
deviceFrame: z.string().optional(),
|
|
433
|
+
});
|
|
434
|
+
const cookieSchema = z.object({
|
|
435
|
+
name: z.string().min(1),
|
|
436
|
+
value: z.string(),
|
|
437
|
+
domain: z.string().min(1),
|
|
438
|
+
path: z.string().optional(),
|
|
439
|
+
});
|
|
440
|
+
// `auth` enum removed: bootstrap is auto-detected from cookies / storageState /
|
|
441
|
+
// sessionStorage (injected into the browser context) and/or credentials
|
|
442
|
+
// (substituted into {{email}}/{{password}}/{{loginUrl}} placeholders inside
|
|
443
|
+
// opcodes). Old programs carrying an `auth` field still parse — Zod strips
|
|
444
|
+
// unknown keys silently — and the runtime ignores it.
|
|
445
|
+
export const PreconditionSpecSchema = z.object({
|
|
446
|
+
credentialsId: z.string().optional(),
|
|
447
|
+
credentials: z.object({
|
|
448
|
+
email: z.string().optional(),
|
|
449
|
+
password: z.string().optional(),
|
|
450
|
+
loginUrl: z.string().optional(),
|
|
451
|
+
}).optional(),
|
|
452
|
+
storageState: z.any().optional(),
|
|
453
|
+
sessionStorage: z.record(z.string(), z.record(z.string(), z.string())).optional(),
|
|
454
|
+
cookies: z.array(cookieSchema).optional(),
|
|
455
|
+
});
|
|
456
|
+
// ── Artifact spec ───────────────────────────────────────────────────
|
|
457
|
+
export const ArtifactSpecSchema = z.object({
|
|
458
|
+
mediaMode: z.enum(['screenshot', 'clip', 'dom']),
|
|
459
|
+
format: z.object({
|
|
460
|
+
clipFormat: z.enum(['gif', 'mp4', 'both']).optional(),
|
|
461
|
+
screenshotFormat: z.enum(['png', 'jpeg']).optional(),
|
|
462
|
+
}).optional(),
|
|
463
|
+
cursorTheme: z.enum(['minimal', 'macos', 'windows']).optional(),
|
|
464
|
+
maxClipDurationSec: z.number().positive().optional(),
|
|
465
|
+
applyMockup: z.boolean().optional(),
|
|
466
|
+
applyStatusBar: z.boolean().optional(),
|
|
467
|
+
domOptions: z.object({
|
|
468
|
+
sanitize: z.boolean().optional(),
|
|
469
|
+
}).optional(),
|
|
470
|
+
});
|
|
471
|
+
// ── Full program ────────────────────────────────────────────────────
|
|
472
|
+
export const ExecutionProgramSchema = z.object({
|
|
473
|
+
presetId: z.string().min(1),
|
|
474
|
+
programVersion: z.number().int().positive(),
|
|
475
|
+
mediaMode: z.enum(['screenshot', 'clip', 'dom']),
|
|
476
|
+
baseUrl: StrictUrlSchema,
|
|
477
|
+
maxParallelCaptures: z.number().int().positive().optional(),
|
|
478
|
+
variants: z.array(VariantSpecSchema).min(1),
|
|
479
|
+
preconditions: PreconditionSpecSchema,
|
|
480
|
+
steps: z.array(ExecutionOpcodeSchema).min(1),
|
|
481
|
+
artifactPlan: ArtifactSpecSchema,
|
|
482
|
+
outputScale: z.number().positive().optional(),
|
|
483
|
+
compileFingerprint: z.string().min(1),
|
|
484
|
+
variantFingerprint: z.string().optional(),
|
|
485
|
+
compiledAt: z.string().datetime(),
|
|
486
|
+
compiledWith: z.string().optional(),
|
|
487
|
+
mockDataGroups: z.array(MockDataGroupSchema).optional(),
|
|
488
|
+
});
|
|
489
|
+
// ── Healer patch ────────────────────────────────────────────────────
|
|
490
|
+
export const HealerPatchSchema = z.object({
|
|
491
|
+
opcodeIndex: z.number().int().min(0),
|
|
492
|
+
originalOpcode: ExecutionOpcodeSchema,
|
|
493
|
+
replacementOpcodes: z.array(ExecutionOpcodeSchema).min(1).max(3),
|
|
494
|
+
reason: z.string().min(1),
|
|
495
|
+
patchedAt: z.string().datetime(),
|
|
496
|
+
});
|
|
497
|
+
// ── Typed parse helpers ─────────────────────────────────────────────
|
|
498
|
+
export function parseProgram(data) {
|
|
499
|
+
return ExecutionProgramSchema.parse(data);
|
|
500
|
+
}
|
|
501
|
+
export function parseOpcode(data) {
|
|
502
|
+
return ExecutionOpcodeSchema.parse(data);
|
|
503
|
+
}
|
|
504
|
+
export function safeParseProgramResult(data) {
|
|
505
|
+
return ExecutionProgramSchema.safeParse(data);
|
|
506
|
+
}
|
|
507
|
+
//# sourceMappingURL=execution-schema.js.map
|