autokap 1.6.1 → 1.6.3
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/dist/browser-pool.d.ts +1 -0
- package/dist/browser-pool.js +2 -0
- package/dist/browser.js +13 -1
- package/dist/cli-config.js +69 -25
- package/dist/cli-contract.d.ts +25 -5
- package/dist/cli-contract.js +55 -151
- package/dist/cli-doctor.d.ts +1 -1
- package/dist/cli-doctor.js +67 -82
- package/dist/cli-runner.d.ts +1 -1
- package/dist/cli-runner.js +23 -10
- package/dist/cli.js +25 -1163
- package/dist/execution-schema.d.ts +9 -3
- package/dist/execution-schema.js +12 -0
- package/dist/execution-types.d.ts +33 -2
- package/dist/mockup.d.ts +66 -2
- package/dist/mockup.js +31 -14
- package/dist/opcode-runner.js +9 -0
- package/dist/program-signing.d.ts +4 -1
- package/dist/program-signing.js +4 -0
- package/dist/skill-packaging.d.ts +0 -16
- package/dist/skill-packaging.js +1 -51
- package/dist/transform-browser-url.d.ts +6 -0
- package/dist/transform-browser-url.js +28 -0
- package/dist/types.d.ts +11 -0
- package/dist/video-narration-schema.d.ts +4 -1
- package/dist/web-playwright-local.d.ts +1 -0
- package/dist/web-playwright-local.js +0 -0
- package/package.json +6 -6
- package/readme.md +15 -12
- package/assets/skill/OPCODE-REFERENCE.md +0 -625
- package/assets/skill/README.md +0 -38
- package/assets/skill/SKILL.md +0 -590
- package/assets/skill/references/STANDARDS.md +0 -236
- package/assets/skill/references/examples.md +0 -88
- package/assets/skill/references/mock-data.md +0 -178
- package/dist/auth-capture.d.ts +0 -17
- package/dist/auth-capture.js +0 -199
- package/dist/cli-utils.d.ts +0 -5
- package/dist/cli-utils.js +0 -14
- package/dist/version-check.d.ts +0 -4
- package/dist/version-check.js +0 -102
|
@@ -1072,9 +1072,9 @@ export declare const PreconditionSpecSchema: z.ZodObject<{
|
|
|
1072
1072
|
httpOnly: z.ZodBoolean;
|
|
1073
1073
|
secure: z.ZodBoolean;
|
|
1074
1074
|
sameSite: z.ZodEnum<{
|
|
1075
|
-
Strict: "Strict";
|
|
1076
1075
|
Lax: "Lax";
|
|
1077
1076
|
None: "None";
|
|
1077
|
+
Strict: "Strict";
|
|
1078
1078
|
}>;
|
|
1079
1079
|
}, z.core.$strict>>;
|
|
1080
1080
|
origins: z.ZodArray<z.ZodObject<{
|
|
@@ -1221,9 +1221,9 @@ export declare const ExecutionProgramSchema: z.ZodObject<{
|
|
|
1221
1221
|
httpOnly: z.ZodBoolean;
|
|
1222
1222
|
secure: z.ZodBoolean;
|
|
1223
1223
|
sameSite: z.ZodEnum<{
|
|
1224
|
-
Strict: "Strict";
|
|
1225
1224
|
Lax: "Lax";
|
|
1226
1225
|
None: "None";
|
|
1226
|
+
Strict: "Strict";
|
|
1227
1227
|
}>;
|
|
1228
1228
|
}, z.core.$strict>>;
|
|
1229
1229
|
origins: z.ZodArray<z.ZodObject<{
|
|
@@ -2226,6 +2226,9 @@ export declare const ExecutionProgramSchema: z.ZodObject<{
|
|
|
2226
2226
|
defaultValues: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2227
2227
|
replaceExisting: z.ZodOptional<z.ZodBoolean>;
|
|
2228
2228
|
}, z.core.$strict>>>;
|
|
2229
|
+
deviceConfigs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
2230
|
+
publicUrl: z.ZodOptional<z.ZodString>;
|
|
2231
|
+
environmentHttpHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2229
2232
|
}, z.core.$strict>;
|
|
2230
2233
|
export declare const HealerPatchSchema: z.ZodObject<{
|
|
2231
2234
|
opcodeIndex: z.ZodNumber;
|
|
@@ -4182,7 +4185,7 @@ export declare function safeParseProgramResult(data: unknown): z.ZodSafeParseRes
|
|
|
4182
4185
|
expires: number;
|
|
4183
4186
|
httpOnly: boolean;
|
|
4184
4187
|
secure: boolean;
|
|
4185
|
-
sameSite: "
|
|
4188
|
+
sameSite: "Lax" | "None" | "Strict";
|
|
4186
4189
|
}[];
|
|
4187
4190
|
origins: {
|
|
4188
4191
|
origin: string;
|
|
@@ -4923,4 +4926,7 @@ export declare function safeParseProgramResult(data: unknown): z.ZodSafeParseRes
|
|
|
4923
4926
|
defaultValues: Record<string, string>[];
|
|
4924
4927
|
replaceExisting?: boolean | undefined;
|
|
4925
4928
|
}[] | undefined;
|
|
4929
|
+
deviceConfigs?: Record<string, Record<string, unknown>> | undefined;
|
|
4930
|
+
publicUrl?: string | undefined;
|
|
4931
|
+
environmentHttpHeaders?: Record<string, string> | undefined;
|
|
4926
4932
|
}>;
|
package/dist/execution-schema.js
CHANGED
|
@@ -652,6 +652,18 @@ export const ExecutionProgramSchema = z.object({
|
|
|
652
652
|
compiledAt: z.string().datetime(),
|
|
653
653
|
compiledWith: z.string().optional(),
|
|
654
654
|
mockDataGroups: z.array(MockDataGroupSchema).optional(),
|
|
655
|
+
// Server-embedded device frame configs. Shape is governed by the
|
|
656
|
+
// `device_mockups.config` JSON column; we accept anything the server stores
|
|
657
|
+
// and let mockup.ts validate structurally at use time.
|
|
658
|
+
deviceConfigs: z.record(z.string().min(1), z.record(z.string(), z.unknown())).optional(),
|
|
659
|
+
// Project-level public URL used to rewrite the captured origin when
|
|
660
|
+
// decorating browser mockups. Validated only as a non-empty string here;
|
|
661
|
+
// the runtime parses it with `new URL()` and falls back gracefully.
|
|
662
|
+
publicUrl: z.string().min(1).optional(),
|
|
663
|
+
// Auth headers attached to the resolved project environment. Key/value
|
|
664
|
+
// pairs that Playwright will inject as `extraHTTPHeaders` on the
|
|
665
|
+
// BrowserContext so protected staging/preview URLs load successfully.
|
|
666
|
+
environmentHttpHeaders: z.record(z.string().min(1), z.string().min(1)).optional(),
|
|
655
667
|
}).strict().superRefine((value, ctx) => {
|
|
656
668
|
if (value.mediaMode !== value.artifactPlan.mediaMode) {
|
|
657
669
|
ctx.addIssue({
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* preset (natural language) -> ExecutionProgram (typed IR) -> deterministic runtime
|
|
6
6
|
*/
|
|
7
7
|
import type { AKTree, BrowserStorageState, BrowserSessionStorageState, OutscaleConfig, VideoCursorTheme, VideoPageSignals } from './types.js';
|
|
8
|
-
import type { MockupOptions } from './mockup.js';
|
|
8
|
+
import type { DeviceConfig, MockupOptions } from './mockup.js';
|
|
9
|
+
export type { DeviceConfig };
|
|
9
10
|
/** Sentinel value that resolves to the current variant's locale or theme at runtime */
|
|
10
11
|
export declare const VARIANT_PLACEHOLDER: "$variant";
|
|
11
12
|
export declare const OPCODE_KINDS: readonly ["NAVIGATE", "DISMISS_OVERLAYS", "ASSERT_ROUTE", "ASSERT_SURFACE", "CLICK", "TYPE", "PRESS_KEY", "WAIT_FOR", "SLEEP", "SET_LOCALE", "SET_THEME", "SCROLL", "CAPTURE_SCREENSHOT", "BEGIN_CLIP", "END_CLIP", "HOVER", "SELECT_OPTION", "CHECK", "DOUBLE_CLICK", "DRAG", "CLONE_ELEMENT", "INJECT_MOCK_DATA", "REMOVE_ELEMENT", "SET_ATTRIBUTE"];
|
|
@@ -557,6 +558,28 @@ export interface ExecutionProgram {
|
|
|
557
558
|
* Compiled from PresetConfig.mockDataInjection.groups by the server.
|
|
558
559
|
*/
|
|
559
560
|
mockDataGroups?: MockDataGroup[];
|
|
561
|
+
/**
|
|
562
|
+
* Server-embedded device frame configs for every `deviceFrame` referenced by
|
|
563
|
+
* `variants[]`. The CLI seeds its mockup engine with these so it does not
|
|
564
|
+
* need direct Supabase access (end-users do not have the service role key).
|
|
565
|
+
* Keyed by the exact deviceFrame string used in the variants.
|
|
566
|
+
*/
|
|
567
|
+
deviceConfigs?: Record<string, DeviceConfig>;
|
|
568
|
+
/**
|
|
569
|
+
* Project-level public URL used to decorate browser mockups. The CLI
|
|
570
|
+
* substitutes the captured origin (typically a local dev server) with this
|
|
571
|
+
* value via `transformBrowserUrl` before baking it into the browser bar.
|
|
572
|
+
* Server-resolved from `projects.public_url`.
|
|
573
|
+
*/
|
|
574
|
+
publicUrl?: string;
|
|
575
|
+
/**
|
|
576
|
+
* Auth headers attached to the resolved project environment (Bearer token,
|
|
577
|
+
* Vercel protection bypass, x-api-key, etc.). Injected into the Playwright
|
|
578
|
+
* BrowserContext so requests to protected staging/preview URLs go through.
|
|
579
|
+
* Decrypted server-side from `project_environments.auth_headers_encrypted`
|
|
580
|
+
* and embedded in the signed program envelope.
|
|
581
|
+
*/
|
|
582
|
+
environmentHttpHeaders?: Record<string, string>;
|
|
560
583
|
}
|
|
561
584
|
export interface CircuitBreakerConfig {
|
|
562
585
|
/** Max recovery attempts per opcode. Default: 3 */
|
|
@@ -629,6 +652,8 @@ export interface ArtifactResult {
|
|
|
629
652
|
altText?: string;
|
|
630
653
|
/** Final URL at the time the artifact was produced */
|
|
631
654
|
captureUrl?: string;
|
|
655
|
+
/** Document title at the time the artifact was produced (page.title()) */
|
|
656
|
+
pageTitle?: string;
|
|
632
657
|
/** Step index that produced the artifact */
|
|
633
658
|
stepIndex?: number;
|
|
634
659
|
/** Human-readable label for the artifact */
|
|
@@ -855,6 +880,13 @@ export interface RuntimeAdapter {
|
|
|
855
880
|
buffer: Buffer;
|
|
856
881
|
mimeType: string;
|
|
857
882
|
} | null>;
|
|
883
|
+
/**
|
|
884
|
+
* Document title of the current page (Playwright's `page.title()`). Captured
|
|
885
|
+
* at screenshot time and stored on the artifact metadata so browser mockups
|
|
886
|
+
* can render the actual page title instead of just the hostname. Optional —
|
|
887
|
+
* adapters that cannot resolve a title should leave this method off.
|
|
888
|
+
*/
|
|
889
|
+
getPageTitle?(): Promise<string | null>;
|
|
858
890
|
/**
|
|
859
891
|
* Read the captured app's version from the live page (meta tag, window
|
|
860
892
|
* global, or data attribute). Mirrors `extractAppVersionFromHtml` server-side
|
|
@@ -958,4 +990,3 @@ export interface RuntimeAdapter {
|
|
|
958
990
|
selector: string;
|
|
959
991
|
}): Promise<void>;
|
|
960
992
|
}
|
|
961
|
-
export {};
|
package/dist/mockup.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export interface DeviceFrameDefinition {
|
|
|
11
11
|
height: number;
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
export type DeviceOrientation = 'portrait' | 'landscape';
|
|
15
|
+
export interface OrientationConfigData {
|
|
15
16
|
screen: {
|
|
16
17
|
logicalWidth: number;
|
|
17
18
|
logicalHeight: number;
|
|
@@ -103,6 +104,69 @@ interface OrientationConfigData {
|
|
|
103
104
|
right?: string;
|
|
104
105
|
};
|
|
105
106
|
}
|
|
107
|
+
export interface DeviceConfig {
|
|
108
|
+
id: string;
|
|
109
|
+
name: string;
|
|
110
|
+
category: DeviceCategory;
|
|
111
|
+
platform: string;
|
|
112
|
+
frameOrientation?: 'portrait' | 'landscape';
|
|
113
|
+
supportedOrientations?: ('portrait' | 'landscape')[];
|
|
114
|
+
orientations?: {
|
|
115
|
+
portrait?: OrientationConfigData;
|
|
116
|
+
landscape?: OrientationConfigData;
|
|
117
|
+
};
|
|
118
|
+
/** Row-level frame_url (shared fallback for all orientations) */
|
|
119
|
+
_rowFrameUrl?: string;
|
|
120
|
+
screen: {
|
|
121
|
+
logicalWidth: number;
|
|
122
|
+
logicalHeight: number;
|
|
123
|
+
scale: number;
|
|
124
|
+
cornerRadius: number;
|
|
125
|
+
};
|
|
126
|
+
viewport: {
|
|
127
|
+
width: number;
|
|
128
|
+
height: number;
|
|
129
|
+
};
|
|
130
|
+
safeArea?: {
|
|
131
|
+
top: number;
|
|
132
|
+
bottom: number;
|
|
133
|
+
left?: number;
|
|
134
|
+
right?: number;
|
|
135
|
+
};
|
|
136
|
+
statusBar?: {
|
|
137
|
+
asset: string;
|
|
138
|
+
height: number;
|
|
139
|
+
width: number;
|
|
140
|
+
type?: StatusBarDeviceType;
|
|
141
|
+
layout?: StatusBarLayout;
|
|
142
|
+
};
|
|
143
|
+
homeIndicator?: {
|
|
144
|
+
width: number;
|
|
145
|
+
height: number;
|
|
146
|
+
cornerRadius: number;
|
|
147
|
+
bottomOffset: number;
|
|
148
|
+
};
|
|
149
|
+
frame: {
|
|
150
|
+
type: 'png' | 'svg';
|
|
151
|
+
asset: string;
|
|
152
|
+
width: number;
|
|
153
|
+
height: number;
|
|
154
|
+
screenRect: {
|
|
155
|
+
x: number;
|
|
156
|
+
y: number;
|
|
157
|
+
width: number;
|
|
158
|
+
height: number;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
frameRotation?: number;
|
|
162
|
+
frameBehindContent?: boolean;
|
|
163
|
+
windowBorder?: OrientationConfigData['windowBorder'];
|
|
164
|
+
frameDarkUrl?: string;
|
|
165
|
+
browserBarZones?: OrientationConfigData['browserBarZones'];
|
|
166
|
+
browserStyle?: OrientationConfigData['browserStyle'];
|
|
167
|
+
adminShowStatusBar?: OrientationConfigData['adminShowStatusBar'];
|
|
168
|
+
adminForcedSafeAreaColors?: OrientationConfigData['adminForcedSafeAreaColors'];
|
|
169
|
+
}
|
|
106
170
|
export type MockupOrientation = 'portrait' | 'landscape';
|
|
107
171
|
export interface MockupOptions {
|
|
108
172
|
orientation?: MockupOrientation;
|
|
@@ -184,6 +248,7 @@ export interface ResolvedDeviceFrameDescriptor {
|
|
|
184
248
|
disableOverlays: boolean;
|
|
185
249
|
}
|
|
186
250
|
export declare function invalidateDeviceConfigCache(): void;
|
|
251
|
+
export declare function seedDeviceConfigs(configs: Record<string, DeviceConfig> | null | undefined): void;
|
|
187
252
|
export declare function resolveDeviceFrameDescriptor(id: DeviceFrameId, options?: {
|
|
188
253
|
orientation?: MockupOrientation;
|
|
189
254
|
}): Promise<ResolvedDeviceFrameDescriptor | null>;
|
|
@@ -191,4 +256,3 @@ export declare function rasterizeDeviceFrame(descriptor: ResolvedDeviceFrameDesc
|
|
|
191
256
|
export declare function getDeviceFrames(): Promise<DeviceFrameDefinition[]>;
|
|
192
257
|
export declare function getDeviceFrame(id: DeviceFrameId): Promise<DeviceFrameDefinition | undefined>;
|
|
193
258
|
export declare function applyDeviceFrame(screenshot: Buffer, deviceId: DeviceFrameId, options?: MockupOptions): Promise<Buffer>;
|
|
194
|
-
export {};
|
package/dist/mockup.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { renderStatusBarBuffer } from './status-bar-render.js';
|
|
6
6
|
import { generateBrowserBarSvg } from './browser-bar.js';
|
|
7
7
|
import { computeMockupLayout } from './mockup-html.js';
|
|
8
|
+
import { logger } from './logger.js';
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = path.dirname(__filename);
|
|
10
11
|
const DEVICES_DIR = path.join(__dirname, '..', 'assets', 'devices');
|
|
@@ -144,7 +145,23 @@ function resolveOrientationConfig(config, requestedOrientation) {
|
|
|
144
145
|
adminForcedSafeAreaColors: config.adminForcedSafeAreaColors,
|
|
145
146
|
};
|
|
146
147
|
}
|
|
148
|
+
// Server-provided device configs embedded in signed execution programs. When
|
|
149
|
+
// set, these short-circuit `loadDeviceConfigs` — the CLI does not need direct
|
|
150
|
+
// Supabase access (and end-users do not have the service role key) because the
|
|
151
|
+
// server already vetted every device referenced by the program's variants and
|
|
152
|
+
// inlined the rows.
|
|
153
|
+
let seededDeviceConfigs = null;
|
|
154
|
+
export function seedDeviceConfigs(configs) {
|
|
155
|
+
if (!configs || Object.keys(configs).length === 0) {
|
|
156
|
+
seededDeviceConfigs = null;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
seededDeviceConfigs = new Map(Object.entries(configs));
|
|
160
|
+
}
|
|
147
161
|
async function loadDeviceConfigs() {
|
|
162
|
+
if (seededDeviceConfigs && seededDeviceConfigs.size > 0) {
|
|
163
|
+
return seededDeviceConfigs;
|
|
164
|
+
}
|
|
148
165
|
if (configCache && configCache.expiresAt > Date.now()) {
|
|
149
166
|
return configCache.configs;
|
|
150
167
|
}
|
|
@@ -478,12 +495,12 @@ export async function applyDeviceFrame(screenshot, deviceId, options) {
|
|
|
478
495
|
const isBrowserDevice = config.category === 'browser';
|
|
479
496
|
const os = Math.max(0.5, Math.min(4, opts.outputScale));
|
|
480
497
|
const geometry = computeResolvedFrameGeometry(resolved);
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
498
|
+
logger.debug(`[mockup] applyDeviceFrame: id=${deviceId}, category=${config.category}, orientation=${requestedOrientation}`);
|
|
499
|
+
logger.debug(`[mockup] hasOrientationConfig=${!!config.orientations?.[requestedOrientation]}, orientations=${JSON.stringify(Object.keys(config.orientations ?? {}))}`);
|
|
500
|
+
logger.debug(`[mockup] resolved.screen: ${JSON.stringify(resolved.screen)}`);
|
|
501
|
+
logger.debug(`[mockup] resolved.frame: w=${resolved.frame.width} h=${resolved.frame.height} asset="${resolved.frame.asset}" url=${resolved.frameUrl ? 'yes' : 'no'}`);
|
|
502
|
+
logger.debug(`[mockup] resolved.safeArea: ${JSON.stringify(resolved.safeArea)}`);
|
|
503
|
+
logger.debug(`[mockup] scale=${scale}, outputScale=${os}`);
|
|
487
504
|
// Browser devices can work without a frame image
|
|
488
505
|
const hasFrame = !!(resolved.frameUrl || resolved.frame.asset);
|
|
489
506
|
let frameData = null;
|
|
@@ -509,7 +526,7 @@ export async function applyDeviceFrame(screenshot, deviceId, options) {
|
|
|
509
526
|
geo.frameWidth = logicalW;
|
|
510
527
|
geo.frameHeight = logicalH;
|
|
511
528
|
geo.screenRect = { x: 0, y: 0, width: logicalW, height: logicalH };
|
|
512
|
-
|
|
529
|
+
logger.debug(`[mockup] frameless browser: logicalW=${logicalW}, logicalH=${logicalH}, os=${os}, geo=${geo.frameWidth}x${geo.frameHeight}`);
|
|
513
530
|
}
|
|
514
531
|
else if (!hasFrame && geo.frameWidth === 0 && geo.frameHeight === 0) {
|
|
515
532
|
// Non-browser frameless fallback
|
|
@@ -551,21 +568,21 @@ export async function applyDeviceFrame(screenshot, deviceId, options) {
|
|
|
551
568
|
});
|
|
552
569
|
const contentW = layout.contentArea.width;
|
|
553
570
|
const contentH = layout.contentArea.height;
|
|
554
|
-
|
|
555
|
-
|
|
571
|
+
logger.debug(`[mockup] hasFrame=${hasFrame}, geo: fw=${geo.frameWidth} fh=${geo.frameHeight} sr=${JSON.stringify(geo.screenRect)}`);
|
|
572
|
+
logger.debug(`[mockup] layout: container=${layout.containerWidth}x${layout.containerHeight} content=${contentW}x${contentH} contentArea=${JSON.stringify(layout.contentArea)}`);
|
|
556
573
|
// Get incoming screenshot dimensions for logging
|
|
557
574
|
const screenshotMeta = await sharp(screenshot).metadata();
|
|
558
|
-
|
|
575
|
+
logger.debug(`[mockup] input screenshot: ${screenshotMeta.width}x${screenshotMeta.height}`);
|
|
559
576
|
const physicalContentW = Math.round(contentW * os);
|
|
560
577
|
const physicalContentH = Math.round(contentH * os);
|
|
561
|
-
|
|
578
|
+
logger.debug(`[mockup] resize target: ${physicalContentW}x${physicalContentH}`);
|
|
562
579
|
if (screenshotMeta.width
|
|
563
580
|
&& screenshotMeta.height
|
|
564
581
|
&& (Math.abs(screenshotMeta.width - physicalContentW) > 1
|
|
565
582
|
|| Math.abs(screenshotMeta.height - physicalContentH) > 1)) {
|
|
566
583
|
const ratioX = physicalContentW / screenshotMeta.width;
|
|
567
584
|
const ratioY = physicalContentH / screenshotMeta.height;
|
|
568
|
-
|
|
585
|
+
logger.debug(`[mockup] screenshot will be resampled: ` +
|
|
569
586
|
`${screenshotMeta.width}x${screenshotMeta.height} -> ` +
|
|
570
587
|
`${physicalContentW}x${physicalContentH} ` +
|
|
571
588
|
`(x=${ratioX.toFixed(4)}, y=${ratioY.toFixed(4)}). ` +
|
|
@@ -597,7 +614,7 @@ export async function applyDeviceFrame(screenshot, deviceId, options) {
|
|
|
597
614
|
colors.leftColor = sanitizeCssColor(opts.safeAreaLeftColor);
|
|
598
615
|
if (opts.safeAreaRightColor)
|
|
599
616
|
colors.rightColor = sanitizeCssColor(opts.safeAreaRightColor);
|
|
600
|
-
|
|
617
|
+
logger.debug(`[mockup] sampled colors: top=${colors.topColor} bottom=${colors.bottomColor} left=${colors.leftColor} right=${colors.rightColor}`);
|
|
601
618
|
// Determine color scheme: use explicit override if provided, otherwise auto-detect from edge colors.
|
|
602
619
|
// Laptops (MacBook) always use dark menu bar (white text on black background).
|
|
603
620
|
const isLaptop = config.category === 'laptop';
|
|
@@ -664,7 +681,7 @@ export async function applyDeviceFrame(screenshot, deviceId, options) {
|
|
|
664
681
|
const renderW = Math.round(geo.frameWidth);
|
|
665
682
|
const renderH = Math.round(geo.frameHeight);
|
|
666
683
|
const cornerRadius = (resolved.screen?.cornerRadius ?? 0) * scale;
|
|
667
|
-
|
|
684
|
+
logger.debug(`[mockup] composeMockup: ${renderW}x${renderH} @${os}x, showBrowserBar=${isBrowserDevice}, windowBorderWidth=${wbw}`);
|
|
668
685
|
// ── Sharp compositing — layer-by-layer mockup assembly ──
|
|
669
686
|
// All dimensions in physical pixels (logical * os).
|
|
670
687
|
const pw = Math.round(renderW * os);
|
package/dist/opcode-runner.js
CHANGED
|
@@ -708,12 +708,21 @@ async function executeOpcodeAction(opcode, opcodeIndex, adapter, artifacts, tele
|
|
|
708
708
|
tabIconMimeType = favicon.mimeType;
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
|
+
// Capture document title so browser mockups can render the real tab
|
|
712
|
+
// title instead of falling back to the hostname.
|
|
713
|
+
let pageTitle;
|
|
714
|
+
if (adapter.getPageTitle) {
|
|
715
|
+
const resolved = await adapter.getPageTitle();
|
|
716
|
+
if (resolved)
|
|
717
|
+
pageTitle = resolved;
|
|
718
|
+
}
|
|
711
719
|
artifacts.push({
|
|
712
720
|
mediaMode: 'screenshot',
|
|
713
721
|
buffer,
|
|
714
722
|
mimeType: 'image/png',
|
|
715
723
|
captureType: opcode.elementSelector ? 'element' : 'fullpage',
|
|
716
724
|
captureUrl,
|
|
725
|
+
pageTitle,
|
|
717
726
|
dimensions: currentVariant?.viewport,
|
|
718
727
|
captureId: opcode.captureId,
|
|
719
728
|
captureName: opcode.captureName ?? opcode.description,
|
|
@@ -121,9 +121,9 @@ export declare const SignedExecutionProgramEnvelopeSchema: z.ZodObject<{
|
|
|
121
121
|
httpOnly: z.ZodBoolean;
|
|
122
122
|
secure: z.ZodBoolean;
|
|
123
123
|
sameSite: z.ZodEnum<{
|
|
124
|
-
Strict: "Strict";
|
|
125
124
|
Lax: "Lax";
|
|
126
125
|
None: "None";
|
|
126
|
+
Strict: "Strict";
|
|
127
127
|
}>;
|
|
128
128
|
}, z.core.$strict>>;
|
|
129
129
|
origins: z.ZodArray<z.ZodObject<{
|
|
@@ -1126,6 +1126,9 @@ export declare const SignedExecutionProgramEnvelopeSchema: z.ZodObject<{
|
|
|
1126
1126
|
defaultValues: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1127
1127
|
replaceExisting: z.ZodOptional<z.ZodBoolean>;
|
|
1128
1128
|
}, z.core.$strict>>>;
|
|
1129
|
+
deviceConfigs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1130
|
+
publicUrl: z.ZodOptional<z.ZodString>;
|
|
1131
|
+
environmentHttpHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1129
1132
|
}, z.core.$strict>;
|
|
1130
1133
|
signature: z.ZodString;
|
|
1131
1134
|
meta: z.ZodOptional<z.ZodObject<{
|
package/dist/program-signing.js
CHANGED
|
@@ -102,6 +102,10 @@ export function signExecutionProgramEnvelope(params) {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
export function verifySignedExecutionProgramEnvelope(params) {
|
|
105
|
+
// The Zod schema describes `deviceConfigs` as a loose record (the server is
|
|
106
|
+
// the source of truth for the rich DeviceConfig shape). Cast to the strongly
|
|
107
|
+
// typed envelope at this trust boundary — the signature verification below
|
|
108
|
+
// proves the server produced this payload.
|
|
105
109
|
const envelope = SignedExecutionProgramEnvelopeSchema.parse(params.envelope);
|
|
106
110
|
const payload = {
|
|
107
111
|
signedAt: envelope.signedAt,
|
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
export type SkillType = 'preset';
|
|
2
|
-
export type SkillAgent = 'claude' | 'codex' | 'cursor' | 'windsurf' | 'copilot';
|
|
3
2
|
export interface SkillPlaceholderOptions {
|
|
4
3
|
projectUrl?: string;
|
|
5
4
|
projectId?: string;
|
|
6
5
|
apiBaseUrl?: string;
|
|
7
6
|
}
|
|
8
|
-
export interface SkillExportResult {
|
|
9
|
-
mode: 'single-file' | 'bundle';
|
|
10
|
-
writtenPaths: string[];
|
|
11
|
-
}
|
|
12
7
|
export declare function resolveSkillAssetDir(): Promise<string>;
|
|
13
|
-
export declare function shouldInstallSkillBundle(params: {
|
|
14
|
-
agent?: string;
|
|
15
|
-
outputPath?: string;
|
|
16
|
-
type: SkillType;
|
|
17
|
-
}): boolean;
|
|
18
8
|
export declare function renderSkillSingleFile(params: {
|
|
19
9
|
type: SkillType;
|
|
20
10
|
agent?: string;
|
|
21
11
|
placeholders: SkillPlaceholderOptions;
|
|
22
12
|
}): Promise<string>;
|
|
23
|
-
export declare function writeSkillExport(params: {
|
|
24
|
-
type: SkillType;
|
|
25
|
-
agent?: string;
|
|
26
|
-
outputPath: string;
|
|
27
|
-
placeholders: SkillPlaceholderOptions;
|
|
28
|
-
}): Promise<SkillExportResult>;
|
package/dist/skill-packaging.js
CHANGED
|
@@ -17,6 +17,7 @@ const PRESET_SKILL_SOURCE = {
|
|
|
17
17
|
coreFile: 'SKILL.md',
|
|
18
18
|
references: [
|
|
19
19
|
{ relativePath: 'OPCODE-REFERENCE.md', title: 'Opcode Reference', anchor: 'reference-opcode-reference' },
|
|
20
|
+
{ relativePath: 'references/STANDARDS.md', title: 'Prompt Charter & Quality Standards', anchor: 'reference-prompt-standards' },
|
|
20
21
|
{ relativePath: 'references/mock-data.md', title: 'Mock Data Injection', anchor: 'reference-mock-data-injection' },
|
|
21
22
|
{ relativePath: 'references/examples.md', title: 'Complete Examples', anchor: 'reference-complete-examples' },
|
|
22
23
|
],
|
|
@@ -57,23 +58,6 @@ export async function resolveSkillAssetDir() {
|
|
|
57
58
|
}
|
|
58
59
|
throw new Error('Could not find assets/skill. Make sure the autokap package is installed correctly.');
|
|
59
60
|
}
|
|
60
|
-
function inferBundleInstall(outputPath) {
|
|
61
|
-
if (!outputPath)
|
|
62
|
-
return false;
|
|
63
|
-
const normalized = path.normalize(outputPath);
|
|
64
|
-
const parts = normalized.split(path.sep).filter(Boolean);
|
|
65
|
-
for (let index = 0; index < parts.length - 1; index += 1) {
|
|
66
|
-
if (parts[index] === '.agents' && parts[index + 1] === 'skills') {
|
|
67
|
-
return path.basename(normalized) === 'SKILL.md';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
export function shouldInstallSkillBundle(params) {
|
|
73
|
-
if (params.agent?.toLowerCase() === 'codex')
|
|
74
|
-
return true;
|
|
75
|
-
return inferBundleInstall(params.outputPath);
|
|
76
|
-
}
|
|
77
61
|
async function readSkillFile(rootDir, relativePath, placeholders) {
|
|
78
62
|
const absolutePath = path.join(rootDir, relativePath);
|
|
79
63
|
const raw = await fs.readFile(absolutePath, 'utf-8');
|
|
@@ -122,38 +106,4 @@ export async function renderSkillSingleFile(params) {
|
|
|
122
106
|
}
|
|
123
107
|
return [core, ...bundledReferences].join('\n\n');
|
|
124
108
|
}
|
|
125
|
-
export async function writeSkillExport(params) {
|
|
126
|
-
const rootDir = await resolveSkillAssetDir();
|
|
127
|
-
const spec = getSkillSourceSpec(params.type);
|
|
128
|
-
if (shouldInstallSkillBundle({
|
|
129
|
-
agent: params.agent,
|
|
130
|
-
outputPath: params.outputPath,
|
|
131
|
-
type: params.type,
|
|
132
|
-
})) {
|
|
133
|
-
const destinationDir = path.dirname(params.outputPath);
|
|
134
|
-
const writtenPaths = [];
|
|
135
|
-
for (const relativePath of [spec.coreFile, ...spec.references.map((reference) => reference.relativePath)]) {
|
|
136
|
-
const absolutePath = path.join(destinationDir, relativePath);
|
|
137
|
-
const content = await readSkillFile(rootDir, relativePath, params.placeholders);
|
|
138
|
-
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
139
|
-
await fs.writeFile(absolutePath, content, 'utf-8');
|
|
140
|
-
writtenPaths.push(absolutePath);
|
|
141
|
-
}
|
|
142
|
-
return {
|
|
143
|
-
mode: 'bundle',
|
|
144
|
-
writtenPaths,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
const content = await renderSkillSingleFile({
|
|
148
|
-
type: params.type,
|
|
149
|
-
agent: params.agent,
|
|
150
|
-
placeholders: params.placeholders,
|
|
151
|
-
});
|
|
152
|
-
await fs.mkdir(path.dirname(params.outputPath), { recursive: true });
|
|
153
|
-
await fs.writeFile(params.outputPath, content, 'utf-8');
|
|
154
|
-
return {
|
|
155
|
-
mode: 'single-file',
|
|
156
|
-
writtenPaths: [params.outputPath],
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
109
|
//# sourceMappingURL=skill-packaging.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform a captured URL for display in the browser bar mockup.
|
|
3
|
+
* 1. Replace the origin with `publicUrl` (if provided).
|
|
4
|
+
* 2. Strip UUID v4 path segments.
|
|
5
|
+
*/
|
|
6
|
+
export declare function transformBrowserUrl(capturedUrl: string, publicUrl?: string | null): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2
|
+
/**
|
|
3
|
+
* Transform a captured URL for display in the browser bar mockup.
|
|
4
|
+
* 1. Replace the origin with `publicUrl` (if provided).
|
|
5
|
+
* 2. Strip UUID v4 path segments.
|
|
6
|
+
*/
|
|
7
|
+
export function transformBrowserUrl(capturedUrl, publicUrl) {
|
|
8
|
+
let parsed;
|
|
9
|
+
try {
|
|
10
|
+
parsed = new URL(capturedUrl);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return capturedUrl;
|
|
14
|
+
}
|
|
15
|
+
if (publicUrl) {
|
|
16
|
+
try {
|
|
17
|
+
const pub = new URL(publicUrl);
|
|
18
|
+
parsed = new URL(`${pub.origin}${parsed.pathname}${parsed.search}${parsed.hash}`);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// invalid publicUrl — skip origin replacement
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const segments = parsed.pathname.split("/").filter((s) => s && !UUID_RE.test(s));
|
|
25
|
+
parsed.pathname = "/" + segments.join("/");
|
|
26
|
+
return parsed.toString().replace(/\/$/, "") || parsed.origin;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=transform-browser-url.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -246,6 +246,17 @@ export interface BrowserOptions {
|
|
|
246
246
|
colorScheme?: 'light' | 'dark';
|
|
247
247
|
/** Optional persisted cookies/localStorage captured during preparation. */
|
|
248
248
|
storageState?: BrowserStorageState;
|
|
249
|
+
/**
|
|
250
|
+
* Extra HTTP headers injected on every navigation. Used to carry the
|
|
251
|
+
* environment-level auth (Bearer token, Vercel protection bypass, x-api-key,
|
|
252
|
+
* etc.) configured on the resolved `project_environments` row.
|
|
253
|
+
*
|
|
254
|
+
* These headers are sent to ALL requests the BrowserContext makes during
|
|
255
|
+
* capture, including cross-origin requests (third-party CDN, analytics).
|
|
256
|
+
* The dashboard surfaces a warning so users only put environment-scoped
|
|
257
|
+
* secrets here.
|
|
258
|
+
*/
|
|
259
|
+
extraHttpHeaders?: Record<string, string>;
|
|
249
260
|
}
|
|
250
261
|
export interface OutscaleConfig {
|
|
251
262
|
/** Uniform padding on all 4 sides (pixels). */
|
|
@@ -147,9 +147,9 @@ export declare const VideoIngestPayloadSchema: z.ZodObject<{
|
|
|
147
147
|
httpOnly: z.ZodBoolean;
|
|
148
148
|
secure: z.ZodBoolean;
|
|
149
149
|
sameSite: z.ZodEnum<{
|
|
150
|
-
Strict: "Strict";
|
|
151
150
|
Lax: "Lax";
|
|
152
151
|
None: "None";
|
|
152
|
+
Strict: "Strict";
|
|
153
153
|
}>;
|
|
154
154
|
}, z.core.$strict>>;
|
|
155
155
|
origins: z.ZodArray<z.ZodObject<{
|
|
@@ -1152,6 +1152,9 @@ export declare const VideoIngestPayloadSchema: z.ZodObject<{
|
|
|
1152
1152
|
defaultValues: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1153
1153
|
replaceExisting: z.ZodOptional<z.ZodBoolean>;
|
|
1154
1154
|
}, z.core.$strict>>>;
|
|
1155
|
+
deviceConfigs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1156
|
+
publicUrl: z.ZodOptional<z.ZodString>;
|
|
1157
|
+
environmentHttpHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1155
1158
|
}, z.core.$strict>;
|
|
1156
1159
|
narration: z.ZodOptional<z.ZodObject<{
|
|
1157
1160
|
voice: z.ZodString;
|
|
@@ -27,6 +27,7 @@ export declare class WebPlaywrightLocal implements RuntimeAdapter {
|
|
|
27
27
|
constructor(browser: Browser, recordingDir?: string | undefined);
|
|
28
28
|
navigate(url: string): Promise<void>;
|
|
29
29
|
getCurrentUrl(): Promise<string>;
|
|
30
|
+
getPageTitle(): Promise<string | null>;
|
|
30
31
|
detectAppVersion(): Promise<string | null>;
|
|
31
32
|
getAKTree(): Promise<AKTree>;
|
|
32
33
|
getPageSignals(): Promise<VideoPageSignals>;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autokap",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "AI-powered CLI tool for capturing clean screenshots of websites",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -181,14 +181,15 @@
|
|
|
181
181
|
"./program-signing": {
|
|
182
182
|
"types": "./dist/program-signing.d.ts",
|
|
183
183
|
"default": "./dist/program-signing.js"
|
|
184
|
+
},
|
|
185
|
+
"./transform-browser-url": {
|
|
186
|
+
"types": "./dist/transform-browser-url.d.ts",
|
|
187
|
+
"default": "./dist/transform-browser-url.js"
|
|
184
188
|
}
|
|
185
189
|
},
|
|
186
190
|
"bin": {
|
|
187
191
|
"autokap": "dist/cli.js"
|
|
188
192
|
},
|
|
189
|
-
"scripts": {
|
|
190
|
-
"postinstall": "node -e \"try{require('child_process').execSync('npx playwright install chromium',{stdio:'inherit'})}catch(e){console.warn('AutoKap: Playwright Chromium install failed. Run npx playwright install chromium manually.',e.message||'')}\""
|
|
191
|
-
},
|
|
192
193
|
"engines": {
|
|
193
194
|
"node": ">=20"
|
|
194
195
|
},
|
|
@@ -203,8 +204,7 @@
|
|
|
203
204
|
"assets/frames/MacBook*",
|
|
204
205
|
"assets/frames/Status*",
|
|
205
206
|
"assets/icons",
|
|
206
|
-
"assets/cursors"
|
|
207
|
-
"assets/skill"
|
|
207
|
+
"assets/cursors"
|
|
208
208
|
],
|
|
209
209
|
"keywords": [
|
|
210
210
|
"screenshot",
|
package/readme.md
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
# AutoKap
|
|
1
|
+
# AutoKap (backend package)
|
|
2
2
|
|
|
3
|
-
AI-powered website screenshot capture across every device, language, and
|
|
3
|
+
AI-powered website screenshot capture across every device, language, and
|
|
4
|
+
theme.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
This npm package (`autokap`) is the **backend** consumed by:
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
- the AutoKap Cloud Run service that handles
|
|
9
|
+
`npx autokap auto-recapture --cloud` jobs, and
|
|
10
|
+
- the official MCP server `@autokap/mcp`, which spawns the package as a
|
|
11
|
+
sub-process for local capture execution (`autokap_start_capture`).
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
**You probably do not need to install this package directly.** Wire your
|
|
14
|
+
IDE assistant to `@autokap/mcp` instead — see the per-IDE install guides
|
|
15
|
+
in the repository root README and the
|
|
16
|
+
[migration guide](https://github.com/autokap/autokap/blob/main/MIGRATION-v1-to-v2.md).
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
The advanced commands `autokap login`, `autokap run`, `autokap doctor`,
|
|
19
|
+
and `autokap auto-recapture` remain available for users who need a
|
|
20
|
+
scriptable backend (CI/CD, custom orchestrators).
|
|
18
21
|
|
|
19
22
|
## Recapture Cloud in CI/CD
|
|
20
23
|
|