@koda-sl/baker-cli 0.346.0 → 0.347.0-dev.043fc924c
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/README.md +3 -3
- package/dist/chunk-4VP5WWPR.js +376 -0
- package/dist/chunk-4VP5WWPR.js.map +1 -0
- package/dist/{chunk-YBD3W4M7.js → chunk-D5P4COPD.js} +8 -9
- package/dist/chunk-D5P4COPD.js.map +1 -0
- package/dist/{chunk-NA5CPMUA.js → chunk-JWMLQSGK.js} +4 -4
- package/dist/{chunk-2IC3CGQO.js → chunk-KGDL7F7M.js} +3 -3
- package/dist/{chunk-XWHHYHKQ.js → chunk-PWGY347J.js} +2 -2
- package/dist/{chunk-4QXKWIFC.js → chunk-XPUSSDLR.js} +3 -3
- package/dist/cli.js +519 -53
- package/dist/cli.js.map +1 -1
- package/dist/{client-ODCNYCP4.js → client-PWRZOA3Q.js} +4 -4
- package/dist/engine/index.js +3 -3
- package/dist/{env-BSG7TY5Y.js → env-TQTHWLBN.js} +2 -6
- package/dist/{output-2XBCYF7L.js → output-HD63GTWI.js} +5 -5
- package/dist/{shared-RYAF7Y7H.js → shared-5662SBDW.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-2OKSJNLA.js +0 -855
- package/dist/chunk-2OKSJNLA.js.map +0 -1
- package/dist/chunk-YBD3W4M7.js.map +0 -1
- /package/dist/{chunk-NA5CPMUA.js.map → chunk-JWMLQSGK.js.map} +0 -0
- /package/dist/{chunk-2IC3CGQO.js.map → chunk-KGDL7F7M.js.map} +0 -0
- /package/dist/{chunk-XWHHYHKQ.js.map → chunk-PWGY347J.js.map} +0 -0
- /package/dist/{chunk-4QXKWIFC.js.map → chunk-XPUSSDLR.js.map} +0 -0
- /package/dist/{client-ODCNYCP4.js.map → client-PWRZOA3Q.js.map} +0 -0
- /package/dist/{env-BSG7TY5Y.js.map → env-TQTHWLBN.js.map} +0 -0
- /package/dist/{output-2XBCYF7L.js.map → output-HD63GTWI.js.map} +0 -0
- /package/dist/{shared-RYAF7Y7H.js.map → shared-5662SBDW.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
validateCanvasDeep,
|
|
68
68
|
withoutCastName,
|
|
69
69
|
ytDlpBlockSignal
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-D5P4COPD.js";
|
|
71
71
|
import {
|
|
72
72
|
csvOrJson,
|
|
73
73
|
daysAgoIso,
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
resolveAccountIdArg,
|
|
77
77
|
resolveEffectiveStatus,
|
|
78
78
|
todayIso
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-JWMLQSGK.js";
|
|
80
80
|
import {
|
|
81
81
|
buildQueryCacheKey,
|
|
82
82
|
cacheGet,
|
|
@@ -92,42 +92,33 @@ import {
|
|
|
92
92
|
writeAdsJson,
|
|
93
93
|
writeAdsOutput,
|
|
94
94
|
writeJsonEnvelope
|
|
95
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-KGDL7F7M.js";
|
|
96
96
|
import {
|
|
97
97
|
ApiError,
|
|
98
98
|
apiGet,
|
|
99
99
|
apiGetWithHeaders,
|
|
100
100
|
apiPost,
|
|
101
101
|
validateConvexId
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-XPUSSDLR.js";
|
|
103
103
|
import {
|
|
104
104
|
installExitRecord,
|
|
105
105
|
installStreamTaps,
|
|
106
106
|
logInvocation
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-PWGY347J.js";
|
|
108
108
|
import {
|
|
109
|
-
adContentNormalizer,
|
|
110
109
|
captureBudgetMs,
|
|
111
110
|
captureProxyCredentials,
|
|
112
111
|
captureVimeoCookie,
|
|
113
|
-
compactImage,
|
|
114
|
-
compactVideo,
|
|
115
112
|
getEnv,
|
|
116
113
|
hasOpenRouterKey,
|
|
117
114
|
isProxyFailure,
|
|
118
115
|
openRouterKey,
|
|
119
|
-
optionalChatId,
|
|
120
116
|
plannedRoutes,
|
|
121
117
|
refuseNonPublicUrl,
|
|
122
118
|
requireChatId,
|
|
123
119
|
resolveChatId,
|
|
124
|
-
shouldEscalate
|
|
125
|
-
|
|
126
|
-
videoNormalizer,
|
|
127
|
-
winningAdNormalizer,
|
|
128
|
-
writeJson,
|
|
129
|
-
writeOutput
|
|
130
|
-
} from "./chunk-2OKSJNLA.js";
|
|
120
|
+
shouldEscalate
|
|
121
|
+
} from "./chunk-4VP5WWPR.js";
|
|
131
122
|
|
|
132
123
|
// src/cli.ts
|
|
133
124
|
import { defineCommand as defineCommand245, runMain } from "citty";
|
|
@@ -168,6 +159,420 @@ import { defineCommand as defineCommand18 } from "citty";
|
|
|
168
159
|
// src/commands/actions/claim.ts
|
|
169
160
|
import { defineCommand } from "citty";
|
|
170
161
|
|
|
162
|
+
// src/output.ts
|
|
163
|
+
var ASPECT_RATIO_MAP = {
|
|
164
|
+
"1:1": 1,
|
|
165
|
+
"16:9": 16 / 9,
|
|
166
|
+
"9:16": 9 / 16,
|
|
167
|
+
"2:3": 2 / 3,
|
|
168
|
+
"3:4": 3 / 4,
|
|
169
|
+
"1:2": 1 / 2,
|
|
170
|
+
"2:1": 2,
|
|
171
|
+
"4:5": 4 / 5,
|
|
172
|
+
"3:2": 3 / 2,
|
|
173
|
+
"4:3": 4 / 3
|
|
174
|
+
};
|
|
175
|
+
var ASPECT_RATIO_TOLERANCE = 0.08;
|
|
176
|
+
function formatAspectRatio(ratio) {
|
|
177
|
+
if (ratio === void 0 || ratio === null) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
for (const [label, value] of Object.entries(ASPECT_RATIO_MAP)) {
|
|
181
|
+
if (Math.abs(ratio - value) / value < ASPECT_RATIO_TOLERANCE) {
|
|
182
|
+
return label;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
function groupSummary(record) {
|
|
188
|
+
const key = record.groupKey;
|
|
189
|
+
if (typeof key !== "string" || !key) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const index = typeof record.groupIndex === "number" ? record.groupIndex : null;
|
|
193
|
+
const size = typeof record.groupSize === "number" ? record.groupSize : null;
|
|
194
|
+
return {
|
|
195
|
+
key,
|
|
196
|
+
kind: typeof record.groupKind === "string" ? record.groupKind : null,
|
|
197
|
+
position: index === null ? null : size === null ? `${index + 1}` : `${index + 1} of ${size}`,
|
|
198
|
+
title: typeof record.groupTitle === "string" ? record.groupTitle : null,
|
|
199
|
+
url: typeof record.groupUrl === "string" ? record.groupUrl : null
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function peopleLines(value) {
|
|
203
|
+
if (!Array.isArray(value)) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
return value.flatMap((entry) => {
|
|
207
|
+
const person = asRecord(entry);
|
|
208
|
+
const role = typeof person.role === "string" ? person.role : "";
|
|
209
|
+
if (!role) {
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
const identity = typeof person.identity === "string" && person.identity ? ` \u2014 ${person.identity}` : "";
|
|
213
|
+
const appearance = typeof person.appearance === "string" && person.appearance ? ` (${person.appearance})` : "";
|
|
214
|
+
const speaking = person.speaking === true ? " [speaking]" : "";
|
|
215
|
+
return [`${role}${identity}${appearance}${speaking}`];
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function compactImage(image) {
|
|
219
|
+
const analysis = asRecord(image.analysis);
|
|
220
|
+
return {
|
|
221
|
+
_id: String(image._id ?? ""),
|
|
222
|
+
name: String(image.name ?? ""),
|
|
223
|
+
imageUrl: String(image.imageUrl ?? ""),
|
|
224
|
+
description: String(image.description ?? ""),
|
|
225
|
+
tags: Array.isArray(image.tags) ? image.tags : [],
|
|
226
|
+
// Two numbers that are not about choosing the image but about placing it.
|
|
227
|
+
// A remote <BakerImage> with no width/height makes Astro DOWNLOAD the file
|
|
228
|
+
// at build time just to measure it — one request per image per build, on a
|
|
229
|
+
// build that is otherwise offline, and a single dropped connection there
|
|
230
|
+
// fails a client's whole verify. They are cheap enough to always carry, and
|
|
231
|
+
// burying them behind --full meant the agent placing the image never had
|
|
232
|
+
// them.
|
|
233
|
+
width: typeof image.width === "number" ? image.width : null,
|
|
234
|
+
height: typeof image.height === "number" ? image.height : null,
|
|
235
|
+
// The facts that decide a pick, so choosing does not need a second call:
|
|
236
|
+
// whose brand it is, who is in it, and what text is burned in.
|
|
237
|
+
subject: typeof analysis.subject === "string" ? analysis.subject : null,
|
|
238
|
+
brandOwnership: typeof analysis.brandOwnership === "string" ? analysis.brandOwnership : null,
|
|
239
|
+
people: peopleLines(analysis.people),
|
|
240
|
+
textInImage: Array.isArray(analysis.textInImage) ? analysis.textInImage : [],
|
|
241
|
+
group: groupSummary(image)
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function fullImage(image) {
|
|
245
|
+
const compact3 = compactImage(image);
|
|
246
|
+
return {
|
|
247
|
+
...compact3,
|
|
248
|
+
aspectRatio: formatAspectRatio(image.aspectRatio),
|
|
249
|
+
dominantColor: image.dominantColor ?? null,
|
|
250
|
+
imagePalette: Array.isArray(image.imagePalette) ? image.imagePalette : [],
|
|
251
|
+
source: String(image.source ?? ""),
|
|
252
|
+
externalUrl: image.externalUrl ?? null,
|
|
253
|
+
originalFilename: image.originalFilename ?? null,
|
|
254
|
+
descriptionContext: image.descriptionContext ?? null,
|
|
255
|
+
style: typeof asRecord(image.analysis).style === "string" ? asRecord(image.analysis).style : null,
|
|
256
|
+
composition: typeof asRecord(image.analysis).composition === "string" ? asRecord(image.analysis).composition : null,
|
|
257
|
+
usageNotes: typeof asRecord(image.analysis).usageNotes === "string" ? asRecord(image.analysis).usageNotes : null,
|
|
258
|
+
createdAt: image.createdAt ?? null
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function imageNormalizer(record, full) {
|
|
262
|
+
if (full) {
|
|
263
|
+
return fullImage(record);
|
|
264
|
+
}
|
|
265
|
+
return compactImage(record);
|
|
266
|
+
}
|
|
267
|
+
function compactVideo(video) {
|
|
268
|
+
const analysis = asRecord(video.analysis);
|
|
269
|
+
const sceneCount = typeof video.sceneCount === "number" ? video.sceneCount : Array.isArray(video.scenes) ? video.scenes.length : 0;
|
|
270
|
+
return {
|
|
271
|
+
_id: String(video._id ?? ""),
|
|
272
|
+
name: String(video.name ?? ""),
|
|
273
|
+
thumbnailUrl: String(video.thumbnailUrl ?? ""),
|
|
274
|
+
description: String(video.description ?? ""),
|
|
275
|
+
tags: Array.isArray(video.tags) ? video.tags : [],
|
|
276
|
+
status: String(video.status ?? ""),
|
|
277
|
+
// What decides whether this clip is usable, without a second call: who is
|
|
278
|
+
// on camera and in what role, what language they speak, how it opens, and
|
|
279
|
+
// how many beats there are to cut from.
|
|
280
|
+
subject: typeof analysis.subject === "string" ? analysis.subject : null,
|
|
281
|
+
brandOwnership: typeof analysis.brandOwnership === "string" ? analysis.brandOwnership : null,
|
|
282
|
+
people: peopleLines(analysis.people),
|
|
283
|
+
spokenLanguages: Array.isArray(analysis.spokenLanguages) ? analysis.spokenLanguages : [],
|
|
284
|
+
hook: typeof analysis.hook === "string" ? analysis.hook : null,
|
|
285
|
+
sceneCount,
|
|
286
|
+
group: groupSummary(video)
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function sceneDecoration(scene) {
|
|
290
|
+
const shot = typeof scene.shot === "string" && scene.shot ? ` [${scene.shot}]` : "";
|
|
291
|
+
const change = typeof scene.visualChange === "string" && scene.visualChange ? ` <${scene.visualChange}>` : "";
|
|
292
|
+
const overlayText = Array.isArray(scene.onScreenText) ? scene.onScreenText.filter(Boolean) : [];
|
|
293
|
+
let overlay = "";
|
|
294
|
+
if (scene.hasOverlay === true) {
|
|
295
|
+
overlay = overlayText.length > 0 ? ` \u2014 banner: "${overlayText.join('" / "')}"` : " \u2014 banner";
|
|
296
|
+
} else if (scene.hasOverlay === false) {
|
|
297
|
+
overlay = " \u2014 clean frame";
|
|
298
|
+
}
|
|
299
|
+
const spoken = typeof scene.spoken === "string" && scene.spoken ? ` \u2014 says: "${scene.spoken}"` : "";
|
|
300
|
+
return `${shot}${change}${overlay}${spoken}`;
|
|
301
|
+
}
|
|
302
|
+
function sceneLines(value) {
|
|
303
|
+
if (!Array.isArray(value)) {
|
|
304
|
+
return [];
|
|
305
|
+
}
|
|
306
|
+
return value.flatMap((s) => {
|
|
307
|
+
const scene = asRecord(s);
|
|
308
|
+
const title = typeof scene.title === "string" ? scene.title : "";
|
|
309
|
+
if (!title) {
|
|
310
|
+
return [];
|
|
311
|
+
}
|
|
312
|
+
const start = round2(scene.startSecond);
|
|
313
|
+
const end = round2(scene.endSecond);
|
|
314
|
+
const range = start !== null && end !== null ? ` (${start}-${end}s)` : "";
|
|
315
|
+
return [`${title}${range}${sceneDecoration(scene)}`];
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
function fullVideo(video) {
|
|
319
|
+
const compact3 = compactVideo(video);
|
|
320
|
+
return {
|
|
321
|
+
...compact3,
|
|
322
|
+
duration: video.duration ?? null,
|
|
323
|
+
muxPlaybackId: String(video.muxPlaybackId ?? ""),
|
|
324
|
+
source: String(video.source ?? ""),
|
|
325
|
+
// The spoken transcript + AI scene breakdown of the client's own clip — the
|
|
326
|
+
// "understand what's in this video" payload. Kept out of the compact/search
|
|
327
|
+
// projection (too large for a list) and surfaced here on --full.
|
|
328
|
+
transcript: video.transcript ?? null,
|
|
329
|
+
transcript_segment_count: Array.isArray(video.transcriptSegments) ? video.transcriptSegments.length : 0,
|
|
330
|
+
scenes: sceneLines(video.scenes),
|
|
331
|
+
originalFilename: video.originalFilename ?? null,
|
|
332
|
+
descriptionContext: video.descriptionContext ?? null,
|
|
333
|
+
shotStyle: typeof asRecord(video.analysis).shotStyle === "string" ? asRecord(video.analysis).shotStyle : null,
|
|
334
|
+
audioStyle: typeof asRecord(video.analysis).audioStyle === "string" ? asRecord(video.analysis).audioStyle : null,
|
|
335
|
+
onScreenText: Array.isArray(asRecord(video.analysis).onScreenText) ? asRecord(video.analysis).onScreenText : [],
|
|
336
|
+
usageNotes: typeof asRecord(video.analysis).usageNotes === "string" ? asRecord(video.analysis).usageNotes : null,
|
|
337
|
+
createdAt: video.createdAt ?? null
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function videoNormalizer(record, full) {
|
|
341
|
+
if (full) {
|
|
342
|
+
return fullVideo(record);
|
|
343
|
+
}
|
|
344
|
+
return compactVideo(record);
|
|
345
|
+
}
|
|
346
|
+
function truncate(text2, maxLength) {
|
|
347
|
+
if (text2.length <= maxLength) return text2;
|
|
348
|
+
return `${text2.slice(0, maxLength)}...`;
|
|
349
|
+
}
|
|
350
|
+
function compactTestimonial(record) {
|
|
351
|
+
return {
|
|
352
|
+
_id: String(record._id ?? ""),
|
|
353
|
+
reviewerName: String(record.reviewerName ?? ""),
|
|
354
|
+
reviewText: truncate(String(record.reviewText ?? ""), 200),
|
|
355
|
+
rating: record.rating ?? null,
|
|
356
|
+
sentiment: record.sentiment ?? null,
|
|
357
|
+
tags: Array.isArray(record.tags) ? record.tags : [],
|
|
358
|
+
sourceType: String(record.sourceType ?? "")
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function fullTestimonial(record) {
|
|
362
|
+
const compact3 = compactTestimonial(record);
|
|
363
|
+
return {
|
|
364
|
+
...compact3,
|
|
365
|
+
reviewText: String(record.reviewText ?? ""),
|
|
366
|
+
highlight: record.highlight ?? null,
|
|
367
|
+
summary: record.summary ?? null,
|
|
368
|
+
language: record.language ?? null,
|
|
369
|
+
reviewerImageUrl: record.reviewerImageUrl ?? null,
|
|
370
|
+
sourceUrl: record.sourceUrl ?? null,
|
|
371
|
+
reviewDate: record.reviewDate ?? null,
|
|
372
|
+
createdAt: record.createdAt ?? null,
|
|
373
|
+
status: String(record.status ?? "")
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function testimonialNormalizer(record, full) {
|
|
377
|
+
if (full) {
|
|
378
|
+
return fullTestimonial(record);
|
|
379
|
+
}
|
|
380
|
+
return compactTestimonial(record);
|
|
381
|
+
}
|
|
382
|
+
function round2(value) {
|
|
383
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
return Math.round(value * 100) / 100;
|
|
387
|
+
}
|
|
388
|
+
function asRecord(value) {
|
|
389
|
+
return value && typeof value === "object" ? value : {};
|
|
390
|
+
}
|
|
391
|
+
function compactWinningAd(record) {
|
|
392
|
+
const dna = asRecord(record.dna);
|
|
393
|
+
return {
|
|
394
|
+
advertiser: String(record.advertiser ?? ""),
|
|
395
|
+
platform: String(record.platform ?? ""),
|
|
396
|
+
format: String(record.format ?? ""),
|
|
397
|
+
relevance: round2(record.relevance),
|
|
398
|
+
winner_score: round2(record.winner_score),
|
|
399
|
+
summary: String(dna.creative_concept ?? ""),
|
|
400
|
+
advertiser_id: String(record.advertiser_id ?? ""),
|
|
401
|
+
ad_id: String(record.ad_id ?? ""),
|
|
402
|
+
media_url: String(record.media_url ?? "")
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function fullWinningAd(record) {
|
|
406
|
+
const compact3 = compactWinningAd(record);
|
|
407
|
+
const dna = asRecord(record.dna);
|
|
408
|
+
return {
|
|
409
|
+
...compact3,
|
|
410
|
+
winner_category: String(record.winner_category ?? ""),
|
|
411
|
+
media_kind: record.media_kind ?? null,
|
|
412
|
+
days_active: record.days_active ?? null,
|
|
413
|
+
reach: record.reach ?? null,
|
|
414
|
+
active: typeof record.active === "boolean" ? record.active : null,
|
|
415
|
+
angle: dna.angle ?? null,
|
|
416
|
+
awareness_stage: dna.awareness_stage ?? null,
|
|
417
|
+
target_persona: dna.target_persona ?? null,
|
|
418
|
+
hook_archetype: dna.hook_archetype ?? null,
|
|
419
|
+
industry: dna.industry ?? null
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function winningAdNormalizer(record, full) {
|
|
423
|
+
if (full) {
|
|
424
|
+
return fullWinningAd(record);
|
|
425
|
+
}
|
|
426
|
+
return compactWinningAd(record);
|
|
427
|
+
}
|
|
428
|
+
function overlayLines(value, detailed = false) {
|
|
429
|
+
if (!Array.isArray(value)) {
|
|
430
|
+
return [];
|
|
431
|
+
}
|
|
432
|
+
return value.flatMap((o) => {
|
|
433
|
+
const item = asRecord(o);
|
|
434
|
+
const text2 = typeof item.text === "string" ? item.text : "";
|
|
435
|
+
if (!text2) {
|
|
436
|
+
return [];
|
|
437
|
+
}
|
|
438
|
+
const at = round2(item.appears_at_s);
|
|
439
|
+
let line = at !== null ? `${text2} @${at}s` : text2;
|
|
440
|
+
if (detailed) {
|
|
441
|
+
const tags = [item.role, item.position].filter((t) => typeof t === "string" && t.length > 0);
|
|
442
|
+
if (tags.length) {
|
|
443
|
+
line += ` [${tags.join(", ")}]`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return [line];
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
function compactAdContent(record) {
|
|
450
|
+
return {
|
|
451
|
+
ad_id: record.ad_id ?? null,
|
|
452
|
+
advertiser: record.advertiser ?? null,
|
|
453
|
+
format: record.format ?? null,
|
|
454
|
+
media_kind: record.media_kind ?? null,
|
|
455
|
+
media_url: record.media_url ?? null,
|
|
456
|
+
summary: record.summary ?? null,
|
|
457
|
+
transcript: record.transcript ?? null,
|
|
458
|
+
on_screen_text: overlayLines(record.on_screen_text),
|
|
459
|
+
has_captions: typeof record.has_captions === "boolean" ? record.has_captions : null,
|
|
460
|
+
primary_text: record.primary_text ?? null,
|
|
461
|
+
headline: record.headline ?? null,
|
|
462
|
+
cta: record.cta ?? null
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function fullAdContent(record) {
|
|
466
|
+
const speech = asRecord(record.speech);
|
|
467
|
+
const pacing = asRecord(record.pacing);
|
|
468
|
+
const music = asRecord(record.music);
|
|
469
|
+
return {
|
|
470
|
+
...compactAdContent(record),
|
|
471
|
+
platform: record.platform ?? null,
|
|
472
|
+
// Re-derive with role/position tags — the lean compact version dropped them.
|
|
473
|
+
on_screen_text: overlayLines(record.on_screen_text, true),
|
|
474
|
+
winner_score: round2(record.winner_score),
|
|
475
|
+
winner_category: record.winner_category ?? null,
|
|
476
|
+
angle: record.angle ?? null,
|
|
477
|
+
hook_archetype: record.hook_archetype ?? null,
|
|
478
|
+
caption_style: record.caption_style ?? null,
|
|
479
|
+
has_speech: typeof record.has_speech === "boolean" ? record.has_speech : null,
|
|
480
|
+
speech_pct_of_runtime: round2(speech.speech_pct_of_runtime),
|
|
481
|
+
speaker_count: speech.speaker_count ?? null,
|
|
482
|
+
voiceover_vs_sync: speech.voiceover_vs_sync ?? null,
|
|
483
|
+
is_direct_address: typeof speech.is_direct_address === "boolean" ? speech.is_direct_address : null,
|
|
484
|
+
speech_emotion_dominant: speech.speech_emotion_dominant ?? null,
|
|
485
|
+
scene_count: pacing.scene_count ?? null,
|
|
486
|
+
avg_shot_length_s: round2(pacing.avg_shot_length_s),
|
|
487
|
+
pacing_shape: pacing.pacing_shape ?? null,
|
|
488
|
+
hook_ends_at_s: round2(pacing.hook_ends_at_s),
|
|
489
|
+
cta_first_shown_at_s: round2(pacing.cta_first_shown_at_s),
|
|
490
|
+
product_first_appears_at_s: round2(pacing.product_first_appears_at_s),
|
|
491
|
+
music_track_title: music.track_title ?? null,
|
|
492
|
+
music_track_artist: music.track_artist ?? null
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function adContentNormalizer(record, full) {
|
|
496
|
+
return full ? fullAdContent(record) : compactAdContent(record);
|
|
497
|
+
}
|
|
498
|
+
function applyFieldMask(data, fields) {
|
|
499
|
+
const result = {};
|
|
500
|
+
for (const field of fields) {
|
|
501
|
+
if (field in data) {
|
|
502
|
+
result[field] = data[field];
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return result;
|
|
506
|
+
}
|
|
507
|
+
function write(text2) {
|
|
508
|
+
process.stdout.write(text2);
|
|
509
|
+
}
|
|
510
|
+
function writeJson(envelope) {
|
|
511
|
+
write(`${JSON.stringify(envelope, null, 2)}
|
|
512
|
+
`);
|
|
513
|
+
}
|
|
514
|
+
function writeFiles(data, fields) {
|
|
515
|
+
write(`${fields.join(" ")}
|
|
516
|
+
`);
|
|
517
|
+
for (const item of data) {
|
|
518
|
+
const values = fields.map((f) => String(item[f] ?? ""));
|
|
519
|
+
write(`${values.join(" ")}
|
|
520
|
+
`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
function writeMd(data, fields) {
|
|
524
|
+
write(`| ${fields.join(" | ")} |
|
|
525
|
+
`);
|
|
526
|
+
write(`| ${fields.map(() => "---").join(" | ")} |
|
|
527
|
+
`);
|
|
528
|
+
for (const item of data) {
|
|
529
|
+
const values = fields.map((f) => String(item[f] ?? ""));
|
|
530
|
+
write(`| ${values.join(" | ")} |
|
|
531
|
+
`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
function normalizeData(envelope, fields, full, normalizer) {
|
|
535
|
+
const raw = Array.isArray(envelope.data) ? envelope.data : [envelope.data];
|
|
536
|
+
const items = raw.map((item) => {
|
|
537
|
+
const record = item;
|
|
538
|
+
return normalizer(record, full);
|
|
539
|
+
});
|
|
540
|
+
if (fields) {
|
|
541
|
+
return items.map((item) => applyFieldMask(item, fields));
|
|
542
|
+
}
|
|
543
|
+
return items;
|
|
544
|
+
}
|
|
545
|
+
function writeOutput(envelope, format, fields, full, normalizer) {
|
|
546
|
+
if (!envelope.ok || "dryRun" in envelope) {
|
|
547
|
+
writeJson(envelope);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
if (format === "json") {
|
|
551
|
+
writeJson(envelope);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (format !== "files" && format !== "md") {
|
|
555
|
+
process.stderr.write(`Unknown --output "${String(format)}". Valid formats: json, files, md. Using json.
|
|
556
|
+
`);
|
|
557
|
+
writeJson(envelope);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const items = normalizeData(envelope, fields, full ?? false, normalizer ?? imageNormalizer);
|
|
561
|
+
const displayFields = fields ?? Object.keys(items[0] ?? {});
|
|
562
|
+
if (format === "files") {
|
|
563
|
+
writeFiles(items, displayFields);
|
|
564
|
+
} else {
|
|
565
|
+
writeMd(items, displayFields);
|
|
566
|
+
}
|
|
567
|
+
writeHints(envelope.hints);
|
|
568
|
+
}
|
|
569
|
+
function writeHints(hints2) {
|
|
570
|
+
for (const hint of hints2 ?? []) {
|
|
571
|
+
process.stderr.write(`${hint}
|
|
572
|
+
`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
171
576
|
// src/schemas.ts
|
|
172
577
|
var registry = /* @__PURE__ */ new Map();
|
|
173
578
|
function registerSchema(schema) {
|
|
@@ -384,6 +789,50 @@ var actionsUpdateRequestSchema = z.object({
|
|
|
384
789
|
var actionsUpdateResponseSchema = okOnlySchema();
|
|
385
790
|
var ACTION_COMPLETE_NOTE_MIN = 20;
|
|
386
791
|
var actionsCompleteNoteMessage = `A completion note (\u2265${ACTION_COMPLETE_NOTE_MIN} chars) describing what was done is required: what changed, where, and the outcome.`;
|
|
792
|
+
var ACCOUNT_CONTEXT = "(?:account|accounts|cuenta|cuentas|customer|cliente|property|propiedad|meta|facebook|google|ads|linkedin|ga4|analytics|gtm|tag manager|id)";
|
|
793
|
+
var COMPLETION_NOTE_INTERNALS = [
|
|
794
|
+
// Repo paths: rooted in a workspace directory, or a path or lowercase file name
|
|
795
|
+
// ending in a source extension (a product name like "Next.js" is not a file).
|
|
796
|
+
/(?:\.{0,2}\/)?(?:src|public|__tooling__|\.claude)\/[^\s,;:)`'"]*[^\s,;:)`'".]/g,
|
|
797
|
+
/(?:[\w.-]*\/[\w./-]*|\b[a-z_][\w-]*)\.(?:mdx?|astro|tsx?|jsx?|mjs|json|ya?ml)\b/g,
|
|
798
|
+
// Meta ad-account ids, Tag Manager containers and GA4 measurement ids.
|
|
799
|
+
/\bact_\d+\b/g,
|
|
800
|
+
/\bGTM-[A-Z0-9]{4,}\b/g,
|
|
801
|
+
/\bG-[A-Z0-9]{6,}\b/g,
|
|
802
|
+
// Google Ads customer ids (386-508-3115), LinkedIn, GA4 and bare Google Ads ids:
|
|
803
|
+
// a long number named next to a platform or an account, so a phone number or
|
|
804
|
+
// a figure elsewhere in the note is not one.
|
|
805
|
+
new RegExp(
|
|
806
|
+
String.raw`(?<=\b${ACCOUNT_CONTEXT}\b[^.\n\d]{0,20})(?<![\w-])(?:\d{3}-\d{3}-\d{4}|\d{7,})(?![\w-])`,
|
|
807
|
+
"gi"
|
|
808
|
+
),
|
|
809
|
+
// Error codes: SCREAMING_SNAKE in the shapes platforms and Baker return them
|
|
810
|
+
// (NO_GOOGLE_ADS_CONNECTION, PERMISSION_DENIED, INVALID_ACCOUNT_ID).
|
|
811
|
+
/\b(?:(?:ERR|INVALID|MISSING)(?:_[A-Z0-9]+)+|[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*_(?:ERROR|CONNECTION|FAILED|NOT_FOUND|DENIED|REQUIRED|INVALID|EXPIRED|UNAVAILABLE|EXCEEDED|UNREACHABLE|UNAUTHORIZED|FORBIDDEN|TIMEOUT|TOKEN)|BAD_REQUEST|NOT_FOUND|RATE_LIMITED)\b/g,
|
|
812
|
+
// CLI invocations (`baker analytics flow`).
|
|
813
|
+
/\bbaker [a-z][a-z-]*/g
|
|
814
|
+
];
|
|
815
|
+
function completionNoteInternals(note) {
|
|
816
|
+
const hits = [];
|
|
817
|
+
for (const pattern of COMPLETION_NOTE_INTERNALS) {
|
|
818
|
+
for (const match of note.matchAll(pattern)) {
|
|
819
|
+
const index = match.index ?? 0;
|
|
820
|
+
hits.push({ index, end: index + match[0].length, text: match[0] });
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
hits.sort((a, b) => a.index - b.index || b.end - a.end);
|
|
824
|
+
const found = [];
|
|
825
|
+
let coveredUntil = -1;
|
|
826
|
+
for (const hit of hits) {
|
|
827
|
+
if (hit.index < coveredUntil) continue;
|
|
828
|
+
found.push(hit.text);
|
|
829
|
+
coveredUntil = hit.end;
|
|
830
|
+
}
|
|
831
|
+
return found;
|
|
832
|
+
}
|
|
833
|
+
function completionNoteInternalsMessage(internals) {
|
|
834
|
+
return `The completion note is read by the client on the Task, and it carries internal details they cannot use: ${internals.join(", ")}. Rewrite it in product terms \u2014 name the page, campaign or Knowledge entry instead of a file, the platform instead of an account id, and say what is missing instead of an error code.`;
|
|
835
|
+
}
|
|
387
836
|
var actionsCompleteRequestSchema = z.object({
|
|
388
837
|
chatId: z.string(),
|
|
389
838
|
actionRef: z.string().min(1, "actionRef is required"),
|
|
@@ -391,6 +840,11 @@ var actionsCompleteRequestSchema = z.object({
|
|
|
391
840
|
}).transform((body) => ({ ...body, note: (body.note ?? "").trim() })).refine((body) => body.note.length >= ACTION_COMPLETE_NOTE_MIN, {
|
|
392
841
|
message: actionsCompleteNoteMessage,
|
|
393
842
|
path: ["note"]
|
|
843
|
+
}).superRefine((body, ctx) => {
|
|
844
|
+
const internals = completionNoteInternals(body.note);
|
|
845
|
+
if (internals.length > 0) {
|
|
846
|
+
ctx.addIssue({ code: "custom", message: completionNoteInternalsMessage(internals), path: ["note"] });
|
|
847
|
+
}
|
|
394
848
|
});
|
|
395
849
|
var actionsCompleteResponseSchema = okOnlySchema();
|
|
396
850
|
var actionsDiscardRequestSchema = z.object({
|
|
@@ -8055,12 +8509,12 @@ var claimCommand = defineCommand({
|
|
|
8055
8509
|
import { defineCommand as defineCommand2 } from "citty";
|
|
8056
8510
|
registerSchema({
|
|
8057
8511
|
command: "actions.complete",
|
|
8058
|
-
description:
|
|
8512
|
+
description: 'Stage completion of an action (it was DONE). Accepts a real action ID (must be claimed) or a temp ID from the same draft. The action becomes completed when the chat is published. --note is REQUIRED and must describe what you actually did to resolve it (what changed, where, and the outcome) \u2014 it is the client-facing record shown on the Task in Tasks and surfaced by `baker actions log`, so write it for a marketer, in the client\'s language and product terms: a few lines, no file paths, account ids, error codes or `baker` commands ("Weekly review saved in your Knowledge; Google Ads and LinkedIn are not connected yet", not "written to src/content/audits/\u2026md; NO_GOOGLE_ADS_CONNECTION"). A note carrying those is refused. Do NOT use this to drop an action you no longer want \u2014 to remove a staged op use `actions draft remove`, to close an unwanted published action use `actions discard`.',
|
|
8059
8513
|
args: {
|
|
8060
8514
|
id: { type: "string", description: "Action ID or temp ID", required: true },
|
|
8061
8515
|
note: {
|
|
8062
8516
|
type: "string",
|
|
8063
|
-
description: "REQUIRED.
|
|
8517
|
+
description: "REQUIRED. What you did to resolve this \u2014 what changed, where (in product terms: the page, the campaign, Knowledge), and the outcome \u2014 in a few lines. The client reads it on the Task: no file paths, account ids, error codes or `baker` commands.",
|
|
8064
8518
|
required: true
|
|
8065
8519
|
}
|
|
8066
8520
|
}
|
|
@@ -8075,7 +8529,7 @@ var completeCommand = defineCommand2({
|
|
|
8075
8529
|
"action-id": { type: "string", description: "Action ID or temp ID", required: false },
|
|
8076
8530
|
note: {
|
|
8077
8531
|
type: "string",
|
|
8078
|
-
description: "REQUIRED. What you did
|
|
8532
|
+
description: "REQUIRED. What you did, where (in product terms) and the outcome \u2014 read by the client, so no file paths, account ids or error codes.",
|
|
8079
8533
|
required: false
|
|
8080
8534
|
}
|
|
8081
8535
|
},
|
|
@@ -8094,6 +8548,10 @@ var completeCommand = defineCommand2({
|
|
|
8094
8548
|
`--note is required and must describe what you did (\u2265${ACTION_COMPLETE_NOTE_MIN} chars): what changed, where, and the outcome. This becomes the client-facing record surfaced by \`baker actions log\`.`
|
|
8095
8549
|
);
|
|
8096
8550
|
}
|
|
8551
|
+
const internals = completionNoteInternals(note);
|
|
8552
|
+
if (internals.length > 0) {
|
|
8553
|
+
failValidation(`--note: ${completionNoteInternalsMessage(internals)} Then run the same command again.`);
|
|
8554
|
+
}
|
|
8097
8555
|
const chatId = requireChatId();
|
|
8098
8556
|
await apiPost("/api/actions/complete", { chatId, actionRef: id, note });
|
|
8099
8557
|
writeOk();
|
|
@@ -12677,8 +13135,8 @@ var writeMdRows = (rows, fields, notices) => {
|
|
|
12677
13135
|
};
|
|
12678
13136
|
var ROW_WRITERS = { csv: writeCsvRows, jsonl: writeJsonlRows, md: writeMdRows };
|
|
12679
13137
|
function writeRows(format, rows, columns, notices) {
|
|
12680
|
-
const
|
|
12681
|
-
|
|
13138
|
+
const write2 = ROW_WRITERS[format] ?? writeMdRows;
|
|
13139
|
+
write2(rows, columns, notices);
|
|
12682
13140
|
if (rows.length > REPEAT_NOTICE_ABOVE_ROWS) {
|
|
12683
13141
|
for (const line of notices) writeLine(line);
|
|
12684
13142
|
}
|
|
@@ -21881,7 +22339,7 @@ Subcommands:
|
|
|
21881
22339
|
|
|
21882
22340
|
// src/commands/ads/linkedin/creatives.ts
|
|
21883
22341
|
import { defineCommand as defineCommand44 } from "citty";
|
|
21884
|
-
function
|
|
22342
|
+
function asRecord2(value) {
|
|
21885
22343
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
21886
22344
|
}
|
|
21887
22345
|
function asString(value) {
|
|
@@ -21891,12 +22349,12 @@ function creativeDestination(content) {
|
|
|
21891
22349
|
if (!content) return { format: "unknown" };
|
|
21892
22350
|
const reference = asString(content.reference);
|
|
21893
22351
|
if (reference) return { format: "post", postUrn: reference };
|
|
21894
|
-
const textAd =
|
|
22352
|
+
const textAd = asRecord2(content.textAd);
|
|
21895
22353
|
if (textAd) return { format: "text", landingUrl: asString(textAd.landingPage) };
|
|
21896
|
-
const spotlight =
|
|
22354
|
+
const spotlight = asRecord2(content.spotlight);
|
|
21897
22355
|
if (spotlight) return { format: "spotlight", landingUrl: asString(spotlight.landingPage) };
|
|
21898
|
-
if (
|
|
21899
|
-
if (
|
|
22356
|
+
if (asRecord2(content.follower)) return { format: "follower" };
|
|
22357
|
+
if (asRecord2(content.jobs)) return { format: "jobs" };
|
|
21900
22358
|
return { format: "unknown" };
|
|
21901
22359
|
}
|
|
21902
22360
|
var COMPACT_COLUMNS = [
|
|
@@ -21927,7 +22385,7 @@ function compactRow(row) {
|
|
|
21927
22385
|
function readPath(row, path48) {
|
|
21928
22386
|
let current = row;
|
|
21929
22387
|
for (const segment of path48.split(".")) {
|
|
21930
|
-
const record =
|
|
22388
|
+
const record = asRecord2(current);
|
|
21931
22389
|
if (!record) return void 0;
|
|
21932
22390
|
current = record[segment];
|
|
21933
22391
|
}
|
|
@@ -25300,10 +25758,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
|
|
|
25300
25758
|
}
|
|
25301
25759
|
},
|
|
25302
25760
|
run: async ({ args: args5 }) => {
|
|
25303
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
25304
|
-
const { requireChatId: requireChatId2 } = await import("./env-
|
|
25305
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
25306
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
25761
|
+
const { apiPost: apiPost2 } = await import("./client-PWRZOA3Q.js");
|
|
25762
|
+
const { requireChatId: requireChatId2 } = await import("./env-TQTHWLBN.js");
|
|
25763
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HD63GTWI.js");
|
|
25764
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-5662SBDW.js");
|
|
25307
25765
|
try {
|
|
25308
25766
|
const accountId = bareAccountId2(args5);
|
|
25309
25767
|
const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
|
|
@@ -25448,10 +25906,10 @@ function duplicateCommand2(entity, label) {
|
|
|
25448
25906
|
replace: { type: "boolean", description: "Pause the original once the copy publishes" }
|
|
25449
25907
|
},
|
|
25450
25908
|
run: async ({ args: args5 }) => {
|
|
25451
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
25452
|
-
const { requireChatId: requireChatId2 } = await import("./env-
|
|
25453
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
25454
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
25909
|
+
const { apiPost: apiPost2 } = await import("./client-PWRZOA3Q.js");
|
|
25910
|
+
const { requireChatId: requireChatId2 } = await import("./env-TQTHWLBN.js");
|
|
25911
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HD63GTWI.js");
|
|
25912
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-5662SBDW.js");
|
|
25455
25913
|
try {
|
|
25456
25914
|
const accountId = bareAccountId2(args5);
|
|
25457
25915
|
const chatId = requireChatId2();
|
|
@@ -33068,8 +33526,8 @@ var conversionsCommand3 = (() => {
|
|
|
33068
33526
|
const args6 = parseConversionsArgs(raw, process.argv);
|
|
33069
33527
|
for (const eventKey of args6.eventKeys) refuseUnmatchableKey(eventKey);
|
|
33070
33528
|
const before = await apiPost("/api/analytics/conversions", {});
|
|
33071
|
-
const
|
|
33072
|
-
const stored =
|
|
33529
|
+
const write2 = conversionsWrite(args6, before.data.definitions);
|
|
33530
|
+
const stored = write2 ? (await apiPost("/api/analytics/conversions", write2)).data.definitions : before.data.definitions;
|
|
33073
33531
|
const report = await apiPost("/api/analytics/query", {
|
|
33074
33532
|
preset: "conversions",
|
|
33075
33533
|
days: args6.days
|
|
@@ -33445,7 +33903,11 @@ function rosterRow(avatar) {
|
|
|
33445
33903
|
};
|
|
33446
33904
|
}
|
|
33447
33905
|
function chatIdFromEnv() {
|
|
33448
|
-
|
|
33906
|
+
try {
|
|
33907
|
+
return getEnv().BAKER_CHAT_ID || void 0;
|
|
33908
|
+
} catch {
|
|
33909
|
+
return void 0;
|
|
33910
|
+
}
|
|
33449
33911
|
}
|
|
33450
33912
|
function rosterHints(roster, statusFilter) {
|
|
33451
33913
|
if (roster.length === 0) {
|
|
@@ -38974,7 +39436,7 @@ function sceneSpokenText(scene) {
|
|
|
38974
39436
|
return (scene.dialogue ?? []).map((d) => d.line?.trim()).filter((l) => Boolean(l)).join(" ") || null;
|
|
38975
39437
|
}
|
|
38976
39438
|
function buildMotionBoard(blueprint) {
|
|
38977
|
-
const
|
|
39439
|
+
const round5 = (n) => Math.round(n * 100) / 100;
|
|
38978
39440
|
let cursor = 0;
|
|
38979
39441
|
return blueprint.scenes.map((scene, i) => {
|
|
38980
39442
|
const start_s = scene.start_s ?? cursor;
|
|
@@ -38986,15 +39448,15 @@ function buildMotionBoard(blueprint) {
|
|
|
38986
39448
|
const graphics = [
|
|
38987
39449
|
...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
|
|
38988
39450
|
kind: "text",
|
|
38989
|
-
at_s:
|
|
38990
|
-
dur_s:
|
|
39451
|
+
at_s: round5(ov.appears_at_s ?? start_s),
|
|
39452
|
+
dur_s: round5(ov.duration_s ?? 2.5),
|
|
38991
39453
|
position: ov.position ?? "bottom_center",
|
|
38992
39454
|
text: ov.text?.trim()
|
|
38993
39455
|
})),
|
|
38994
39456
|
...(floats.success ? floats.data : []).map((fe) => ({
|
|
38995
39457
|
kind: "graphic",
|
|
38996
|
-
at_s:
|
|
38997
|
-
dur_s:
|
|
39458
|
+
at_s: round5(fe.appears_at_s ?? start_s),
|
|
39459
|
+
dur_s: round5(fe.duration_s ?? 2.5),
|
|
38998
39460
|
position: fe.position ?? "bottom_center",
|
|
38999
39461
|
label: fe.brand_name || fe.what_it_represents || fe.description || fe.kind || "element"
|
|
39000
39462
|
}))
|
|
@@ -39002,7 +39464,7 @@ function buildMotionBoard(blueprint) {
|
|
|
39002
39464
|
return {
|
|
39003
39465
|
scene: i,
|
|
39004
39466
|
role: resolveSceneRole(scene, i, blueprint.scenes.length),
|
|
39005
|
-
window_s: [
|
|
39467
|
+
window_s: [round5(start_s), round5(end_s)],
|
|
39006
39468
|
// A continuation b-roll scene shares the previous scene's end frame as its start
|
|
39007
39469
|
// (no own `s<i>_start` node), so point the storyboard at that shared keyframe.
|
|
39008
39470
|
storyboard_frames: [scene.continues_previous && i > 0 ? `s${i - 1}_end` : `s${i}_start`],
|
|
@@ -40765,7 +41227,7 @@ ${describeRewrites(healed.rewrites)}
|
|
|
40765
41227
|
// "edited since last render". Computed from the on-disk canvas.json +
|
|
40766
41228
|
// prompt.json — the same helper the edit-sync uses, so the two are comparable.
|
|
40767
41229
|
sourceSha: await computeSourceSha(filePath),
|
|
40768
|
-
chatId:
|
|
41230
|
+
chatId: getEnv().BAKER_CHAT_ID || void 0,
|
|
40769
41231
|
canvasSnapshotUrl
|
|
40770
41232
|
};
|
|
40771
41233
|
if (client) {
|
|
@@ -44756,7 +45218,11 @@ function detectCreativeContentType(filePath) {
|
|
|
44756
45218
|
});
|
|
44757
45219
|
}
|
|
44758
45220
|
function chatIdFromEnv2() {
|
|
44759
|
-
|
|
45221
|
+
try {
|
|
45222
|
+
return getEnv().BAKER_CHAT_ID || void 0;
|
|
45223
|
+
} catch {
|
|
45224
|
+
return void 0;
|
|
45225
|
+
}
|
|
44760
45226
|
}
|
|
44761
45227
|
function parseOptionalUrl(value) {
|
|
44762
45228
|
if (value === void 0 || value.trim() === "") {
|
|
@@ -52673,7 +53139,7 @@ var extractCommand = defineCommand149({
|
|
|
52673
53139
|
import { defineCommand as defineCommand150 } from "citty";
|
|
52674
53140
|
|
|
52675
53141
|
// src/commands/images/providerHits.ts
|
|
52676
|
-
function
|
|
53142
|
+
function asRecord3(value) {
|
|
52677
53143
|
return value && typeof value === "object" ? value : {};
|
|
52678
53144
|
}
|
|
52679
53145
|
function str(value) {
|
|
@@ -52698,7 +53164,7 @@ function providerHitNormalizer(record, full) {
|
|
|
52698
53164
|
if (!full) {
|
|
52699
53165
|
return compact3;
|
|
52700
53166
|
}
|
|
52701
|
-
const group =
|
|
53167
|
+
const group = asRecord3(record.group);
|
|
52702
53168
|
return {
|
|
52703
53169
|
...compact3,
|
|
52704
53170
|
externalUrl: str(record.externalUrl),
|
|
@@ -56603,7 +57069,7 @@ function dedupe(findings) {
|
|
|
56603
57069
|
|
|
56604
57070
|
// src/engine/landing/lib/critique.ts
|
|
56605
57071
|
var FAMILIES = ["typography", "color", "borders_depth", "motion", "spacing", "copy", "integrity"];
|
|
56606
|
-
function
|
|
57072
|
+
function round4(n) {
|
|
56607
57073
|
return Math.round(n * 100) / 100;
|
|
56608
57074
|
}
|
|
56609
57075
|
function clamp012(n) {
|
|
@@ -56640,11 +57106,11 @@ function critiqueLanding(input) {
|
|
|
56640
57106
|
const dimensions = FAMILIES.map((family) => {
|
|
56641
57107
|
const fam = findings.filter((f) => f.family === family);
|
|
56642
57108
|
const penalty = fam.reduce((s, f) => s + SEVERITY_WEIGHT[f.severity], 0);
|
|
56643
|
-
const score =
|
|
57109
|
+
const score = round4(clamp012(1 - penalty));
|
|
56644
57110
|
const note = fam.length === 0 ? "clean" : `${fam.length} finding(s): ${describeCounts(fam)}`;
|
|
56645
57111
|
return { dimension: family, score, note };
|
|
56646
57112
|
});
|
|
56647
|
-
const overall =
|
|
57113
|
+
const overall = round4(dimensions.reduce((s, d) => s + d.score, 0) / dimensions.length);
|
|
56648
57114
|
const counts = {
|
|
56649
57115
|
block: findings.filter((f) => f.severity === "block").length,
|
|
56650
57116
|
warn: findings.filter((f) => f.severity === "warn").length,
|
|
@@ -60803,7 +61269,7 @@ function writeJsonl(data) {
|
|
|
60803
61269
|
`);
|
|
60804
61270
|
}
|
|
60805
61271
|
}
|
|
60806
|
-
function
|
|
61272
|
+
function writeMd2(data, fields) {
|
|
60807
61273
|
if (data.length === 0) return;
|
|
60808
61274
|
const cols = fields ?? Object.keys(data[0] ?? {});
|
|
60809
61275
|
process.stdout.write(`| ${cols.join(" | ")} |
|
|
@@ -60825,7 +61291,7 @@ function writeResearchOutput(data, format, fields) {
|
|
|
60825
61291
|
writeJsonl(data);
|
|
60826
61292
|
break;
|
|
60827
61293
|
case "md":
|
|
60828
|
-
|
|
61294
|
+
writeMd2(data, fields);
|
|
60829
61295
|
break;
|
|
60830
61296
|
default:
|
|
60831
61297
|
writeResearchJson({ ok: true, data });
|