autokap 1.0.2 → 1.0.4

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 (83) hide show
  1. package/dist/cli-config.d.ts +13 -0
  2. package/dist/cli-config.js +42 -0
  3. package/dist/cli-utils.d.ts +0 -19
  4. package/dist/cli-utils.js +2 -65
  5. package/dist/cli.d.ts +0 -1
  6. package/dist/cli.js +266 -305
  7. package/package.json +26 -19
  8. package/assets/chrome/ios-statusbar-comparison-reference.jpg +0 -0
  9. package/assets/chrome/ios-statusbar-dark-reference.jpg +0 -0
  10. package/assets/chrome/ios-statusbar-light-reference.jpg +0 -0
  11. package/assets/devices/ipad-pro-11-m4.json +0 -52
  12. package/assets/devices/iphone-16-pro.json +0 -53
  13. package/assets/devices/macbook-air-13.json +0 -45
  14. package/assets/frames/MacBook Air 13.svg +0 -242
  15. package/assets/frames/Status bar - iPhone.png +0 -0
  16. package/assets/frames/Status bar and Menu bar- iPad.png +0 -0
  17. package/assets/frames/iPad Pro M4 11_.png +0 -0
  18. package/assets/frames/iPhone 16 Pro.png +0 -0
  19. package/assets/icons/Cellular Connection.svg +0 -3
  20. package/assets/icons/Union.svg +0 -6
  21. package/assets/icons/Wifi.svg +0 -3
  22. package/assets/icons/battery.svg +0 -5
  23. package/assets/icons/battery_charging.svg +0 -8
  24. package/dist/abort.d.ts +0 -5
  25. package/dist/abort.js +0 -44
  26. package/dist/agent.d.ts +0 -142
  27. package/dist/agent.js +0 -4504
  28. package/dist/browser-bar.d.ts +0 -40
  29. package/dist/browser-bar.js +0 -147
  30. package/dist/clip-orchestrator.d.ts +0 -148
  31. package/dist/clip-orchestrator.js +0 -950
  32. package/dist/clip-postprocess.d.ts +0 -42
  33. package/dist/clip-postprocess.js +0 -192
  34. package/dist/credential-templates.d.ts +0 -5
  35. package/dist/credential-templates.js +0 -60
  36. package/dist/element-capture.d.ts +0 -53
  37. package/dist/element-capture.js +0 -766
  38. package/dist/hybrid-navigator.d.ts +0 -138
  39. package/dist/hybrid-navigator.js +0 -468
  40. package/dist/index.d.ts +0 -15
  41. package/dist/index.js +0 -11
  42. package/dist/llm-usage.d.ts +0 -17
  43. package/dist/llm-usage.js +0 -45
  44. package/dist/mockup-html.d.ts +0 -119
  45. package/dist/mockup-html.js +0 -253
  46. package/dist/mockup.d.ts +0 -94
  47. package/dist/mockup.js +0 -604
  48. package/dist/mouse-animation.d.ts +0 -46
  49. package/dist/mouse-animation.js +0 -100
  50. package/dist/overlay-utils.d.ts +0 -14
  51. package/dist/overlay-utils.js +0 -13
  52. package/dist/posthog.d.ts +0 -4
  53. package/dist/posthog.js +0 -26
  54. package/dist/prompt-cache.d.ts +0 -10
  55. package/dist/prompt-cache.js +0 -24
  56. package/dist/prompts.d.ts +0 -167
  57. package/dist/prompts.js +0 -1165
  58. package/dist/security.d.ts +0 -20
  59. package/dist/security.js +0 -569
  60. package/dist/session-profile.d.ts +0 -86
  61. package/dist/session-profile.js +0 -1471
  62. package/dist/sf-pro-fonts.d.ts +0 -4
  63. package/dist/sf-pro-fonts.js +0 -7
  64. package/dist/status-bar-l10n.d.ts +0 -14
  65. package/dist/status-bar-l10n.js +0 -177
  66. package/dist/status-bar.d.ts +0 -44
  67. package/dist/status-bar.js +0 -336
  68. package/dist/tools.d.ts +0 -4
  69. package/dist/tools.js +0 -578
  70. package/dist/video-agent.d.ts +0 -143
  71. package/dist/video-agent.js +0 -4783
  72. package/dist/video-observation.d.ts +0 -36
  73. package/dist/video-observation.js +0 -192
  74. package/dist/video-planner.d.ts +0 -12
  75. package/dist/video-planner.js +0 -500
  76. package/dist/video-prompts.d.ts +0 -37
  77. package/dist/video-prompts.js +0 -554
  78. package/dist/video-tools.d.ts +0 -3
  79. package/dist/video-tools.js +0 -59
  80. package/dist/video-variant-state.d.ts +0 -29
  81. package/dist/video-variant-state.js +0 -80
  82. package/dist/vision-model.d.ts +0 -17
  83. package/dist/vision-model.js +0 -74
