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.
Files changed (278) hide show
  1. package/assets/cursors/macos.svg +4 -0
  2. package/assets/cursors/windows.svg +15 -0
  3. package/assets/skill/OPCODE-REFERENCE.md +607 -0
  4. package/assets/skill/README.md +39 -0
  5. package/assets/skill/SKILL.md +453 -468
  6. package/assets/skill/STUDIO-SKILL.md +476 -0
  7. package/assets/skill/references/examples.md +104 -0
  8. package/assets/skill/references/interactive-demo.md +225 -0
  9. package/assets/skill/references/mock-data.md +178 -0
  10. package/dist/action-verifier.d.ts +29 -0
  11. package/dist/action-verifier.js +133 -0
  12. package/dist/agent-action-recovery.d.ts +45 -0
  13. package/dist/agent-action-recovery.js +370 -0
  14. package/dist/agent-message-utils.d.ts +21 -0
  15. package/dist/agent-message-utils.js +77 -0
  16. package/dist/agent-url-utils.d.ts +30 -0
  17. package/dist/agent-url-utils.js +138 -0
  18. package/dist/agent.d.ts +92 -8
  19. package/dist/agent.js +2936 -781
  20. package/dist/ak-tree.d.ts +39 -0
  21. package/dist/ak-tree.js +368 -0
  22. package/dist/alt-text.d.ts +26 -0
  23. package/dist/alt-text.js +55 -0
  24. package/dist/auth-capture.d.ts +17 -0
  25. package/dist/auth-capture.js +164 -0
  26. package/dist/benchmark.d.ts +59 -0
  27. package/dist/benchmark.js +135 -0
  28. package/dist/browser-bar.d.ts +14 -6
  29. package/dist/browser-bar.js +145 -8
  30. package/dist/browser-pool.d.ts +7 -0
  31. package/dist/browser-pool.js +15 -5
  32. package/dist/browser-utils.d.ts +31 -0
  33. package/dist/browser-utils.js +97 -0
  34. package/dist/browser.d.ts +51 -1
  35. package/dist/browser.js +1481 -31
  36. package/dist/capture-alt-text.js +2 -1
  37. package/dist/capture-language-preflight.js +14 -0
  38. package/dist/capture-llm-page-identity.js +22 -10
  39. package/dist/capture-page-identity.d.ts +5 -7
  40. package/dist/capture-page-identity.js +211 -78
  41. package/dist/capture-preset-credentials.d.ts +50 -0
  42. package/dist/capture-preset-credentials.js +127 -0
  43. package/dist/capture-request-plan.d.ts +2 -2
  44. package/dist/capture-request-plan.js +64 -16
  45. package/dist/capture-run-optimizer.js +48 -33
  46. package/dist/capture-selector-memory.d.ts +5 -0
  47. package/dist/capture-selector-memory.js +18 -0
  48. package/dist/capture-strategy.d.ts +36 -0
  49. package/dist/capture-strategy.js +95 -0
  50. package/dist/capture-studio-sync.d.ts +1 -0
  51. package/dist/capture-studio-sync.js +9 -3
  52. package/dist/capture-surface-contract.d.ts +36 -0
  53. package/dist/capture-surface-contract.js +299 -0
  54. package/dist/capture-transition-engine.d.ts +28 -0
  55. package/dist/capture-transition-engine.js +292 -0
  56. package/dist/capture-variant-state.d.ts +2 -0
  57. package/dist/capture-variant-state.js +26 -0
  58. package/dist/capture-verification.d.ts +35 -0
  59. package/dist/capture-verification.js +95 -0
  60. package/dist/capture-viewport-lock.d.ts +48 -0
  61. package/dist/capture-viewport-lock.js +74 -0
  62. package/dist/circuit-breaker.d.ts +42 -0
  63. package/dist/circuit-breaker.js +119 -0
  64. package/dist/cli-config.d.ts +8 -1
  65. package/dist/cli-config.js +62 -6
  66. package/dist/cli-contract.d.ts +15 -0
  67. package/dist/cli-contract.js +167 -0
  68. package/dist/cli-runner-local.d.ts +12 -0
  69. package/dist/cli-runner-local.js +102 -0
  70. package/dist/cli-runner.d.ts +34 -0
  71. package/dist/cli-runner.js +433 -0
  72. package/dist/cli-utils.d.ts +0 -1
  73. package/dist/cli-utils.js +2 -5
  74. package/dist/cli.js +1005 -267
  75. package/dist/clip-orchestrator.js +9 -2
  76. package/dist/clip-postprocess.js +25 -16
  77. package/dist/cookie-dismiss.d.ts +2 -0
  78. package/dist/cookie-dismiss.js +48 -13
  79. package/dist/cost-logging.d.ts +8 -0
  80. package/dist/cost-logging.js +160 -46
  81. package/dist/cost-resolution-monitor.d.ts +16 -0
  82. package/dist/cost-resolution-monitor.js +34 -0
  83. package/dist/credential-templates.js +2 -2
  84. package/dist/cursor-overlay-script.d.ts +6 -0
  85. package/dist/cursor-overlay-script.js +169 -0
  86. package/dist/dom-css-purger.d.ts +65 -0
  87. package/dist/dom-css-purger.js +333 -0
  88. package/dist/dom-font-inliner.d.ts +45 -0
  89. package/dist/dom-font-inliner.js +148 -0
  90. package/dist/dom-patch-resolver.d.ts +52 -0
  91. package/dist/dom-patch-resolver.js +242 -0
  92. package/dist/dom-serializer.d.ts +82 -0
  93. package/dist/dom-serializer.js +378 -0
  94. package/dist/element-capture.d.ts +1 -41
  95. package/dist/element-capture.js +202 -446
  96. package/dist/env-validation.d.ts +5 -0
  97. package/dist/env-validation.js +29 -0
  98. package/dist/execution-schema.d.ts +4423 -0
  99. package/dist/execution-schema.js +507 -0
  100. package/dist/execution-types.d.ts +886 -0
  101. package/dist/execution-types.js +65 -0
  102. package/dist/fonts-loader.d.ts +14 -0
  103. package/dist/fonts-loader.js +55 -0
  104. package/dist/hybrid-navigator.js +12 -12
  105. package/dist/index.d.ts +9 -6
  106. package/dist/index.js +10 -4
  107. package/dist/legacy/agent-action-recovery.d.ts +45 -0
  108. package/dist/legacy/agent-action-recovery.js +370 -0
  109. package/dist/legacy/agent-message-utils.d.ts +21 -0
  110. package/dist/legacy/agent-message-utils.js +77 -0
  111. package/dist/legacy/agent-url-utils.d.ts +30 -0
  112. package/dist/legacy/agent-url-utils.js +138 -0
  113. package/dist/legacy/agent.d.ts +226 -0
  114. package/dist/legacy/agent.js +6666 -0
  115. package/dist/legacy/clip-orchestrator.d.ts +148 -0
  116. package/dist/legacy/clip-orchestrator.js +957 -0
  117. package/dist/legacy/credential-templates.d.ts +5 -0
  118. package/dist/legacy/credential-templates.js +60 -0
  119. package/dist/legacy/hybrid-navigator.d.ts +138 -0
  120. package/dist/legacy/hybrid-navigator.js +468 -0
  121. package/dist/legacy/llm-usage.d.ts +17 -0
  122. package/dist/legacy/llm-usage.js +45 -0
  123. package/dist/legacy/prompt-cache.d.ts +10 -0
  124. package/dist/legacy/prompt-cache.js +24 -0
  125. package/dist/legacy/prompts.d.ts +175 -0
  126. package/dist/legacy/prompts.js +1038 -0
  127. package/dist/legacy/tools.d.ts +4 -0
  128. package/dist/legacy/tools.js +216 -0
  129. package/dist/legacy/video-agent.d.ts +143 -0
  130. package/dist/legacy/video-agent.js +4788 -0
  131. package/dist/legacy/video-observation.d.ts +36 -0
  132. package/dist/legacy/video-observation.js +192 -0
  133. package/dist/legacy/video-planner.d.ts +12 -0
  134. package/dist/legacy/video-planner.js +501 -0
  135. package/dist/legacy/video-prompts.d.ts +37 -0
  136. package/dist/legacy/video-prompts.js +569 -0
  137. package/dist/legacy/video-tools.d.ts +3 -0
  138. package/dist/legacy/video-tools.js +59 -0
  139. package/dist/legacy/video-variant-state.d.ts +29 -0
  140. package/dist/legacy/video-variant-state.js +80 -0
  141. package/dist/legacy/vision-model.d.ts +17 -0
  142. package/dist/legacy/vision-model.js +74 -0
  143. package/dist/llm-healer.d.ts +63 -0
  144. package/dist/llm-healer.js +166 -0
  145. package/dist/llm-provider.d.ts +29 -0
  146. package/dist/llm-provider.js +80 -0
  147. package/dist/logger.d.ts +6 -2
  148. package/dist/logger.js +15 -1
  149. package/dist/mockup-html.js +35 -25
  150. package/dist/mockup.d.ts +95 -2
  151. package/dist/mockup.js +427 -166
  152. package/dist/mouse-animation.d.ts +2 -2
  153. package/dist/mouse-animation.js +34 -20
  154. package/dist/opcode-actions.d.ts +42 -0
  155. package/dist/opcode-actions.js +511 -0
  156. package/dist/opcode-runner.d.ts +51 -0
  157. package/dist/opcode-runner.js +770 -0
  158. package/dist/openrouter-client.d.ts +40 -0
  159. package/dist/openrouter-client.js +16 -0
  160. package/dist/overlay-engine.d.ts +24 -0
  161. package/dist/overlay-engine.js +176 -0
  162. package/dist/postcondition.d.ts +16 -0
  163. package/dist/postcondition.js +269 -0
  164. package/dist/program-patcher.d.ts +25 -0
  165. package/dist/program-patcher.js +44 -0
  166. package/dist/prompts.d.ts +13 -5
  167. package/dist/prompts.js +224 -351
  168. package/dist/provider-config.d.ts +12 -0
  169. package/dist/provider-config.js +15 -0
  170. package/dist/recovery-chain.d.ts +37 -0
  171. package/dist/recovery-chain.js +350 -0
  172. package/dist/remote-browser.d.ts +28 -4
  173. package/dist/remote-browser.js +60 -5
  174. package/dist/safari-browser-bar.d.ts +15 -0
  175. package/dist/safari-browser-bar.js +95 -0
  176. package/dist/safari-toolbar-asset.d.ts +15 -0
  177. package/dist/safari-toolbar-asset.js +12 -0
  178. package/dist/security.d.ts +2 -1
  179. package/dist/security.js +49 -10
  180. package/dist/selector-resolver.d.ts +34 -0
  181. package/dist/selector-resolver.js +181 -0
  182. package/dist/semantic-resolver.d.ts +35 -0
  183. package/dist/semantic-resolver.js +161 -0
  184. package/dist/server-capture-runtime.d.ts +5 -3
  185. package/dist/server-capture-runtime.js +42 -95
  186. package/dist/server-credit-usage.d.ts +2 -2
  187. package/dist/server-project-webhooks.d.ts +15 -1
  188. package/dist/server-project-webhooks.js +34 -8
  189. package/dist/server-screenshot-watermark.js +27 -5
  190. package/dist/session-profile.js +164 -1
  191. package/dist/sf-pro-symbols.d.ts +1 -0
  192. package/dist/sf-pro-symbols.js +55 -0
  193. package/dist/skill-packaging.d.ts +28 -0
  194. package/dist/skill-packaging.js +169 -0
  195. package/dist/smart-wait.d.ts +27 -0
  196. package/dist/smart-wait.js +81 -0
  197. package/dist/status-bar-render.d.ts +20 -0
  198. package/dist/status-bar-render.js +410 -0
  199. package/dist/status-bar.d.ts +9 -0
  200. package/dist/status-bar.js +298 -14
  201. package/dist/svg-browser-bar.d.ts +33 -0
  202. package/dist/svg-browser-bar.js +206 -0
  203. package/dist/svg-status-bar.d.ts +36 -0
  204. package/dist/svg-status-bar.js +597 -0
  205. package/dist/svg-text.d.ts +61 -0
  206. package/dist/svg-text.js +118 -0
  207. package/dist/tools.js +89 -451
  208. package/dist/types.d.ts +240 -5
  209. package/dist/types.js +23 -1
  210. package/dist/v2/action-verifier.d.ts +29 -0
  211. package/dist/v2/action-verifier.js +133 -0
  212. package/dist/v2/alt-text.d.ts +26 -0
  213. package/dist/v2/alt-text.js +55 -0
  214. package/dist/v2/benchmark.d.ts +59 -0
  215. package/dist/v2/benchmark.js +135 -0
  216. package/dist/v2/capture-strategy.d.ts +30 -0
  217. package/dist/v2/capture-strategy.js +67 -0
  218. package/dist/v2/capture-verification.d.ts +35 -0
  219. package/dist/v2/capture-verification.js +95 -0
  220. package/dist/v2/circuit-breaker.d.ts +42 -0
  221. package/dist/v2/circuit-breaker.js +119 -0
  222. package/dist/v2/cli-runner-local.d.ts +11 -0
  223. package/dist/v2/cli-runner-local.js +91 -0
  224. package/dist/v2/cli-runner.d.ts +34 -0
  225. package/dist/v2/cli-runner.js +300 -0
  226. package/dist/v2/compiler-prompts.d.ts +27 -0
  227. package/dist/v2/compiler-prompts.js +123 -0
  228. package/dist/v2/compiler.d.ts +37 -0
  229. package/dist/v2/compiler.js +147 -0
  230. package/dist/v2/explorer.d.ts +41 -0
  231. package/dist/v2/explorer.js +56 -0
  232. package/dist/v2/index.d.ts +37 -0
  233. package/dist/v2/index.js +31 -0
  234. package/dist/v2/llm-healer.d.ts +62 -0
  235. package/dist/v2/llm-healer.js +166 -0
  236. package/dist/v2/llm-provider.d.ts +29 -0
  237. package/dist/v2/llm-provider.js +80 -0
  238. package/dist/v2/opcode-runner.d.ts +47 -0
  239. package/dist/v2/opcode-runner.js +634 -0
  240. package/dist/v2/overlay-engine.d.ts +24 -0
  241. package/dist/v2/overlay-engine.js +150 -0
  242. package/dist/v2/postcondition.d.ts +16 -0
  243. package/dist/v2/postcondition.js +249 -0
  244. package/dist/v2/program-patcher.d.ts +25 -0
  245. package/dist/v2/program-patcher.js +44 -0
  246. package/dist/v2/recovery-chain.d.ts +30 -0
  247. package/dist/v2/recovery-chain.js +368 -0
  248. package/dist/v2/schema.d.ts +2580 -0
  249. package/dist/v2/schema.js +295 -0
  250. package/dist/v2/selector-resolver.d.ts +34 -0
  251. package/dist/v2/selector-resolver.js +181 -0
  252. package/dist/v2/semantic-resolver.d.ts +35 -0
  253. package/dist/v2/semantic-resolver.js +161 -0
  254. package/dist/v2/smart-wait.d.ts +27 -0
  255. package/dist/v2/smart-wait.js +81 -0
  256. package/dist/v2/types.d.ts +444 -0
  257. package/dist/v2/types.js +19 -0
  258. package/dist/v2/web-playwright-local.d.ts +69 -0
  259. package/dist/v2/web-playwright-local.js +392 -0
  260. package/dist/version.d.ts +1 -0
  261. package/dist/version.js +5 -0
  262. package/dist/video-agent.js +18 -13
  263. package/dist/video-planner.js +2 -1
  264. package/dist/video-prompts.js +3 -3
  265. package/dist/web-playwright-local.d.ts +126 -0
  266. package/dist/web-playwright-local.js +819 -0
  267. package/dist/ws-auth.js +4 -1
  268. package/dist/ws-broadcast.d.ts +34 -0
  269. package/dist/ws-broadcast.js +85 -0
  270. package/dist/ws-connection-limits.d.ts +12 -0
  271. package/dist/ws-connection-limits.js +44 -0
  272. package/dist/ws-handler-utils.d.ts +32 -0
  273. package/dist/ws-handler-utils.js +139 -0
  274. package/dist/ws-handler.js +294 -164
  275. package/dist/ws-metrics-server.d.ts +9 -0
  276. package/dist/ws-metrics-server.js +31 -0
  277. package/dist/ws-server.js +41 -1
  278. package/package.json +51 -34
