@koda-sl/baker-cli 0.347.0-dev.043fc924c → 0.347.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +4 -4
  2. package/dist/{chunk-KGDL7F7M.js → chunk-2IC3CGQO.js} +3 -3
  3. package/dist/chunk-2OKSJNLA.js +855 -0
  4. package/dist/chunk-2OKSJNLA.js.map +1 -0
  5. package/dist/{chunk-XPUSSDLR.js → chunk-4QXKWIFC.js} +3 -3
  6. package/dist/{chunk-JWMLQSGK.js → chunk-NA5CPMUA.js} +4 -4
  7. package/dist/{chunk-PWGY347J.js → chunk-XWHHYHKQ.js} +2 -2
  8. package/dist/{chunk-D5P4COPD.js → chunk-YBD3W4M7.js} +9 -8
  9. package/dist/chunk-YBD3W4M7.js.map +1 -0
  10. package/dist/cli.js +357 -754
  11. package/dist/cli.js.map +1 -1
  12. package/dist/{client-PWRZOA3Q.js → client-ODCNYCP4.js} +4 -4
  13. package/dist/engine/index.js +3 -3
  14. package/dist/{env-TQTHWLBN.js → env-BSG7TY5Y.js} +6 -2
  15. package/dist/{output-HD63GTWI.js → output-2XBCYF7L.js} +5 -5
  16. package/dist/{shared-5662SBDW.js → shared-RYAF7Y7H.js} +6 -6
  17. package/package.json +1 -1
  18. package/dist/chunk-4VP5WWPR.js +0 -376
  19. package/dist/chunk-4VP5WWPR.js.map +0 -1
  20. package/dist/chunk-D5P4COPD.js.map +0 -1
  21. /package/dist/{chunk-KGDL7F7M.js.map → chunk-2IC3CGQO.js.map} +0 -0
  22. /package/dist/{chunk-XPUSSDLR.js.map → chunk-4QXKWIFC.js.map} +0 -0
  23. /package/dist/{chunk-JWMLQSGK.js.map → chunk-NA5CPMUA.js.map} +0 -0
  24. /package/dist/{chunk-PWGY347J.js.map → chunk-XWHHYHKQ.js.map} +0 -0
  25. /package/dist/{client-PWRZOA3Q.js.map → client-ODCNYCP4.js.map} +0 -0
  26. /package/dist/{env-TQTHWLBN.js.map → env-BSG7TY5Y.js.map} +0 -0
  27. /package/dist/{output-HD63GTWI.js.map → output-2XBCYF7L.js.map} +0 -0
  28. /package/dist/{shared-5662SBDW.js.map → shared-RYAF7Y7H.js.map} +0 -0