@@ -1,42 +0,0 @@
1
- import type { ClipOptions } from './types.js';
2
- /**
3
- * Resolve the system ffmpeg binary path. Throws if not found.
4
- */
5
- export declare function ensureFfmpegAvailable(): Promise<string>;
6
- /**
7
- * Convert a WebM recording to an optimized GIF using a 2-pass palette approach.
8
- * Pass 1: generate an optimal palette. Pass 2: encode with that palette.
9
- */
10
- export declare function convertToGif(webmPath: string, outputPath: string, opts?: {
11
- fps?: number;
12
- maxWidth?: number;
13
- loop?: boolean;
14
- }): Promise<void>;
15
- /**
16
- * Convert a WebM recording to an MP4 with web-optimized settings.
17
- */
18
- export declare function convertToMp4(webmPath: string, outputPath: string): Promise<void>;
19
- /**
20
- * Extract the first frame of a WebM as a PNG thumbnail.
21
- */
22
- export declare function extractThumbnail(webmPath: string, outputPath: string): Promise<void>;
23
- /**
24
- * Trim a recording: skip dead frames at the start and cap duration.
25
- */
26
- export declare function trimRecording(inputPath: string, outputPath: string, startSec?: number, maxDurationSec?: number): Promise<void>;
27
- /**
28
- * Get the duration of a media file in milliseconds.
29
- */
30
- export declare function getMediaDurationMs(filePath: string): Promise<number>;
31
- export interface ClipPostProcessResult {
32
- gifPath?: string;
33
- mp4Path?: string;
34
- thumbnailPath?: string;
35
- durationMs: number;
36
- fileSizeBytes?: number;
37
- }
38
- /**
39
- * Full post-processing pipeline for a single clip recording:
40
- * trim → GIF and/or MP4 → thumbnail → measure.
41
- */
42
- export declare function postProcessClipRecording(webmPath: string, outputDir: string, clipId: string, options?: ClipOptions): Promise<ClipPostProcessResult>;
@@ -1,192 +0,0 @@
1
- import { execFile } from 'node:child_process';
2
- import { stat } from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { promisify } from 'node:util';
5
- const execFileAsync = promisify(execFile);
6
- // ── Default values ──────────────────────────────────────────────────
7
- const DEFAULT_GIF_FPS = 15;
8
- const DEFAULT_GIF_MAX_WIDTH = 800;
9
- const DEFAULT_MAX_DURATION_SEC = 8;
10
- const DEFAULT_TRIM_START_SEC = 0.3;
11
- // ── ffmpeg detection ────────────────────────────────────────────────
12
- let cachedFfmpegPath = null;
13
- /**
14
- * Resolve the system ffmpeg binary path. Throws if not found.
15
- */
16
- export async function ensureFfmpegAvailable() {
17
- if (cachedFfmpegPath)
18
- return cachedFfmpegPath;
19
- try {
20
- const { stdout } = await execFileAsync('which', ['ffmpeg']);
21
- const ffmpegPath = stdout.trim();
22
- if (!ffmpegPath)
23
- throw new Error('ffmpeg not found');
24
- cachedFfmpegPath = ffmpegPath;
25
- return ffmpegPath;
26
- }
27
- catch {
28
- throw new Error('ffmpeg is required for clip post-processing but was not found on your system. ' +
29
- 'Install it via: brew install ffmpeg (macOS) or apt install ffmpeg (Linux).');
30
- }
31
- }
32
- // ── Conversion functions ────────────────────────────────────────────
33
- /**
34
- * Convert a WebM recording to an optimized GIF using a 2-pass palette approach.
35
- * Pass 1: generate an optimal palette. Pass 2: encode with that palette.
36
- */
37
- export async function convertToGif(webmPath, outputPath, opts = {}) {
38
- const ffmpeg = await ensureFfmpegAvailable();
39
- const fps = opts.fps ?? DEFAULT_GIF_FPS;
40
- const maxWidth = opts.maxWidth ?? DEFAULT_GIF_MAX_WIDTH;
41
- const loopFlag = (opts.loop ?? true) ? '0' : '-1';
42
- const paletteDir = path.dirname(outputPath);
43
- const palettePath = path.join(paletteDir, `_palette_${Date.now()}.png`);
44
- const scaleFilter = `fps=${fps},scale=${maxWidth}:-1:flags=lanczos`;
45
- // Pass 1: Generate palette
46
- await execFileAsync(ffmpeg, [
47
- '-i', webmPath,
48
- '-vf', `${scaleFilter},palettegen=stats_mode=diff`,
49
- '-y', palettePath,
50
- ]);
51
- // Pass 2: Encode GIF with palette
52
- try {
53
- await execFileAsync(ffmpeg, [
54
- '-i', webmPath,
55
- '-i', palettePath,
56
- '-lavfi', `${scaleFilter}[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=3`,
57
- '-loop', loopFlag,
58
- '-y', outputPath,
59
- ]);
60
- }
61
- finally {
62
- // Clean up palette file
63
- try {
64
- await stat(palettePath).then(() => execFileAsync('rm', [palettePath]));
65
- }
66
- catch { /* ignore */ }
67
- }
68
- }
69
- /**
70
- * Convert a WebM recording to an MP4 with web-optimized settings.
71
- */
72
- export async function convertToMp4(webmPath, outputPath) {
73
- const ffmpeg = await ensureFfmpegAvailable();
74
- await execFileAsync(ffmpeg, [
75
- '-i', webmPath,
76
- '-c:v', 'libx264',
77
- '-preset', 'slow',
78
- '-crf', '22',
79
- '-pix_fmt', 'yuv420p',
80
- '-movflags', '+faststart',
81
- '-an',
82
- '-y', outputPath,
83
- ]);
84
- }
85
- /**
86
- * Extract the first frame of a WebM as a PNG thumbnail.
87
- */
88
- export async function extractThumbnail(webmPath, outputPath) {
89
- const ffmpeg = await ensureFfmpegAvailable();
90
- await execFileAsync(ffmpeg, [
91
- '-i', webmPath,
92
- '-frames:v', '1',
93
- '-y', outputPath,
94
- ]);
95
- }
96
- /**
97
- * Trim a recording: skip dead frames at the start and cap duration.
98
- */
99
- export async function trimRecording(inputPath, outputPath, startSec = DEFAULT_TRIM_START_SEC, maxDurationSec = DEFAULT_MAX_DURATION_SEC) {
100
- const ffmpeg = await ensureFfmpegAvailable();
101
- await execFileAsync(ffmpeg, [
102
- '-ss', String(startSec),
103
- '-i', inputPath,
104
- '-t', String(maxDurationSec),
105
- '-c', 'copy',
106
- '-y', outputPath,
107
- ]);
108
- }
109
- /**
110
- * Get the duration of a media file in milliseconds.
111
- */
112
- export async function getMediaDurationMs(filePath) {
113
- const ffmpeg = await ensureFfmpegAvailable();
114
- const ffprobe = ffmpeg.replace(/ffmpeg$/, 'ffprobe');
115
- const { stdout } = await execFileAsync(ffprobe, [
116
- '-v', 'error',
117
- '-show_entries', 'format=duration',
118
- '-of', 'default=noprint_wrappers=1:nokey=1',
119
- filePath,
120
- ]);
121
- return Math.round(parseFloat(stdout.trim()) * 1000);
122
- }
123
- /**
124
- * Freeze the last frame of a video for `durationSec` additional seconds.
125
- * Uses ffmpeg's tpad filter to hold the final frame in place.
126
- */
127
- async function freezeLastFrame(inputPath, outputPath, durationSec) {
128
- const ffmpeg = await ensureFfmpegAvailable();
129
- const stopDurationMs = Math.round(durationSec * 1000);
130
- await execFileAsync(ffmpeg, [
131
- '-i', inputPath,
132
- '-vf', `tpad=stop_mode=clone:stop_duration=${stopDurationMs}ms`,
133
- '-c:v', 'libvpx-vp9',
134
- '-crf', '30',
135
- '-b:v', '0',
136
- '-an',
137
- '-y', outputPath,
138
- ]);
139
- }
140
- /**
141
- * Full post-processing pipeline for a single clip recording:
142
- * trim → GIF and/or MP4 → thumbnail → measure.
143
- */
144
- export async function postProcessClipRecording(webmPath, outputDir, clipId, options = {}) {
145
- const maxDuration = options.maxDurationSec ?? DEFAULT_MAX_DURATION_SEC;
146
- // Step 1: Trim the recording — cut the setup phase (page load, overlay dismiss)
147
- const trimStart = options.trimStartSec ?? DEFAULT_TRIM_START_SEC;
148
- const trimmedPath = path.join(outputDir, `${clipId}_trimmed.webm`);
149
- await trimRecording(webmPath, trimmedPath, trimStart, maxDuration);
150
- // Step 1b: Optionally freeze the last frame for a pause before looping
151
- const holdSec = Math.min(Math.max(options.holdLastFrameSec ?? 0, 0), 10);
152
- let sourcePath = trimmedPath;
153
- if (holdSec > 0) {
154
- const paddedPath = path.join(outputDir, `${clipId}_padded.webm`);
155
- await freezeLastFrame(trimmedPath, paddedPath, holdSec);
156
- sourcePath = paddedPath;
157
- }
158
- const durationMs = await getMediaDurationMs(sourcePath);
159
- const result = { durationMs };
160
- // Step 2: Always persist both a GIF and an MP4.
161
- // The GIF remains useful for delivery and embeds, while the MP4 is the
162
- // high-fidelity source for Studio playback and downstream re-renders.
163
- const gifPath = path.join(outputDir, `${clipId}.gif`);
164
- await convertToGif(sourcePath, gifPath, {
165
- fps: options.gifFps,
166
- maxWidth: options.gifMaxWidth,
167
- loop: options.loop,
168
- });
169
- result.gifPath = gifPath;
170
- const gifStat = await stat(gifPath);
171
- result.fileSizeBytes = gifStat.size;
172
- const mp4Path = path.join(outputDir, `${clipId}.mp4`);
173
- await convertToMp4(sourcePath, mp4Path);
174
- result.mp4Path = mp4Path;
175
- // Step 3: Extract thumbnail
176
- const thumbnailPath = path.join(outputDir, `${clipId}_thumb.png`);
177
- await extractThumbnail(sourcePath, thumbnailPath);
178
- result.thumbnailPath = thumbnailPath;
179
- // Clean up intermediate files
180
- try {
181
- await execFileAsync('rm', [trimmedPath]);
182
- }
183
- catch { /* ignore */ }
184
- if (sourcePath !== trimmedPath) {
185
- try {
186
- await execFileAsync('rm', [sourcePath]);
187
- }
188
- catch { /* ignore */ }
189
- }
190
- return result;
191
- }
192
- //# sourceMappingURL=clip-postprocess.js.map
@@ -1,5 +0,0 @@
1
- import type { LoginCredentials } from "./types.js";
2
- export declare function resolveCredentialTemplates(value: string | undefined, credentials?: LoginCredentials): string | undefined;
3
- export declare function ensureNoCredentialTemplate(field: string, value: string | undefined): void;
4
- export declare function sanitizeCredentialParams(params: Record<string, unknown>, credentials?: LoginCredentials): Record<string, unknown>;
5
- export declare function resolveActionCredentialArgs(action: string, args: Record<string, unknown>, credentials?: LoginCredentials): Record<string, unknown>;
@@ -1,60 +0,0 @@
1
- const TEMPLATE_RE = /\{\{credential\.(loginUrl|email|password)\}\}/g;
2
- export function resolveCredentialTemplates(value, credentials) {
3
- if (!value)
4
- return value;
5
- const replacements = {
6
- loginUrl: credentials?.loginUrl,
7
- email: credentials?.email,
8
- password: credentials?.password,
9
- };
10
- return value.replace(TEMPLATE_RE, (match, key) => {
11
- const replacement = replacements[key];
12
- return typeof replacement === "string" ? replacement : match;
13
- });
14
- }
15
- export function ensureNoCredentialTemplate(field, value) {
16
- if (value && TEMPLATE_RE.test(value)) {
17
- TEMPLATE_RE.lastIndex = 0;
18
- throw new Error(`Missing credential value for ${field}`);
19
- }
20
- TEMPLATE_RE.lastIndex = 0;
21
- }
22
- function sanitizeCredentialString(value, credentials) {
23
- if (!credentials)
24
- return value;
25
- if (credentials.password && value === credentials.password) {
26
- return "{{credential.password}}";
27
- }
28
- if (credentials.email && value === credentials.email) {
29
- return "{{credential.email}}";
30
- }
31
- if (credentials.loginUrl && value === credentials.loginUrl) {
32
- return "{{credential.loginUrl}}";
33
- }
34
- return value;
35
- }
36
- export function sanitizeCredentialParams(params, credentials) {
37
- const sanitized = {};
38
- for (const [key, value] of Object.entries(params)) {
39
- sanitized[key] =
40
- typeof value === "string"
41
- ? sanitizeCredentialString(value, credentials)
42
- : value;
43
- }
44
- return sanitized;
45
- }
46
- export function resolveActionCredentialArgs(action, args, credentials) {
47
- if (!credentials)
48
- return args;
49
- const resolved = { ...args };
50
- if (action === "type_text" && typeof resolved.text === "string") {
51
- resolved.text = resolveCredentialTemplates(resolved.text, credentials);
52
- ensureNoCredentialTemplate("type_text.text", resolved.text);
53
- }
54
- if (action === "navigate_to" && typeof resolved.url === "string") {
55
- resolved.url = resolveCredentialTemplates(resolved.url, credentials);
56
- ensureNoCredentialTemplate("navigate_to.url", resolved.url);
57
- }
58
- return resolved;
59
- }
60
- //# sourceMappingURL=credential-templates.js.map
@@ -1,53 +0,0 @@
1
- import { Browser } from './browser.js';
2
- import type { IsolatedElement, ElementCaptureResult, OutscaleConfig, SelectorValidationResult } from './types.js';
3
- interface SearchQueryHistoryEntry {
4
- candidateLines: string[];
5
- domSignature: string;
6
- selectors: string[];
7
- hasTransientSelectors: boolean;
8
- /** Best candidate bounding box for coordinate-based fallback capture. */
9
- bestRegion?: {
10
- x: number;
11
- y: number;
12
- width: number;
13
- height: number;
14
- } | null;
15
- }
16
- export declare function isLooseElementCaptureRejectionReason(reason: string | null | undefined): boolean;
17
- export declare function isTagOnlyStructuralSelector(selector: string): boolean;
18
- export declare function shouldBlockUngroundedStructuralSelector(params: {
19
- selector: string;
20
- groundedSelectors: Iterable<string>;
21
- verifierRejectedAsTooLoose: boolean;
22
- }): boolean;
23
- export declare function outscaleAddsPadding(outscale: OutscaleConfig | undefined): boolean;
24
- export declare function buildVerificationOutscale(outscale: OutscaleConfig | undefined): OutscaleConfig;
25
- export declare function shouldAcceptDomCorroboratedSelector(params: {
26
- looseFailureCount: number;
27
- verifierRejectedAsTooLoose: boolean;
28
- validation: SelectorValidationResult;
29
- viewport: {
30
- width: number;
31
- height: number;
32
- } | null;
33
- observedAsInteractive: boolean;
34
- directQueryCount: number;
35
- containerQueryCount: number;
36
- }): boolean;
37
- export declare function computeElementCaptureDomSignature(params: {
38
- currentUrl: string;
39
- interactiveElements: Array<Pick<Awaited<ReturnType<Browser['getInteractiveElements']>>[number], 'index' | 'tag' | 'role' | 'text' | 'selector' | 'visibilityState'>>;
40
- }): string;
41
- export declare function shouldAllowSearchRefresh(params: {
42
- cached: SearchQueryHistoryEntry | undefined;
43
- domSignature: string;
44
- lastFailedTransientSelector: string | null;
45
- }): boolean;
46
- interface ElementCaptureOptions {
47
- abortSignal?: AbortSignal;
48
- distinctId?: string;
49
- fallbackModel?: string;
50
- uploadImage?: (buffer: Buffer, mimeType: 'image/jpeg' | 'image/png') => Promise<string>;
51
- }
52
- export declare function captureIsolatedElement(browser: Browser, element: IsolatedElement, apiKey: string, model: string, options?: ElementCaptureOptions): Promise<ElementCaptureResult>;
53
- export {};