@@ -0,0 +1,433 @@
1
+ /**
2
+ * Capture Agent — CLI Runner
3
+ *
4
+ * Entry point for deterministic execution from the CLI.
5
+ * Flow:
6
+ * 1. Authenticate via stored CLI key
7
+ * 2. Fetch compiled program from server
8
+ * 3. Validate program against Zod schema
9
+ * 4. Launch local Playwright browser per variant
10
+ * 5. Execute program via opcode-runner
11
+ * 6. Upload artifacts + telemetry to server
12
+ */
13
+ import fs from 'node:fs/promises';
14
+ import os from 'node:os';
15
+ import path from 'node:path';
16
+ import { randomUUID } from 'node:crypto';
17
+ import { Browser } from './browser.js';
18
+ import { API_BASE_URL_ENV_VAR, requireConfig } from './cli-config.js';
19
+ import { WebPlaywrightLocal } from './web-playwright-local.js';
20
+ import { executeProgram } from './opcode-runner.js';
21
+ import { RecoveryChainImpl } from './recovery-chain.js';
22
+ import { parseProgram } from './execution-schema.js';
23
+ import { buildCursorOverlayScript } from './cursor-overlay-script.js';
24
+ import { logger } from './logger.js';
25
+ import { callLLM } from './llm-provider.js';
26
+ const HEALER_SYSTEM_PROMPT = 'You repair failed deterministic browser opcodes. Respond only with JSON.';
27
+ // ── Main entry point ────────────────────────────────────────────────
28
+ export async function runCapture(options) {
29
+ const config = await requireConfig();
30
+ // Step 1: Get the compiled program
31
+ let program;
32
+ if (options.program) {
33
+ program = options.program;
34
+ }
35
+ else {
36
+ const fetched = await fetchProgram(config, options.presetId);
37
+ if (!fetched.success) {
38
+ return { success: false, error: fetched.error };
39
+ }
40
+ program = fetched.program;
41
+ }
42
+ // Step 2: Validate the program
43
+ try {
44
+ program = parseProgram(program);
45
+ }
46
+ catch (err) {
47
+ return { success: false, error: `program validation failed: ${err instanceof Error ? err.message : String(err)}` };
48
+ }
49
+ // Persist against the canonical preset identifier selected by the CLI,
50
+ // even if the compiled program carries a human-readable preset slug/name.
51
+ if (program.presetId !== options.presetId) {
52
+ program = {
53
+ ...program,
54
+ presetId: options.presetId,
55
+ };
56
+ }
57
+ logger.info(`[capture] Running preset "${options.presetId}" — ${program.steps.length} opcodes, ${program.variants.length} variant(s)`);
58
+ const llmConfig = resolveCliLLMConfig();
59
+ // Step 3: Set up recovery chain
60
+ const recoveryChain = new RecoveryChainImpl({
61
+ selectorMemory: options.selectorMemory,
62
+ programSteps: program.steps,
63
+ llmProvider: llmConfig ? createHealerLLMProvider(llmConfig) : undefined,
64
+ credentials: program.preconditions.credentials,
65
+ });
66
+ // Step 4: Execute the program
67
+ const runOptions = {
68
+ recoveryChain,
69
+ abortSignal: options.abortSignal,
70
+ maxParallelVariants: program.maxParallelCaptures,
71
+ llmConfig,
72
+ presetName: program.presetId,
73
+ onProgress: (event) => {
74
+ if (!options.onProgress) {
75
+ logProgress(event);
76
+ }
77
+ options.onProgress?.(event);
78
+ },
79
+ };
80
+ const captureStart = Date.now();
81
+ if (program.maxParallelCaptures) {
82
+ logger.info(`[capture] Concurrency cap resolved to ${program.maxParallelCaptures} parallel variant(s)`);
83
+ }
84
+ const createAdapter = async (variant) => {
85
+ const browserOptions = {
86
+ headed: options.headed ?? false,
87
+ viewport: variant.viewport,
88
+ deviceScaleFactor: variant.deviceScaleFactor ?? program.outputScale,
89
+ lang: variant.locale,
90
+ colorScheme: variant.theme,
91
+ storageState: program.preconditions.storageState,
92
+ };
93
+ const recordable = program.mediaMode === 'clip';
94
+ let recordingDir;
95
+ let browser;
96
+ logger.info(`[capture] Launching browser${browserOptions.headed ? ' (headed)' : ''}…`);
97
+ if (recordable) {
98
+ recordingDir = await fs.mkdtemp(path.join(os.tmpdir(), `autokap-${program.mediaMode}-`));
99
+ browser = await Browser.forVideoRecording(browserOptions, recordingDir, buildCursorOverlayScript(program.artifactPlan.cursorTheme ?? 'minimal'));
100
+ }
101
+ else if (browserOptions.headed) {
102
+ // Headed mode: standalone browser (pool is always headless)
103
+ browser = new Browser(browserOptions);
104
+ await browser.launch();
105
+ }
106
+ else {
107
+ browser = await Browser.fromPool(browserOptions);
108
+ await browser.launch();
109
+ }
110
+ await applyPreconditions(browser, program);
111
+ return new WebPlaywrightLocal(browser, recordingDir);
112
+ };
113
+ const runResult = await executeProgram(program, createAdapter, runOptions);
114
+ if (runResult.success) {
115
+ logger.info(`[capture] Run completed successfully — ${runResult.telemetry.totalOpcodes} opcodes, ${runResult.telemetry.recoveredOpcodes} recovered, ${runResult.totalDurationMs}ms`);
116
+ }
117
+ else {
118
+ logger.error(`[capture] Run failed: ${runResult.error}`);
119
+ }
120
+ try {
121
+ logger.info('[capture] Saving captures, might take a few seconds...');
122
+ await uploadResults(config, program, runResult);
123
+ const totalDurationSec = ((Date.now() - captureStart) / 1000).toFixed(1);
124
+ logger.info(`[capture] Captures saved successfully — total ${totalDurationSec}s`);
125
+ }
126
+ catch (err) {
127
+ logger.error(`[capture] Failed to upload results: ${err instanceof Error ? err.message : String(err)}`);
128
+ }
129
+ return { success: runResult.success, runResult };
130
+ }
131
+ // ── Server communication ────────────────────────────────────────────
132
+ async function fetchProgram(config, presetId) {
133
+ try {
134
+ const url = `${config.apiBaseUrl}/api/cli/programs/${presetId}`;
135
+ const response = await fetch(url, {
136
+ headers: {
137
+ 'Authorization': `Bearer ${config.apiKey}`,
138
+ 'Content-Type': 'application/json',
139
+ },
140
+ });
141
+ if (!response.ok) {
142
+ return { success: false, error: await formatServerError(response, url) };
143
+ }
144
+ const data = await response.json();
145
+ if (data?._meta?.stale) {
146
+ logger.warn('[capture] Program is stale — langs/themes changed since last compilation. Recompile to apply changes.');
147
+ }
148
+ return { success: true, program: data };
149
+ }
150
+ catch (err) {
151
+ return { success: false, error: `failed to fetch program: ${err instanceof Error ? err.message : String(err)}` };
152
+ }
153
+ }
154
+ async function uploadResults(config, program, result) {
155
+ const runId = randomUUID();
156
+ const totalArtifacts = result.variantResults.reduce((sum, v) => sum + v.artifacts.length, 0);
157
+ let uploadedCount = 0;
158
+ // Upload artifacts
159
+ for (const variant of result.variantResults) {
160
+ const variantSpec = program.variants.find((entry) => entry.id === variant.variantId);
161
+ for (const artifact of variant.artifacts) {
162
+ const formData = new FormData();
163
+ const filename = buildArtifactFilename(program.presetId, variant.variantId, artifact);
164
+ uploadedCount += 1;
165
+ const label = artifact.captureName ?? artifact.clipName ?? artifact.fragmentName ?? artifact.stateName ?? filename;
166
+ logger.info(`[capture] Exporting capture ${uploadedCount}/${totalArtifacts}: ${label}`);
167
+ formData.append('file', new Blob([new Uint8Array(artifact.buffer)], { type: artifact.mimeType }), filename);
168
+ formData.append('presetId', program.presetId);
169
+ formData.append('programVersion', String(program.programVersion));
170
+ formData.append('compileFingerprint', program.compileFingerprint);
171
+ formData.append('runId', runId);
172
+ formData.append('variantId', variant.variantId);
173
+ formData.append('targetId', variantSpec?.targetId ?? variant.variantId);
174
+ formData.append('targetLabel', variantSpec?.targetLabel ?? variantSpec?.deviceFrame ?? variant.variantId);
175
+ formData.append('mediaMode', artifact.mediaMode);
176
+ formData.append('mimeType', artifact.mimeType);
177
+ formData.append('captureType', artifact.captureType ?? 'fullpage');
178
+ formData.append('captureUrl', artifact.captureUrl ?? program.baseUrl);
179
+ formData.append('lang', variantSpec?.locale ?? 'en');
180
+ formData.append('theme', variantSpec?.theme ?? 'light');
181
+ if (variantSpec?.deviceFrame) {
182
+ formData.append('deviceFrame', variantSpec.deviceFrame);
183
+ }
184
+ formData.append('viewport', JSON.stringify(variantSpec?.viewport ?? null));
185
+ formData.append('artifactPlan', JSON.stringify(program.artifactPlan));
186
+ if (artifact.altText) {
187
+ formData.append('altText', artifact.altText);
188
+ }
189
+ if (artifact.elementSelector) {
190
+ formData.append('elementSelector', artifact.elementSelector);
191
+ }
192
+ if (artifact.captureId) {
193
+ formData.append('captureId', artifact.captureId);
194
+ }
195
+ if (artifact.captureName) {
196
+ formData.append('captureName', artifact.captureName);
197
+ }
198
+ if (artifact.clipId) {
199
+ formData.append('clipId', artifact.clipId);
200
+ }
201
+ if (artifact.clipName) {
202
+ formData.append('clipName', artifact.clipName);
203
+ }
204
+ if (artifact.stepDescription) {
205
+ formData.append('stepDescription', artifact.stepDescription);
206
+ }
207
+ if (typeof artifact.stepIndex === 'number') {
208
+ formData.append('stepIndex', String(artifact.stepIndex));
209
+ }
210
+ if (artifact.tabIconData) {
211
+ formData.append('tabIcon', new Blob([new Uint8Array(artifact.tabIconData)], { type: artifact.tabIconMimeType ?? 'image/png' }), 'favicon');
212
+ }
213
+ if (typeof artifact.durationMs === 'number') {
214
+ formData.append('durationMs', String(artifact.durationMs));
215
+ }
216
+ if (typeof artifact.trimStartMs === 'number') {
217
+ formData.append('trimStartMs', String(artifact.trimStartMs));
218
+ }
219
+ // ── Interactive demo (mediaMode === 'dom') ──
220
+ if (artifact.stateName) {
221
+ formData.append('stateName', artifact.stateName);
222
+ }
223
+ if (artifact.domAssetUrls && artifact.domAssetUrls.length > 0) {
224
+ formData.append('domAssetUrls', JSON.stringify(artifact.domAssetUrls));
225
+ }
226
+ if (artifact.domThumbnailBuffer) {
227
+ formData.append('domThumbnail', new Blob([new Uint8Array(artifact.domThumbnailBuffer)], { type: 'image/png' }), 'thumbnail.png');
228
+ }
229
+ // Phase 5: fragment fields
230
+ if (artifact.fragmentName) {
231
+ formData.append('fragmentName', artifact.fragmentName);
232
+ }
233
+ // Phase 8: variant of the fragment capture (defaults to 'default'
234
+ // server-side when omitted, but we always send it explicitly so the
235
+ // upload row's unique key includes it).
236
+ if (artifact.fragmentVariantName) {
237
+ formData.append('fragmentVariantName', artifact.fragmentVariantName);
238
+ }
239
+ if (artifact.parentStateName) {
240
+ formData.append('parentStateName', artifact.parentStateName);
241
+ }
242
+ if (artifact.mountStrategy) {
243
+ formData.append('mountStrategy', artifact.mountStrategy);
244
+ }
245
+ if (artifact.mountTargetSelector) {
246
+ formData.append('mountTargetSelector', artifact.mountTargetSelector);
247
+ }
248
+ const response = await fetch(`${config.apiBaseUrl}/api/cli/artifacts`, {
249
+ method: 'POST',
250
+ headers: { 'Authorization': `Bearer ${config.apiKey}` },
251
+ body: formData,
252
+ });
253
+ if (!response.ok) {
254
+ throw new Error(`artifact upload failed for ${variant.variantId}: ${await formatServerError(response, `${config.apiBaseUrl}/api/cli/artifacts`)}`);
255
+ }
256
+ }
257
+ }
258
+ // Strip binary buffers from artifacts before sending. The raw PNG/video
259
+ // buffers were already uploaded via /api/cli/artifacts above, and the
260
+ // server strips them again before persisting. Sending them in the JSON
261
+ // body bloats the payload (each Buffer serializes as a giant int array,
262
+ // ~3-4× the original byte size) and overflows Next.js' request body limit.
263
+ const strippedRunResult = {
264
+ ...result,
265
+ variantResults: result.variantResults.map((variant) => ({
266
+ ...variant,
267
+ artifacts: variant.artifacts.map((artifact) => {
268
+ const { buffer: _buffer, tabIconData: _tabIconData, ...rest } = artifact;
269
+ return rest;
270
+ }),
271
+ })),
272
+ };
273
+ // Upload telemetry + healer patches
274
+ const telemetryResponse = await fetch(`${config.apiBaseUrl}/api/cli/telemetry`, {
275
+ method: 'POST',
276
+ headers: {
277
+ 'Authorization': `Bearer ${config.apiKey}`,
278
+ 'Content-Type': 'application/json',
279
+ },
280
+ body: JSON.stringify({
281
+ runId,
282
+ presetId: program.presetId,
283
+ programVersion: program.programVersion,
284
+ compileFingerprint: program.compileFingerprint,
285
+ success: result.success,
286
+ mediaMode: program.mediaMode,
287
+ telemetry: result.telemetry,
288
+ healerPatches: result.healerPatches,
289
+ runResult: strippedRunResult,
290
+ totalDurationMs: result.totalDurationMs,
291
+ variantSummaries: result.variantResults.map(v => ({
292
+ variantId: v.variantId,
293
+ success: v.success,
294
+ opcodeCount: v.opcodeResults.length,
295
+ artifactCount: v.artifacts.length,
296
+ durationMs: v.durationMs,
297
+ error: v.error,
298
+ })),
299
+ }),
300
+ });
301
+ if (!telemetryResponse.ok) {
302
+ throw new Error(`telemetry upload failed: ${await formatServerError(telemetryResponse, `${config.apiBaseUrl}/api/cli/telemetry`)}`);
303
+ }
304
+ }
305
+ async function formatServerError(response, requestedUrl) {
306
+ const contentType = response.headers?.get?.('content-type') ?? '';
307
+ const rawBody = (await response.text()).trim();
308
+ if (!rawBody) {
309
+ return `server returned ${response.status}`;
310
+ }
311
+ if (contentType.includes('application/json') || rawBody.startsWith('{')) {
312
+ try {
313
+ const parsed = JSON.parse(rawBody);
314
+ const message = typeof parsed.error === 'string'
315
+ ? parsed.error
316
+ : typeof parsed.message === 'string'
317
+ ? parsed.message
318
+ : null;
319
+ if (message) {
320
+ return `server returned ${response.status}: ${message}`;
321
+ }
322
+ }
323
+ catch {
324
+ // Fall back to a condensed text preview below.
325
+ }
326
+ }
327
+ const isHtml = contentType.includes('text/html') || /^<!doctype html>/i.test(rawBody);
328
+ if (response.status === 404 && isHtml) {
329
+ return [
330
+ `server returned 404 for ${requestedUrl}.`,
331
+ `The configured AutoKap server (${safeOrigin(requestedUrl)}) does not expose this CLI route yet.`,
332
+ 'This usually means the web app deployment is older than the CLI.',
333
+ `Point the CLI at your local dev server with \`autokap run --local <preset-id>\`, \`${API_BASE_URL_ENV_VAR}=http://localhost:3000 autokap run <preset-id>\`, or re-initialize against a local server with \`autokap init --cli-key <key> --api-base-url http://localhost:3000\`.`,
334
+ ].join(' ');
335
+ }
336
+ if (isHtml) {
337
+ return `server returned ${response.status}: unexpected HTML response from ${requestedUrl}`;
338
+ }
339
+ return `server returned ${response.status}: ${rawBody.replace(/\s+/g, ' ').slice(0, 240)}`;
340
+ }
341
+ function safeOrigin(url) {
342
+ try {
343
+ return new URL(url).origin;
344
+ }
345
+ catch {
346
+ return url;
347
+ }
348
+ }
349
+ async function applyPreconditions(browser, program) {
350
+ const { preconditions } = program;
351
+ // Auth bootstrap auto-adapts to whatever is configured on the preset.
352
+ // - cookies / sessionStorage / storageState are injected into the browser
353
+ // context so the page starts already authenticated.
354
+ // - credentials are NOT applied here; they're substituted into
355
+ // {{email}}/{{password}}/{{loginUrl}} placeholders inside opcodes by the
356
+ // opcode runner, and the program performs the UI login itself.
357
+ // - If neither is set, the run is anonymous.
358
+ if (preconditions.cookies && preconditions.cookies.length > 0) {
359
+ await browser.addCookies(preconditions.cookies);
360
+ }
361
+ if (preconditions.sessionStorage && Object.keys(preconditions.sessionStorage).length > 0) {
362
+ await browser.prepareSessionStorage(preconditions.sessionStorage, { replace: false });
363
+ }
364
+ }
365
+ function resolveCliLLMConfig() {
366
+ const apiKey = process.env.OPENROUTER_API_KEY?.trim();
367
+ if (!apiKey)
368
+ return undefined;
369
+ return {
370
+ apiKey,
371
+ model: process.env.AUTOKAP_LLM_MODEL?.trim() || undefined,
372
+ };
373
+ }
374
+ function createHealerLLMProvider(llmConfig) {
375
+ return {
376
+ call: async (prompt, screenshot) => {
377
+ const llmResult = await callLLM({
378
+ ...llmConfig,
379
+ maxTokens: Math.max(llmConfig.maxTokens ?? 400, 400),
380
+ timeoutMs: llmConfig.timeoutMs ?? 20000,
381
+ }, HEALER_SYSTEM_PROMPT, prompt, screenshot);
382
+ return {
383
+ response: llmResult.text,
384
+ llmResult,
385
+ };
386
+ },
387
+ };
388
+ }
389
+ function buildArtifactFilename(presetId, variantId, artifact) {
390
+ const ext = artifact.mediaMode === 'dom'
391
+ ? 'html'
392
+ : artifact.mimeType === 'image/jpeg'
393
+ ? 'jpg'
394
+ : artifact.mimeType === 'image/png'
395
+ ? 'png'
396
+ : artifact.mimeType.includes('gif')
397
+ ? 'gif'
398
+ : artifact.mimeType.includes('mp4')
399
+ ? 'mp4'
400
+ : 'webm';
401
+ const stepToken = typeof artifact.stepIndex === 'number' ? `-${artifact.stepIndex}` : '';
402
+ return `${presetId}-${variantId}${stepToken}.${ext}`;
403
+ }
404
+ // ── Progress logging ────────────────────────────────────────────────
405
+ function logProgress(event) {
406
+ const prefix = `[capture][${event.variantId}]`;
407
+ switch (event.type) {
408
+ case 'variant_start':
409
+ logger.info(`${prefix} Starting variant`);
410
+ break;
411
+ case 'variant_end':
412
+ logger.info(`${prefix} ${event.status === 'ok' ? 'Completed' : 'Failed'}: ${event.message}`);
413
+ break;
414
+ case 'opcode_start':
415
+ logger.debug(`${prefix}[${event.opcodeIndex}] ${event.opcodeKind}: ${event.message}`);
416
+ break;
417
+ case 'opcode_end':
418
+ if (event.status === 'failed') {
419
+ logger.error(`${prefix}[${event.opcodeIndex}] FAILED: ${event.message}`);
420
+ }
421
+ else if (event.status === 'recovered') {
422
+ logger.warn(`${prefix}[${event.opcodeIndex}] RECOVERED: ${event.message}`);
423
+ }
424
+ break;
425
+ case 'recovery':
426
+ logger.warn(`${prefix}[${event.opcodeIndex}] Recovery: ${event.message}`);
427
+ break;
428
+ case 'breaker_trip':
429
+ logger.error(`${prefix} Circuit breaker tripped: ${event.message}`);
430
+ break;
431
+ }
432
+ }
433
+ //# sourceMappingURL=cli-runner.js.map
@@ -1,6 +1,5 @@
1
1
  export declare function replaceSkillPlaceholders(content: string, opts: {
2
2
  projectUrl?: string;
3
3
  projectId?: string;
4
- apiKey?: string;
5
4
  apiBaseUrl?: string;
6
5
  }): string;
package/dist/cli-utils.js CHANGED
@@ -6,12 +6,9 @@ export function replaceSkillPlaceholders(content, opts) {
6
6
  if (opts.projectId) {
7
7
  result = result.replace(/\[AUTOKAP_PROJECT_ID\]/g, opts.projectId);
8
8
  }
9
- if (opts.apiKey) {
10
- result = result.replace(/YOUR_API_KEY/g, opts.apiKey);
9
+ if (opts.apiBaseUrl) {
10
+ result = result.replace(/https:\/\/autokap\.app/g, opts.apiBaseUrl);
11
11
  }
12
- const baseUrl = opts.apiBaseUrl ?? 'https://autokap.app';
13
- result = result.replace(/https:\/\/app\.autokap\.com/g, baseUrl);
14
- result = result.replace(/https:\/\/autokap\.com/g, baseUrl);
15
12
  return result;
16
13
  }
17
14
  //# sourceMappingURL=cli-utils.js.map