@@ -0,0 +1,855 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // ../proxy/src/challenge.ts
28
+ var CHALLENGE_PHRASES = [
29
+ "just a moment",
30
+ "attention required",
31
+ "verify you are human",
32
+ "checking your browser",
33
+ "enable javascript and cookies to continue",
34
+ "unusual traffic",
35
+ "access denied",
36
+ "you have been blocked",
37
+ "request unsuccessful",
38
+ "are you a robot",
39
+ "security check",
40
+ "ddos protection",
41
+ "captcha"
42
+ ];
43
+ var CHALLENGE_MARKERS = ["cf-browser-verification", "cf_chl_", "px-captcha", "_incapsula_", "distil_r_captcha"];
44
+ var CHALLENGE_LENGTH_CEILING = 2e3;
45
+ function isChallengeBody(content, title) {
46
+ if (content.length <= CHALLENGE_LENGTH_CEILING) {
47
+ const haystack = `${title ?? ""}
48
+ ${content}`.toLowerCase();
49
+ if (CHALLENGE_PHRASES.some((phrase) => haystack.includes(phrase))) return true;
50
+ }
51
+ const whole = content.toLowerCase();
52
+ return CHALLENGE_MARKERS.some((marker) => whole.includes(marker));
53
+ }
54
+
55
+ // ../proxy/src/tiers.ts
56
+ var PROXY_TIERS = {
57
+ datacenter: {
58
+ tier: "datacenter",
59
+ host: "dc.oxylabs.io",
60
+ port: 8e3,
61
+ usernamePrefix: "user-",
62
+ countryKey: "-country-",
63
+ sessionKey: null
64
+ },
65
+ residential: {
66
+ tier: "residential",
67
+ host: "pr.oxylabs.io",
68
+ port: 7777,
69
+ usernamePrefix: "customer-",
70
+ countryKey: "-cc-",
71
+ sessionKey: "-sessid-"
72
+ }
73
+ };
74
+ var ESCALATION_ORDER = ["datacenter", "residential"];
75
+ var KNOWN_USERNAME_PREFIXES = ["user-", "customer-"];
76
+
77
+ // ../proxy/src/credentials.ts
78
+ var PROXY_ENV_VARS = {
79
+ datacenter: { username: "OXYLABS_DATACENTER_USERNAME", password: "OXYLABS_DATACENTER_PASSWORD" },
80
+ residential: { username: "OXYLABS_RESIDENTIAL_USERNAME", password: "OXYLABS_RESIDENTIAL_PASSWORD" }
81
+ };
82
+ function readProxyCredentials(env) {
83
+ const credentials = {};
84
+ for (const tier of ESCALATION_ORDER) {
85
+ const username = env[PROXY_ENV_VARS[tier].username]?.trim();
86
+ const password = env[PROXY_ENV_VARS[tier].password]?.trim();
87
+ if (username && password) credentials[tier] = { username, password };
88
+ }
89
+ return credentials;
90
+ }
91
+ function configuredTiers(credentials) {
92
+ return ESCALATION_ORDER.filter((tier) => credentials[tier] !== void 0);
93
+ }
94
+
95
+ // ../proxy/src/escalate.ts
96
+ var ESCALATABLE_STATUSES = /* @__PURE__ */ new Set([403, 429, 451]);
97
+ var ESCALATABLE_NET_ERRORS = /* @__PURE__ */ new Set(["ERR_CONNECTION_RESET", "ERR_CONNECTION_CLOSED", "ERR_EMPTY_RESPONSE"]);
98
+ var PROXY_NET_ERRORS = /* @__PURE__ */ new Set([
99
+ "ERR_TUNNEL_CONNECTION_FAILED",
100
+ "ERR_PROXY_CONNECTION_FAILED",
101
+ "ERR_PROXY_AUTH_REQUESTED",
102
+ "ERR_PROXY_CERTIFICATE_INVALID",
103
+ "ERR_UNEXPECTED_PROXY_AUTH",
104
+ "ERR_MANDATORY_PROXY_CONFIGURATION_FAILED",
105
+ "ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT"
106
+ ]);
107
+ function isProxyFailure(signal) {
108
+ if (signal.status === 407) return true;
109
+ return signal.netError ? PROXY_NET_ERRORS.has(signal.netError) : false;
110
+ }
111
+ function shouldEscalate(signal) {
112
+ if (isProxyFailure(signal)) return false;
113
+ if (signal.timedOut) return false;
114
+ if (signal.challenge) return true;
115
+ if (signal.status != null && ESCALATABLE_STATUSES.has(signal.status)) return true;
116
+ return signal.netError ? ESCALATABLE_NET_ERRORS.has(signal.netError) : false;
117
+ }
118
+
119
+ // ../proxy/src/privateAddress.ts
120
+ function isPrivateIpv4Octets(octets) {
121
+ const [a, b] = octets;
122
+ if (a === 0) return true;
123
+ if (a === 10) return true;
124
+ if (a === 127) return true;
125
+ if (a === 169 && b === 254) return true;
126
+ if (a === 172 && b >= 16 && b <= 31) return true;
127
+ if (a === 192 && b === 168) return true;
128
+ if (a === 100 && b >= 64 && b <= 127) return true;
129
+ if (a >= 224) return true;
130
+ return false;
131
+ }
132
+ function parseIpv4(value) {
133
+ const parts = value.split(".");
134
+ if (parts.length !== 4) return null;
135
+ const octets = parts.map((part) => /^\d{1,3}$/.test(part) ? Number(part) : Number.NaN);
136
+ if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) return null;
137
+ return octets;
138
+ }
139
+ function expandGroups(part) {
140
+ if (part === "") return [];
141
+ const chunks = part.split(":");
142
+ const groups = [];
143
+ for (let index = 0; index < chunks.length; index++) {
144
+ const chunk = chunks[index];
145
+ if (chunk.includes(".")) {
146
+ if (index !== chunks.length - 1) return null;
147
+ const octets = parseIpv4(chunk);
148
+ if (!octets) return null;
149
+ groups.push(octets[0] << 8 | octets[1]);
150
+ groups.push(octets[2] << 8 | octets[3]);
151
+ continue;
152
+ }
153
+ if (!/^[0-9a-f]{1,4}$/.test(chunk)) return null;
154
+ groups.push(Number.parseInt(chunk, 16));
155
+ }
156
+ return groups;
157
+ }
158
+ function parseIpv6(value) {
159
+ const halves = value.split("::");
160
+ if (halves.length > 2) return null;
161
+ const head = expandGroups(halves[0]);
162
+ const tail = halves.length === 2 ? expandGroups(halves[1]) : [];
163
+ if (head === null || tail === null) return null;
164
+ if (halves.length === 1) return head.length === 8 ? head : null;
165
+ const missing = 8 - head.length - tail.length;
166
+ if (missing < 1) return null;
167
+ return [...head, ...new Array(missing).fill(0), ...tail];
168
+ }
169
+ function isPrivateAddress(ip) {
170
+ const address = ip.trim().toLowerCase();
171
+ if (!address) return true;
172
+ const v4 = parseIpv4(address);
173
+ if (v4) return isPrivateIpv4Octets(v4);
174
+ const v6 = parseIpv6(address);
175
+ if (!v6) return true;
176
+ const [g0, g1, g2, g3, g4, g5, g6, g7] = v6;
177
+ if (g0 === 0 && g1 === 0 && g2 === 0 && g3 === 0 && g4 === 0 && g5 === 0 && g6 === 0) return true;
178
+ const mappedV4 = g0 === 0 && g1 === 0 && g2 === 0 && g3 === 0;
179
+ if (mappedV4 && g4 === 0 && g5 === 65535) {
180
+ return isPrivateIpv4Octets([g6 >> 8, g6 & 255, g7 >> 8, g7 & 255]);
181
+ }
182
+ if (mappedV4 && g4 === 65535 && g5 === 0) {
183
+ return isPrivateIpv4Octets([g6 >> 8, g6 & 255, g7 >> 8, g7 & 255]);
184
+ }
185
+ if ((g0 & 65024) === 64512) return true;
186
+ if ((g0 & 65472) === 65152) return true;
187
+ return false;
188
+ }
189
+
190
+ // ../proxy/src/publicAddress.ts
191
+ var PRIVATE_HOST = /^(localhost|.*\.localhost|.*\.local)$/;
192
+ var SANDBOX_HOST = /\.e2b\.(app|dev)$/;
193
+ function unwrapIpLiteral(host) {
194
+ if (host.startsWith("[") && host.endsWith("]")) return host.slice(1, -1);
195
+ if (/^[0-9.]+$/.test(host) || host.includes(":")) return host;
196
+ return null;
197
+ }
198
+ function isPrivateHostname(hostname) {
199
+ const host = hostname.trim().toLowerCase();
200
+ if (!host) return true;
201
+ if (PRIVATE_HOST.test(host) || SANDBOX_HOST.test(host)) return true;
202
+ const literal = unwrapIpLiteral(host);
203
+ return literal === null ? false : isPrivateAddress(literal);
204
+ }
205
+ var BROWSER_PROXY_BYPASS = [
206
+ "localhost",
207
+ "*.localhost",
208
+ "127.0.0.1",
209
+ "0.0.0.0",
210
+ "::1",
211
+ "*.local",
212
+ // A Session's own preview, which is served from the sandbox's public host —
213
+ // public in DNS, ours in every sense that matters here.
214
+ "*.e2b.app",
215
+ "*.e2b.dev",
216
+ "10.*",
217
+ "192.168.*",
218
+ "169.254.*",
219
+ ...Array.from({ length: 16 }, (_, i) => `172.${16 + i}.*`)
220
+ ].join(",");
221
+ function refuseNonPublicUrl(url) {
222
+ let parsed;
223
+ try {
224
+ parsed = new URL(url);
225
+ } catch {
226
+ return "unparseable";
227
+ }
228
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return "not_public";
229
+ return isPrivateHostname(parsed.hostname) ? "not_public" : null;
230
+ }
231
+
232
+ // ../proxy/src/route.ts
233
+ var DIRECT_ROUTE = { kind: "direct" };
234
+ function proxyUsername(spec, rawUsername, options) {
235
+ const raw = rawUsername.trim();
236
+ const foreignPrefix = KNOWN_USERNAME_PREFIXES.find(
237
+ (prefix) => prefix !== spec.usernamePrefix && raw.startsWith(prefix)
238
+ );
239
+ if (foreignPrefix) return { ok: false, problem: "wrong_prefix" };
240
+ let username = raw.startsWith(spec.usernamePrefix) ? raw : `${spec.usernamePrefix}${raw}`;
241
+ if (options?.country) username += `${spec.countryKey}${options.country.toUpperCase()}`;
242
+ if (options?.session && spec.sessionKey) username += `${spec.sessionKey}${options.session}`;
243
+ return { ok: true, username };
244
+ }
245
+ function buildProxyRoute(tier, credentials, options) {
246
+ const held = credentials[tier];
247
+ if (!held) return { ok: false, problem: "missing" };
248
+ const spec = PROXY_TIERS[tier];
249
+ const username = proxyUsername(spec, held.username, options);
250
+ if (!username.ok) return username;
251
+ return {
252
+ ok: true,
253
+ route: {
254
+ kind: "proxy",
255
+ tier,
256
+ server: `http://${spec.host}:${spec.port}`,
257
+ username: username.username,
258
+ password: held.password
259
+ }
260
+ };
261
+ }
262
+
263
+ // ../proxy/src/ladder.ts
264
+ function plannedRoutes(url, credentials, options) {
265
+ if (refuseNonPublicUrl(url) !== null) return [DIRECT_ROUTE];
266
+ const routes = [DIRECT_ROUTE];
267
+ for (const tier of configuredTiers(credentials)) {
268
+ const built = buildProxyRoute(tier, credentials, options);
269
+ if (built.ok) routes.push(built.route);
270
+ }
271
+ return routes;
272
+ }
273
+
274
+ // src/env.ts
275
+ import { createEnv } from "@t3-oss/env-core";
276
+ import { z } from "zod";
277
+
278
+ // src/apiKeyFormat.ts
279
+ var KEY_PREFIXES = ["bk_", "bkr_"];
280
+ var API_KEY_FORMAT_MESSAGE = "API key must start with 'bk_' or 'bkr_'";
281
+ function isBakerApiKey(value) {
282
+ return KEY_PREFIXES.some((prefix) => value.startsWith(prefix));
283
+ }
284
+
285
+ // src/output.ts
286
+ var ASPECT_RATIO_MAP = {
287
+ "1:1": 1,
288
+ "16:9": 16 / 9,
289
+ "9:16": 9 / 16,
290
+ "2:3": 2 / 3,
291
+ "3:4": 3 / 4,
292
+ "1:2": 1 / 2,
293
+ "2:1": 2,
294
+ "4:5": 4 / 5,
295
+ "3:2": 3 / 2,
296
+ "4:3": 4 / 3
297
+ };
298
+ var ASPECT_RATIO_TOLERANCE = 0.08;
299
+ function formatAspectRatio(ratio) {
300
+ if (ratio === void 0 || ratio === null) {
301
+ return null;
302
+ }
303
+ for (const [label, value] of Object.entries(ASPECT_RATIO_MAP)) {
304
+ if (Math.abs(ratio - value) / value < ASPECT_RATIO_TOLERANCE) {
305
+ return label;
306
+ }
307
+ }
308
+ return null;
309
+ }
310
+ function groupSummary(record) {
311
+ const key = record.groupKey;
312
+ if (typeof key !== "string" || !key) {
313
+ return null;
314
+ }
315
+ const index = typeof record.groupIndex === "number" ? record.groupIndex : null;
316
+ const size = typeof record.groupSize === "number" ? record.groupSize : null;
317
+ return {
318
+ key,
319
+ kind: typeof record.groupKind === "string" ? record.groupKind : null,
320
+ position: index === null ? null : size === null ? `${index + 1}` : `${index + 1} of ${size}`,
321
+ title: typeof record.groupTitle === "string" ? record.groupTitle : null,
322
+ url: typeof record.groupUrl === "string" ? record.groupUrl : null
323
+ };
324
+ }
325
+ function peopleLines(value) {
326
+ if (!Array.isArray(value)) {
327
+ return [];
328
+ }
329
+ return value.flatMap((entry) => {
330
+ const person = asRecord(entry);
331
+ const role = typeof person.role === "string" ? person.role : "";
332
+ if (!role) {
333
+ return [];
334
+ }
335
+ const identity = typeof person.identity === "string" && person.identity ? ` \u2014 ${person.identity}` : "";
336
+ const appearance = typeof person.appearance === "string" && person.appearance ? ` (${person.appearance})` : "";
337
+ const speaking = person.speaking === true ? " [speaking]" : "";
338
+ return [`${role}${identity}${appearance}${speaking}`];
339
+ });
340
+ }
341
+ function compactImage(image) {
342
+ const analysis = asRecord(image.analysis);
343
+ return {
344
+ _id: String(image._id ?? ""),
345
+ name: String(image.name ?? ""),
346
+ imageUrl: String(image.imageUrl ?? ""),
347
+ description: String(image.description ?? ""),
348
+ tags: Array.isArray(image.tags) ? image.tags : [],
349
+ // Two numbers that are not about choosing the image but about placing it.
350
+ // A remote <BakerImage> with no width/height makes Astro DOWNLOAD the file
351
+ // at build time just to measure it — one request per image per build, on a
352
+ // build that is otherwise offline, and a single dropped connection there
353
+ // fails a client's whole verify. They are cheap enough to always carry, and
354
+ // burying them behind --full meant the agent placing the image never had
355
+ // them.
356
+ width: typeof image.width === "number" ? image.width : null,
357
+ height: typeof image.height === "number" ? image.height : null,
358
+ // The facts that decide a pick, so choosing does not need a second call:
359
+ // whose brand it is, who is in it, and what text is burned in.
360
+ subject: typeof analysis.subject === "string" ? analysis.subject : null,
361
+ brandOwnership: typeof analysis.brandOwnership === "string" ? analysis.brandOwnership : null,
362
+ people: peopleLines(analysis.people),
363
+ textInImage: Array.isArray(analysis.textInImage) ? analysis.textInImage : [],
364
+ group: groupSummary(image)
365
+ };
366
+ }
367
+ function fullImage(image) {
368
+ const compact = compactImage(image);
369
+ return {
370
+ ...compact,
371
+ aspectRatio: formatAspectRatio(image.aspectRatio),
372
+ dominantColor: image.dominantColor ?? null,
373
+ imagePalette: Array.isArray(image.imagePalette) ? image.imagePalette : [],
374
+ source: String(image.source ?? ""),
375
+ externalUrl: image.externalUrl ?? null,
376
+ originalFilename: image.originalFilename ?? null,
377
+ descriptionContext: image.descriptionContext ?? null,
378
+ style: typeof asRecord(image.analysis).style === "string" ? asRecord(image.analysis).style : null,
379
+ composition: typeof asRecord(image.analysis).composition === "string" ? asRecord(image.analysis).composition : null,
380
+ usageNotes: typeof asRecord(image.analysis).usageNotes === "string" ? asRecord(image.analysis).usageNotes : null,
381
+ createdAt: image.createdAt ?? null
382
+ };
383
+ }
384
+ function imageNormalizer(record, full) {
385
+ if (full) {
386
+ return fullImage(record);
387
+ }
388
+ return compactImage(record);
389
+ }
390
+ function compactVideo(video) {
391
+ const analysis = asRecord(video.analysis);
392
+ const sceneCount = typeof video.sceneCount === "number" ? video.sceneCount : Array.isArray(video.scenes) ? video.scenes.length : 0;
393
+ return {
394
+ _id: String(video._id ?? ""),
395
+ name: String(video.name ?? ""),
396
+ thumbnailUrl: String(video.thumbnailUrl ?? ""),
397
+ description: String(video.description ?? ""),
398
+ tags: Array.isArray(video.tags) ? video.tags : [],
399
+ status: String(video.status ?? ""),
400
+ // What decides whether this clip is usable, without a second call: who is
401
+ // on camera and in what role, what language they speak, how it opens, and
402
+ // how many beats there are to cut from.
403
+ subject: typeof analysis.subject === "string" ? analysis.subject : null,
404
+ brandOwnership: typeof analysis.brandOwnership === "string" ? analysis.brandOwnership : null,
405
+ people: peopleLines(analysis.people),
406
+ spokenLanguages: Array.isArray(analysis.spokenLanguages) ? analysis.spokenLanguages : [],
407
+ hook: typeof analysis.hook === "string" ? analysis.hook : null,
408
+ sceneCount,
409
+ group: groupSummary(video)
410
+ };
411
+ }
412
+ function sceneDecoration(scene) {
413
+ const shot = typeof scene.shot === "string" && scene.shot ? ` [${scene.shot}]` : "";
414
+ const change = typeof scene.visualChange === "string" && scene.visualChange ? ` <${scene.visualChange}>` : "";
415
+ const overlayText = Array.isArray(scene.onScreenText) ? scene.onScreenText.filter(Boolean) : [];
416
+ let overlay = "";
417
+ if (scene.hasOverlay === true) {
418
+ overlay = overlayText.length > 0 ? ` \u2014 banner: "${overlayText.join('" / "')}"` : " \u2014 banner";
419
+ } else if (scene.hasOverlay === false) {
420
+ overlay = " \u2014 clean frame";
421
+ }
422
+ const spoken = typeof scene.spoken === "string" && scene.spoken ? ` \u2014 says: "${scene.spoken}"` : "";
423
+ return `${shot}${change}${overlay}${spoken}`;
424
+ }
425
+ function sceneLines(value) {
426
+ if (!Array.isArray(value)) {
427
+ return [];
428
+ }
429
+ return value.flatMap((s) => {
430
+ const scene = asRecord(s);
431
+ const title = typeof scene.title === "string" ? scene.title : "";
432
+ if (!title) {
433
+ return [];
434
+ }
435
+ const start = round2(scene.startSecond);
436
+ const end = round2(scene.endSecond);
437
+ const range = start !== null && end !== null ? ` (${start}-${end}s)` : "";
438
+ return [`${title}${range}${sceneDecoration(scene)}`];
439
+ });
440
+ }
441
+ function fullVideo(video) {
442
+ const compact = compactVideo(video);
443
+ return {
444
+ ...compact,
445
+ duration: video.duration ?? null,
446
+ muxPlaybackId: String(video.muxPlaybackId ?? ""),
447
+ source: String(video.source ?? ""),
448
+ // The spoken transcript + AI scene breakdown of the client's own clip — the
449
+ // "understand what's in this video" payload. Kept out of the compact/search
450
+ // projection (too large for a list) and surfaced here on --full.
451
+ transcript: video.transcript ?? null,
452
+ transcript_segment_count: Array.isArray(video.transcriptSegments) ? video.transcriptSegments.length : 0,
453
+ scenes: sceneLines(video.scenes),
454
+ originalFilename: video.originalFilename ?? null,
455
+ descriptionContext: video.descriptionContext ?? null,
456
+ shotStyle: typeof asRecord(video.analysis).shotStyle === "string" ? asRecord(video.analysis).shotStyle : null,
457
+ audioStyle: typeof asRecord(video.analysis).audioStyle === "string" ? asRecord(video.analysis).audioStyle : null,
458
+ onScreenText: Array.isArray(asRecord(video.analysis).onScreenText) ? asRecord(video.analysis).onScreenText : [],
459
+ usageNotes: typeof asRecord(video.analysis).usageNotes === "string" ? asRecord(video.analysis).usageNotes : null,
460
+ createdAt: video.createdAt ?? null
461
+ };
462
+ }
463
+ function videoNormalizer(record, full) {
464
+ if (full) {
465
+ return fullVideo(record);
466
+ }
467
+ return compactVideo(record);
468
+ }
469
+ function truncate(text, maxLength) {
470
+ if (text.length <= maxLength) return text;
471
+ return `${text.slice(0, maxLength)}...`;
472
+ }
473
+ function compactTestimonial(record) {
474
+ return {
475
+ _id: String(record._id ?? ""),
476
+ reviewerName: String(record.reviewerName ?? ""),
477
+ reviewText: truncate(String(record.reviewText ?? ""), 200),
478
+ rating: record.rating ?? null,
479
+ sentiment: record.sentiment ?? null,
480
+ tags: Array.isArray(record.tags) ? record.tags : [],
481
+ sourceType: String(record.sourceType ?? "")
482
+ };
483
+ }
484
+ function fullTestimonial(record) {
485
+ const compact = compactTestimonial(record);
486
+ return {
487
+ ...compact,
488
+ reviewText: String(record.reviewText ?? ""),
489
+ highlight: record.highlight ?? null,
490
+ summary: record.summary ?? null,
491
+ language: record.language ?? null,
492
+ reviewerImageUrl: record.reviewerImageUrl ?? null,
493
+ sourceUrl: record.sourceUrl ?? null,
494
+ reviewDate: record.reviewDate ?? null,
495
+ createdAt: record.createdAt ?? null,
496
+ status: String(record.status ?? "")
497
+ };
498
+ }
499
+ function testimonialNormalizer(record, full) {
500
+ if (full) {
501
+ return fullTestimonial(record);
502
+ }
503
+ return compactTestimonial(record);
504
+ }
505
+ function round2(value) {
506
+ if (typeof value !== "number" || Number.isNaN(value)) {
507
+ return null;
508
+ }
509
+ return Math.round(value * 100) / 100;
510
+ }
511
+ function asRecord(value) {
512
+ return value && typeof value === "object" ? value : {};
513
+ }
514
+ function compactWinningAd(record) {
515
+ const dna = asRecord(record.dna);
516
+ return {
517
+ advertiser: String(record.advertiser ?? ""),
518
+ platform: String(record.platform ?? ""),
519
+ format: String(record.format ?? ""),
520
+ relevance: round2(record.relevance),
521
+ winner_score: round2(record.winner_score),
522
+ summary: String(dna.creative_concept ?? ""),
523
+ advertiser_id: String(record.advertiser_id ?? ""),
524
+ ad_id: String(record.ad_id ?? ""),
525
+ media_url: String(record.media_url ?? "")
526
+ };
527
+ }
528
+ function fullWinningAd(record) {
529
+ const compact = compactWinningAd(record);
530
+ const dna = asRecord(record.dna);
531
+ return {
532
+ ...compact,
533
+ winner_category: String(record.winner_category ?? ""),
534
+ media_kind: record.media_kind ?? null,
535
+ days_active: record.days_active ?? null,
536
+ reach: record.reach ?? null,
537
+ active: typeof record.active === "boolean" ? record.active : null,
538
+ angle: dna.angle ?? null,
539
+ awareness_stage: dna.awareness_stage ?? null,
540
+ target_persona: dna.target_persona ?? null,
541
+ hook_archetype: dna.hook_archetype ?? null,
542
+ industry: dna.industry ?? null
543
+ };
544
+ }
545
+ function winningAdNormalizer(record, full) {
546
+ if (full) {
547
+ return fullWinningAd(record);
548
+ }
549
+ return compactWinningAd(record);
550
+ }
551
+ function overlayLines(value, detailed = false) {
552
+ if (!Array.isArray(value)) {
553
+ return [];
554
+ }
555
+ return value.flatMap((o) => {
556
+ const item = asRecord(o);
557
+ const text = typeof item.text === "string" ? item.text : "";
558
+ if (!text) {
559
+ return [];
560
+ }
561
+ const at = round2(item.appears_at_s);
562
+ let line = at !== null ? `${text} @${at}s` : text;
563
+ if (detailed) {
564
+ const tags = [item.role, item.position].filter((t) => typeof t === "string" && t.length > 0);
565
+ if (tags.length) {
566
+ line += ` [${tags.join(", ")}]`;
567
+ }
568
+ }
569
+ return [line];
570
+ });
571
+ }
572
+ function compactAdContent(record) {
573
+ return {
574
+ ad_id: record.ad_id ?? null,
575
+ advertiser: record.advertiser ?? null,
576
+ format: record.format ?? null,
577
+ media_kind: record.media_kind ?? null,
578
+ media_url: record.media_url ?? null,
579
+ summary: record.summary ?? null,
580
+ transcript: record.transcript ?? null,
581
+ on_screen_text: overlayLines(record.on_screen_text),
582
+ has_captions: typeof record.has_captions === "boolean" ? record.has_captions : null,
583
+ primary_text: record.primary_text ?? null,
584
+ headline: record.headline ?? null,
585
+ cta: record.cta ?? null
586
+ };
587
+ }
588
+ function fullAdContent(record) {
589
+ const speech = asRecord(record.speech);
590
+ const pacing = asRecord(record.pacing);
591
+ const music = asRecord(record.music);
592
+ return {
593
+ ...compactAdContent(record),
594
+ platform: record.platform ?? null,
595
+ // Re-derive with role/position tags — the lean compact version dropped them.
596
+ on_screen_text: overlayLines(record.on_screen_text, true),
597
+ winner_score: round2(record.winner_score),
598
+ winner_category: record.winner_category ?? null,
599
+ angle: record.angle ?? null,
600
+ hook_archetype: record.hook_archetype ?? null,
601
+ caption_style: record.caption_style ?? null,
602
+ has_speech: typeof record.has_speech === "boolean" ? record.has_speech : null,
603
+ speech_pct_of_runtime: round2(speech.speech_pct_of_runtime),
604
+ speaker_count: speech.speaker_count ?? null,
605
+ voiceover_vs_sync: speech.voiceover_vs_sync ?? null,
606
+ is_direct_address: typeof speech.is_direct_address === "boolean" ? speech.is_direct_address : null,
607
+ speech_emotion_dominant: speech.speech_emotion_dominant ?? null,
608
+ scene_count: pacing.scene_count ?? null,
609
+ avg_shot_length_s: round2(pacing.avg_shot_length_s),
610
+ pacing_shape: pacing.pacing_shape ?? null,
611
+ hook_ends_at_s: round2(pacing.hook_ends_at_s),
612
+ cta_first_shown_at_s: round2(pacing.cta_first_shown_at_s),
613
+ product_first_appears_at_s: round2(pacing.product_first_appears_at_s),
614
+ music_track_title: music.track_title ?? null,
615
+ music_track_artist: music.track_artist ?? null
616
+ };
617
+ }
618
+ function adContentNormalizer(record, full) {
619
+ return full ? fullAdContent(record) : compactAdContent(record);
620
+ }
621
+ function applyFieldMask(data, fields) {
622
+ const result = {};
623
+ for (const field of fields) {
624
+ if (field in data) {
625
+ result[field] = data[field];
626
+ }
627
+ }
628
+ return result;
629
+ }
630
+ function write(text) {
631
+ process.stdout.write(text);
632
+ }
633
+ function writeJson(envelope) {
634
+ write(`${JSON.stringify(envelope, null, 2)}
635
+ `);
636
+ }
637
+ function writeFiles(data, fields) {
638
+ write(`${fields.join(" ")}
639
+ `);
640
+ for (const item of data) {
641
+ const values = fields.map((f) => String(item[f] ?? ""));
642
+ write(`${values.join(" ")}
643
+ `);
644
+ }
645
+ }
646
+ function writeMd(data, fields) {
647
+ write(`| ${fields.join(" | ")} |
648
+ `);
649
+ write(`| ${fields.map(() => "---").join(" | ")} |
650
+ `);
651
+ for (const item of data) {
652
+ const values = fields.map((f) => String(item[f] ?? ""));
653
+ write(`| ${values.join(" | ")} |
654
+ `);
655
+ }
656
+ }
657
+ function normalizeData(envelope, fields, full, normalizer) {
658
+ const raw = Array.isArray(envelope.data) ? envelope.data : [envelope.data];
659
+ const items = raw.map((item) => {
660
+ const record = item;
661
+ return normalizer(record, full);
662
+ });
663
+ if (fields) {
664
+ return items.map((item) => applyFieldMask(item, fields));
665
+ }
666
+ return items;
667
+ }
668
+ function writeOutput(envelope, format, fields, full, normalizer) {
669
+ if (!envelope.ok || "dryRun" in envelope) {
670
+ writeJson(envelope);
671
+ return;
672
+ }
673
+ if (format === "json") {
674
+ writeJson(envelope);
675
+ return;
676
+ }
677
+ if (format !== "files" && format !== "md") {
678
+ process.stderr.write(`Unknown --output "${String(format)}". Valid formats: json, files, md. Using json.
679
+ `);
680
+ writeJson(envelope);
681
+ return;
682
+ }
683
+ const items = normalizeData(envelope, fields, full ?? false, normalizer ?? imageNormalizer);
684
+ const displayFields = fields ?? Object.keys(items[0] ?? {});
685
+ if (format === "files") {
686
+ writeFiles(items, displayFields);
687
+ } else {
688
+ writeMd(items, displayFields);
689
+ }
690
+ writeHints(envelope.hints);
691
+ }
692
+ function writeHints(hints) {
693
+ for (const hint of hints ?? []) {
694
+ process.stderr.write(`${hint}
695
+ `);
696
+ }
697
+ }
698
+
699
+ // src/env.ts
700
+ var cached;
701
+ var CONNECTION = {
702
+ BAKER_API_KEY: z.string().refine(isBakerApiKey, API_KEY_FORMAT_MESSAGE),
703
+ BAKER_API_URL: z.url("BAKER_API_URL must be a valid URL")
704
+ };
705
+ function getEnv() {
706
+ if (!cached) {
707
+ cached = createEnv({
708
+ server: {
709
+ ...CONNECTION,
710
+ BAKER_PUBLIC_API_URL: z.url("BAKER_PUBLIC_API_URL must be a valid URL").optional(),
711
+ BAKER_CHAT_ID: z.string().optional(),
712
+ BAKER_ACTING_USER_ID: z.string().optional(),
713
+ BAKER_GOOGLE_ADS_CUSTOMER_ID: z.string().regex(/^\d{10}$/).optional(),
714
+ BAKER_GA4_PROPERTY_ID: z.string().optional(),
715
+ BAKER_GSC_SITE_URL: z.string().optional(),
716
+ BAKER_X_ADS_ACCOUNT_ID: z.string().regex(/^[a-z0-9]+$/, "X Ads account ID must be a base36 string").optional(),
717
+ BAKER_META_AD_ACCOUNT_ID: z.string().optional(),
718
+ BAKER_LINKEDIN_AD_ACCOUNT_ID: z.string().regex(/^\d+$/, "LinkedIn ad account ID must be the numeric portion of urn:li:sponsoredAccount:N").optional()
719
+ },
720
+ runtimeEnv: process.env,
721
+ onValidationError: refuseInvalidEnv
722
+ });
723
+ }
724
+ return cached;
725
+ }
726
+ function requireConnection() {
727
+ return createEnv({ server: CONNECTION, runtimeEnv: process.env, onValidationError: refuseInvalidEnv });
728
+ }
729
+ function issueVariable(issue) {
730
+ const first = issue.path?.[0];
731
+ const key = typeof first === "object" && first !== null ? first.key : first;
732
+ return key === void 0 ? "environment" : String(key);
733
+ }
734
+ var AGENT_SET_VARIABLES = /* @__PURE__ */ new Set([
735
+ "BAKER_GOOGLE_ADS_CUSTOMER_ID",
736
+ "BAKER_LINKEDIN_AD_ACCOUNT_ID",
737
+ "BAKER_X_ADS_ACCOUNT_ID"
738
+ ]);
739
+ function listVariables(variables) {
740
+ return `${variables.join(", ")} ${variables.length === 1 ? "is" : "are"}`;
741
+ }
742
+ function refuseInvalidEnv(issues) {
743
+ const problems = issues.map((issue) => `${issueVariable(issue)}: ${issue.message}`).join("; ");
744
+ const variables = [...new Set(issues.map(issueVariable))];
745
+ if (variables.every((variable) => AGENT_SET_VARIABLES.has(variable))) {
746
+ writeJson({
747
+ ok: false,
748
+ error: {
749
+ code: "VALIDATION_ERROR",
750
+ message: `An environment variable has the wrong format \u2014 ${problems}.`,
751
+ retryable: false,
752
+ fix: {
753
+ action: "retry_with_changes",
754
+ explanation: `${listVariables(variables)} an optional override set in this workspace, not by the platform. Export it again in the format named above, or unset ${variables.join(" and ")} and pass the account with the command's flag instead, then re-run the command.`
755
+ }
756
+ }
757
+ });
758
+ process.exit(1);
759
+ }
760
+ writeJson({
761
+ ok: false,
762
+ error: {
763
+ code: "NOT_CONFIGURED",
764
+ message: `This workspace's Baker connection is misconfigured \u2014 ${problems}.`,
765
+ retryable: false,
766
+ fix: {
767
+ action: "continue_without",
768
+ explanation: `${listVariables(variables)} set by the platform when this workspace starts, and nothing in this workspace can correct it \u2014 do not retry, and do not set or edit it yourself. Every command that reads or writes Baker data will fail the same way. Carry on with work that does not need Baker's data (files in the repo, local checks), and tell the user that reading and saving their Baker data is unavailable in this conversation until the platform fixes it.`
769
+ }
770
+ }
771
+ });
772
+ process.exit(1);
773
+ }
774
+ function optionalChatId() {
775
+ return process.env.BAKER_CHAT_ID || void 0;
776
+ }
777
+ function debugLogSetting() {
778
+ const raw = process.env.BAKER_DEBUG_LOG?.trim();
779
+ return raw ? raw : void 0;
780
+ }
781
+ function requireChatId() {
782
+ const env = getEnv();
783
+ if (!env.BAKER_CHAT_ID) {
784
+ throw new Error(
785
+ "BAKER_CHAT_ID is not set. This command stages changes against a chat \u2014 run it from a chat-attached environment."
786
+ );
787
+ }
788
+ return env.BAKER_CHAT_ID;
789
+ }
790
+ function resolveChatId(chat) {
791
+ return typeof chat === "string" && chat.length > 0 ? chat : requireChatId();
792
+ }
793
+ function hasFrameVisionKey() {
794
+ return Boolean(frameVisionKey());
795
+ }
796
+ function frameVisionKey() {
797
+ return process.env.GEMINI_API_KEY;
798
+ }
799
+ function openRouterKey() {
800
+ return process.env.OPENROUTER_API_KEY;
801
+ }
802
+ function hasOpenRouterKey() {
803
+ return Boolean(openRouterKey());
804
+ }
805
+ function captureBudgetMs() {
806
+ const raw = Number(process.env.BAKER_CAPTURE_BUDGET_MS);
807
+ return Number.isFinite(raw) && raw > 0 ? raw : null;
808
+ }
809
+ function captureProxyCredentials() {
810
+ return readProxyCredentials(process.env);
811
+ }
812
+ function captureVimeoCookie() {
813
+ const raw = process.env.VIMEO_COOKIE?.trim();
814
+ return raw ? raw : void 0;
815
+ }
816
+ function childEnvWith(extra) {
817
+ return { ...process.env, ...extra };
818
+ }
819
+
820
+ export {
821
+ __commonJS,
822
+ __toESM,
823
+ isChallengeBody,
824
+ isProxyFailure,
825
+ shouldEscalate,
826
+ isPrivateAddress,
827
+ refuseNonPublicUrl,
828
+ DIRECT_ROUTE,
829
+ plannedRoutes,
830
+ API_KEY_FORMAT_MESSAGE,
831
+ isBakerApiKey,
832
+ compactImage,
833
+ compactVideo,
834
+ videoNormalizer,
835
+ testimonialNormalizer,
836
+ winningAdNormalizer,
837
+ adContentNormalizer,
838
+ writeJson,
839
+ writeOutput,
840
+ getEnv,
841
+ requireConnection,
842
+ optionalChatId,
843
+ debugLogSetting,
844
+ requireChatId,
845
+ resolveChatId,
846
+ hasFrameVisionKey,
847
+ frameVisionKey,
848
+ openRouterKey,
849
+ hasOpenRouterKey,
850
+ captureBudgetMs,
851
+ captureProxyCredentials,
852
+ captureVimeoCookie,
853
+ childEnvWith
854
+ };
855
+ //# sourceMappingURL=chunk-2OKSJNLA.js.map