@koda-sl/baker-cli 0.345.0-dev.9f4314fa9 → 0.346.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.
- package/README.md +8 -4
- package/dist/{chunk-KGDL7F7M.js → chunk-2IC3CGQO.js} +3 -3
- package/dist/chunk-2OKSJNLA.js +855 -0
- package/dist/chunk-2OKSJNLA.js.map +1 -0
- package/dist/{chunk-XPUSSDLR.js → chunk-4QXKWIFC.js} +3 -3
- package/dist/{chunk-JWMLQSGK.js → chunk-NA5CPMUA.js} +4 -4
- package/dist/{chunk-PWGY347J.js → chunk-XWHHYHKQ.js} +2 -2
- package/dist/{chunk-D5P4COPD.js → chunk-YBD3W4M7.js} +9 -8
- package/dist/chunk-YBD3W4M7.js.map +1 -0
- package/dist/cli.js +341 -761
- package/dist/cli.js.map +1 -1
- package/dist/{client-PWRZOA3Q.js → client-ODCNYCP4.js} +4 -4
- package/dist/engine/index.js +3 -3
- package/dist/{env-TQTHWLBN.js → env-BSG7TY5Y.js} +6 -2
- package/dist/{output-HD63GTWI.js → output-2XBCYF7L.js} +5 -5
- package/dist/{shared-5662SBDW.js → shared-RYAF7Y7H.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-4VP5WWPR.js +0 -376
- package/dist/chunk-4VP5WWPR.js.map +0 -1
- package/dist/chunk-D5P4COPD.js.map +0 -1
- /package/dist/{chunk-KGDL7F7M.js.map → chunk-2IC3CGQO.js.map} +0 -0
- /package/dist/{chunk-XPUSSDLR.js.map → chunk-4QXKWIFC.js.map} +0 -0
- /package/dist/{chunk-JWMLQSGK.js.map → chunk-NA5CPMUA.js.map} +0 -0
- /package/dist/{chunk-PWGY347J.js.map → chunk-XWHHYHKQ.js.map} +0 -0
- /package/dist/{client-PWRZOA3Q.js.map → client-ODCNYCP4.js.map} +0 -0
- /package/dist/{env-TQTHWLBN.js.map → env-BSG7TY5Y.js.map} +0 -0
- /package/dist/{output-HD63GTWI.js.map → output-2XBCYF7L.js.map} +0 -0
- /package/dist/{shared-5662SBDW.js.map → shared-RYAF7Y7H.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-YBD3W4M7.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-NA5CPMUA.js";
|
|
80
80
|
import {
|
|
81
81
|
buildQueryCacheKey,
|
|
82
82
|
cacheGet,
|
|
@@ -92,33 +92,42 @@ import {
|
|
|
92
92
|
writeAdsJson,
|
|
93
93
|
writeAdsOutput,
|
|
94
94
|
writeJsonEnvelope
|
|
95
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-2IC3CGQO.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-4QXKWIFC.js";
|
|
103
103
|
import {
|
|
104
104
|
installExitRecord,
|
|
105
105
|
installStreamTaps,
|
|
106
106
|
logInvocation
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-XWHHYHKQ.js";
|
|
108
108
|
import {
|
|
109
|
+
adContentNormalizer,
|
|
109
110
|
captureBudgetMs,
|
|
110
111
|
captureProxyCredentials,
|
|
111
112
|
captureVimeoCookie,
|
|
113
|
+
compactImage,
|
|
114
|
+
compactVideo,
|
|
112
115
|
getEnv,
|
|
113
116
|
hasOpenRouterKey,
|
|
114
117
|
isProxyFailure,
|
|
115
118
|
openRouterKey,
|
|
119
|
+
optionalChatId,
|
|
116
120
|
plannedRoutes,
|
|
117
121
|
refuseNonPublicUrl,
|
|
118
122
|
requireChatId,
|
|
119
123
|
resolveChatId,
|
|
120
|
-
shouldEscalate
|
|
121
|
-
|
|
124
|
+
shouldEscalate,
|
|
125
|
+
testimonialNormalizer,
|
|
126
|
+
videoNormalizer,
|
|
127
|
+
winningAdNormalizer,
|
|
128
|
+
writeJson,
|
|
129
|
+
writeOutput
|
|
130
|
+
} from "./chunk-2OKSJNLA.js";
|
|
122
131
|
|
|
123
132
|
// src/cli.ts
|
|
124
133
|
import { defineCommand as defineCommand245, runMain } from "citty";
|
|
@@ -159,420 +168,6 @@ import { defineCommand as defineCommand18 } from "citty";
|
|
|
159
168
|
// src/commands/actions/claim.ts
|
|
160
169
|
import { defineCommand } from "citty";
|
|
161
170
|
|
|
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
|
-
|
|
576
171
|
// src/schemas.ts
|
|
577
172
|
var registry = /* @__PURE__ */ new Map();
|
|
578
173
|
function registerSchema(schema) {
|
|
@@ -13082,8 +12677,8 @@ var writeMdRows = (rows, fields, notices) => {
|
|
|
13082
12677
|
};
|
|
13083
12678
|
var ROW_WRITERS = { csv: writeCsvRows, jsonl: writeJsonlRows, md: writeMdRows };
|
|
13084
12679
|
function writeRows(format, rows, columns, notices) {
|
|
13085
|
-
const
|
|
13086
|
-
|
|
12680
|
+
const write = ROW_WRITERS[format] ?? writeMdRows;
|
|
12681
|
+
write(rows, columns, notices);
|
|
13087
12682
|
if (rows.length > REPEAT_NOTICE_ABOVE_ROWS) {
|
|
13088
12683
|
for (const line of notices) writeLine(line);
|
|
13089
12684
|
}
|
|
@@ -22286,7 +21881,7 @@ Subcommands:
|
|
|
22286
21881
|
|
|
22287
21882
|
// src/commands/ads/linkedin/creatives.ts
|
|
22288
21883
|
import { defineCommand as defineCommand44 } from "citty";
|
|
22289
|
-
function
|
|
21884
|
+
function asRecord(value) {
|
|
22290
21885
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
22291
21886
|
}
|
|
22292
21887
|
function asString(value) {
|
|
@@ -22296,12 +21891,12 @@ function creativeDestination(content) {
|
|
|
22296
21891
|
if (!content) return { format: "unknown" };
|
|
22297
21892
|
const reference = asString(content.reference);
|
|
22298
21893
|
if (reference) return { format: "post", postUrn: reference };
|
|
22299
|
-
const textAd =
|
|
21894
|
+
const textAd = asRecord(content.textAd);
|
|
22300
21895
|
if (textAd) return { format: "text", landingUrl: asString(textAd.landingPage) };
|
|
22301
|
-
const spotlight =
|
|
21896
|
+
const spotlight = asRecord(content.spotlight);
|
|
22302
21897
|
if (spotlight) return { format: "spotlight", landingUrl: asString(spotlight.landingPage) };
|
|
22303
|
-
if (
|
|
22304
|
-
if (
|
|
21898
|
+
if (asRecord(content.follower)) return { format: "follower" };
|
|
21899
|
+
if (asRecord(content.jobs)) return { format: "jobs" };
|
|
22305
21900
|
return { format: "unknown" };
|
|
22306
21901
|
}
|
|
22307
21902
|
var COMPACT_COLUMNS = [
|
|
@@ -22332,7 +21927,7 @@ function compactRow(row) {
|
|
|
22332
21927
|
function readPath(row, path48) {
|
|
22333
21928
|
let current = row;
|
|
22334
21929
|
for (const segment of path48.split(".")) {
|
|
22335
|
-
const record =
|
|
21930
|
+
const record = asRecord(current);
|
|
22336
21931
|
if (!record) return void 0;
|
|
22337
21932
|
current = record[segment];
|
|
22338
21933
|
}
|
|
@@ -25705,10 +25300,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
|
|
|
25705
25300
|
}
|
|
25706
25301
|
},
|
|
25707
25302
|
run: async ({ args: args5 }) => {
|
|
25708
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
25709
|
-
const { requireChatId: requireChatId2 } = await import("./env-
|
|
25710
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
25711
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
25303
|
+
const { apiPost: apiPost2 } = await import("./client-ODCNYCP4.js");
|
|
25304
|
+
const { requireChatId: requireChatId2 } = await import("./env-BSG7TY5Y.js");
|
|
25305
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-2XBCYF7L.js");
|
|
25306
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-RYAF7Y7H.js");
|
|
25712
25307
|
try {
|
|
25713
25308
|
const accountId = bareAccountId2(args5);
|
|
25714
25309
|
const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
|
|
@@ -25853,10 +25448,10 @@ function duplicateCommand2(entity, label) {
|
|
|
25853
25448
|
replace: { type: "boolean", description: "Pause the original once the copy publishes" }
|
|
25854
25449
|
},
|
|
25855
25450
|
run: async ({ args: args5 }) => {
|
|
25856
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
25857
|
-
const { requireChatId: requireChatId2 } = await import("./env-
|
|
25858
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
25859
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
25451
|
+
const { apiPost: apiPost2 } = await import("./client-ODCNYCP4.js");
|
|
25452
|
+
const { requireChatId: requireChatId2 } = await import("./env-BSG7TY5Y.js");
|
|
25453
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-2XBCYF7L.js");
|
|
25454
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-RYAF7Y7H.js");
|
|
25860
25455
|
try {
|
|
25861
25456
|
const accountId = bareAccountId2(args5);
|
|
25862
25457
|
const chatId = requireChatId2();
|
|
@@ -31032,278 +30627,6 @@ function mergeStoredWithCounts(stored, reported) {
|
|
|
31032
30627
|
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
31033
30628
|
}
|
|
31034
30629
|
|
|
31035
|
-
// src/commands/analytics/render.ts
|
|
31036
|
-
var SPARKLINE_POINTS = 30;
|
|
31037
|
-
var DASHBOARD_ONLY_FIELDS = /* @__PURE__ */ new Set([
|
|
31038
|
-
// The Convex row id. It exists so a dashboard can link to the row; an agent
|
|
31039
|
-
// addresses a landing by `landingId`, which is the id in its `_definition.md`.
|
|
31040
|
-
"landingRef"
|
|
31041
|
-
]);
|
|
31042
|
-
function isAbsent(value) {
|
|
31043
|
-
if (value === "") return true;
|
|
31044
|
-
if (Array.isArray(value)) return value.length === 0;
|
|
31045
|
-
if (typeof value === "object" && value !== null) return Object.keys(value).length === 0;
|
|
31046
|
-
return false;
|
|
31047
|
-
}
|
|
31048
|
-
function resample(series, points) {
|
|
31049
|
-
if (series.length <= points || points < 1) return [...series];
|
|
31050
|
-
const out = [];
|
|
31051
|
-
for (let i = 0; i < points; i += 1) {
|
|
31052
|
-
const from = Math.floor(i * series.length / points);
|
|
31053
|
-
const to = Math.floor((i + 1) * series.length / points);
|
|
31054
|
-
let sum = 0;
|
|
31055
|
-
for (let j = from; j < to; j += 1) sum += series[j] ?? 0;
|
|
31056
|
-
out.push(sum);
|
|
31057
|
-
}
|
|
31058
|
-
return out;
|
|
31059
|
-
}
|
|
31060
|
-
function pruneValue(value, full) {
|
|
31061
|
-
if (Array.isArray(value)) return value.map((entry) => pruneValue(entry, full));
|
|
31062
|
-
if (typeof value === "object" && value !== null) {
|
|
31063
|
-
return pruneRow(value, full);
|
|
31064
|
-
}
|
|
31065
|
-
return value;
|
|
31066
|
-
}
|
|
31067
|
-
function pruneRow(row, full) {
|
|
31068
|
-
const out = {};
|
|
31069
|
-
for (const [key, value] of Object.entries(row)) {
|
|
31070
|
-
if (DASHBOARD_ONLY_FIELDS.has(key)) continue;
|
|
31071
|
-
if (key === "sparkline" && Array.isArray(value)) {
|
|
31072
|
-
if (!full) continue;
|
|
31073
|
-
out[key] = resample(value, SPARKLINE_POINTS);
|
|
31074
|
-
continue;
|
|
31075
|
-
}
|
|
31076
|
-
if (isAbsent(value)) continue;
|
|
31077
|
-
out[key] = pruneValue(value, full);
|
|
31078
|
-
}
|
|
31079
|
-
return out;
|
|
31080
|
-
}
|
|
31081
|
-
function pruneForAgent(data, full) {
|
|
31082
|
-
return pruneRow(data, full);
|
|
31083
|
-
}
|
|
31084
|
-
function isTabular(rows) {
|
|
31085
|
-
return rows.every(
|
|
31086
|
-
(row) => typeof row === "object" && row !== null && !Array.isArray(row) && Object.values(row).every(
|
|
31087
|
-
(value) => value === null || typeof value !== "object" || Array.isArray(value) && value.every((e) => typeof e !== "object")
|
|
31088
|
-
)
|
|
31089
|
-
);
|
|
31090
|
-
}
|
|
31091
|
-
function cell2(value, key) {
|
|
31092
|
-
if (value === null || value === void 0) return "";
|
|
31093
|
-
if (Array.isArray(value)) return value.join(" ");
|
|
31094
|
-
if (typeof value === "number" && !Number.isInteger(value)) {
|
|
31095
|
-
if (key?.endsWith("Ms")) return String(Math.round(value));
|
|
31096
|
-
return value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
|
|
31097
|
-
}
|
|
31098
|
-
return String(value);
|
|
31099
|
-
}
|
|
31100
|
-
var IDENTITY_COLUMNS = [
|
|
31101
|
-
"landingId",
|
|
31102
|
-
"name",
|
|
31103
|
-
"slug",
|
|
31104
|
-
"path",
|
|
31105
|
-
"flowSlug",
|
|
31106
|
-
"stepId",
|
|
31107
|
-
"value",
|
|
31108
|
-
"key",
|
|
31109
|
-
"bucket",
|
|
31110
|
-
"tag",
|
|
31111
|
-
"eventName",
|
|
31112
|
-
"release",
|
|
31113
|
-
"place",
|
|
31114
|
-
"bot",
|
|
31115
|
-
"source",
|
|
31116
|
-
"medium",
|
|
31117
|
-
"campaign",
|
|
31118
|
-
"platform",
|
|
31119
|
-
"sessionId",
|
|
31120
|
-
"eventId"
|
|
31121
|
-
];
|
|
31122
|
-
function byIdentityFirst(a, b) {
|
|
31123
|
-
const ia = IDENTITY_COLUMNS.indexOf(a);
|
|
31124
|
-
const ib = IDENTITY_COLUMNS.indexOf(b);
|
|
31125
|
-
if (ia !== -1 || ib !== -1)
|
|
31126
|
-
return (ia === -1 ? Number.MAX_SAFE_INTEGER : ia) - (ib === -1 ? Number.MAX_SAFE_INTEGER : ib);
|
|
31127
|
-
return 0;
|
|
31128
|
-
}
|
|
31129
|
-
var BLOCK_ORDER = ["window", "totals", "previous", "pageInfo"];
|
|
31130
|
-
function byBlockOrder(a, b) {
|
|
31131
|
-
const rank = (key) => {
|
|
31132
|
-
const at = BLOCK_ORDER.indexOf(key);
|
|
31133
|
-
if (at !== -1) return at;
|
|
31134
|
-
return key === "preset" ? BLOCK_ORDER.length + 1 : BLOCK_ORDER.length;
|
|
31135
|
-
};
|
|
31136
|
-
return rank(a) - rank(b);
|
|
31137
|
-
}
|
|
31138
|
-
function columnsOf(rows) {
|
|
31139
|
-
const seen = [];
|
|
31140
|
-
for (const row of rows) {
|
|
31141
|
-
for (const key of Object.keys(row)) {
|
|
31142
|
-
if (!seen.includes(key)) seen.push(key);
|
|
31143
|
-
}
|
|
31144
|
-
}
|
|
31145
|
-
return seen.filter((key) => rows.some((row) => !isAbsent(row[key]) && row[key] !== null && row[key] !== void 0)).sort(byIdentityFirst);
|
|
31146
|
-
}
|
|
31147
|
-
function table2(rows) {
|
|
31148
|
-
const cols = columnsOf(rows);
|
|
31149
|
-
if (cols.length === 0) return "";
|
|
31150
|
-
const head = `| ${cols.join(" | ")} |`;
|
|
31151
|
-
const rule = `| ${cols.map(() => "---").join(" | ")} |`;
|
|
31152
|
-
const body = rows.map((row) => `| ${cols.map((col) => cell2(row[col], col)).join(" | ")} |`);
|
|
31153
|
-
return [head, rule, ...body].join("\n");
|
|
31154
|
-
}
|
|
31155
|
-
function isRowList(value) {
|
|
31156
|
-
return Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry));
|
|
31157
|
-
}
|
|
31158
|
-
function labelOf(row, index) {
|
|
31159
|
-
for (const key of IDENTITY_COLUMNS) {
|
|
31160
|
-
const value = row[key];
|
|
31161
|
-
if (typeof value === "string" && value !== "") return value;
|
|
31162
|
-
}
|
|
31163
|
-
return `#${index + 1}`;
|
|
31164
|
-
}
|
|
31165
|
-
function nestedBlock(name, rows) {
|
|
31166
|
-
const parents = rows.map(
|
|
31167
|
-
(row) => Object.fromEntries(Object.entries(row).filter(([, value]) => !isRowList(value) && !isPlainRow(value)))
|
|
31168
|
-
);
|
|
31169
|
-
const parts = [`### ${name}`, table2(parents)];
|
|
31170
|
-
rows.forEach((row, index) => {
|
|
31171
|
-
for (const [key, value] of Object.entries(row)) {
|
|
31172
|
-
if (isRowList(value)) parts.push(`#### ${name}[${labelOf(row, index)}].${key}`, table2(value));
|
|
31173
|
-
else if (isPlainRow(value)) parts.push(`#### ${name}[${labelOf(row, index)}].${key}`, table2([value]));
|
|
31174
|
-
}
|
|
31175
|
-
});
|
|
31176
|
-
return parts.filter((part) => part !== "").join("\n");
|
|
31177
|
-
}
|
|
31178
|
-
function isPlainRow(value) {
|
|
31179
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31180
|
-
}
|
|
31181
|
-
function block(name, value) {
|
|
31182
|
-
if (Array.isArray(value)) {
|
|
31183
|
-
if (value.length === 0) return "";
|
|
31184
|
-
if (isTabular(value)) return `### ${name}
|
|
31185
|
-
${table2(value)}`;
|
|
31186
|
-
if (isRowList(value)) return nestedBlock(name, value);
|
|
31187
|
-
return `### ${name}
|
|
31188
|
-
${JSON.stringify(value)}`;
|
|
31189
|
-
}
|
|
31190
|
-
if (typeof value === "object" && value !== null) {
|
|
31191
|
-
const entries = Object.entries(value);
|
|
31192
|
-
if (entries.length === 0) return "";
|
|
31193
|
-
if (entries.every(([, v]) => v === null || typeof v !== "object")) {
|
|
31194
|
-
return `### ${name}
|
|
31195
|
-
${entries.map(([k, v]) => `- ${k}: ${v === null ? "null" : cell2(v, k)}`).join("\n")}`;
|
|
31196
|
-
}
|
|
31197
|
-
return `### ${name}
|
|
31198
|
-
${JSON.stringify(value)}`;
|
|
31199
|
-
}
|
|
31200
|
-
return `### ${name}
|
|
31201
|
-
${cell2(value)}`;
|
|
31202
|
-
}
|
|
31203
|
-
function renderMarkdown3(envelope) {
|
|
31204
|
-
const parts = [];
|
|
31205
|
-
for (const warning of envelope.warnings ?? []) parts.push(`> **${warning.code}** \u2014 ${warning.message}`);
|
|
31206
|
-
for (const hint of envelope.hints ?? []) parts.push(`> ${hint}`);
|
|
31207
|
-
for (const [name, value] of Object.entries(envelope.data).sort(([a], [b]) => byBlockOrder(a, b))) {
|
|
31208
|
-
const rendered = block(name, value);
|
|
31209
|
-
if (rendered !== "") parts.push(rendered);
|
|
31210
|
-
}
|
|
31211
|
-
return `${parts.join("\n\n")}
|
|
31212
|
-
`;
|
|
31213
|
-
}
|
|
31214
|
-
function missingBreakdownHint(data, asked) {
|
|
31215
|
-
if (asked.eventName === void 0) return [];
|
|
31216
|
-
const breakdown = data.eventBreakdown;
|
|
31217
|
-
if (Array.isArray(breakdown) && breakdown.length > 0) return [];
|
|
31218
|
-
const known = Array.isArray(data.customEvents) ? data.customEvents.flatMap((row) => isPlainRow(row) && typeof row.eventName === "string" ? [row.eventName] : []) : [];
|
|
31219
|
-
return [
|
|
31220
|
-
`No rows came back for --event ${asked.eventName}${asked.property ? ` --property ${asked.property}` : ""}. That event or property does not exist on these pages${known.length > 0 ? `; the ones that do are: ${known.slice(0, 12).join(", ")}${known.length > 12 ? ", \u2026" : ""}` : ""}.`
|
|
31221
|
-
];
|
|
31222
|
-
}
|
|
31223
|
-
var ANALYTICS_OUTPUT_FORMATS = ["json", "md"];
|
|
31224
|
-
function isAnalyticsOutputFormat(value) {
|
|
31225
|
-
return ANALYTICS_OUTPUT_FORMATS.includes(value);
|
|
31226
|
-
}
|
|
31227
|
-
function writeAnalyticsReport(envelope, format) {
|
|
31228
|
-
if (format === "md") {
|
|
31229
|
-
process.stdout.write(renderMarkdown3(envelope));
|
|
31230
|
-
return;
|
|
31231
|
-
}
|
|
31232
|
-
process.stdout.write(`${JSON.stringify(envelope)}
|
|
31233
|
-
`);
|
|
31234
|
-
}
|
|
31235
|
-
var ROWS_BEFORE_FORMAT_HINT = 25;
|
|
31236
|
-
function rowCount(data) {
|
|
31237
|
-
let total = 0;
|
|
31238
|
-
for (const value of Object.values(data)) {
|
|
31239
|
-
if (Array.isArray(value)) total += value.length;
|
|
31240
|
-
}
|
|
31241
|
-
return total;
|
|
31242
|
-
}
|
|
31243
|
-
function formatHint(data, format) {
|
|
31244
|
-
if (format === "md") return [];
|
|
31245
|
-
const rows = rowCount(data);
|
|
31246
|
-
if (rows < ROWS_BEFORE_FORMAT_HINT) return [];
|
|
31247
|
-
return [
|
|
31248
|
-
`This report is ${rows} rows. If you are going to read the numbers rather than pick one field out of them, --output md returns the same answer as tables, typically a third to a half smaller.`
|
|
31249
|
-
];
|
|
31250
|
-
}
|
|
31251
|
-
|
|
31252
|
-
// src/commands/analytics/conversionsMarkdown.ts
|
|
31253
|
-
function doorsCell(doors) {
|
|
31254
|
-
return doors.map((door) => `${door.door}=${door.events}/${door.sessions}`).join(" ");
|
|
31255
|
-
}
|
|
31256
|
-
function eventKeysCell(eventKeys) {
|
|
31257
|
-
const formKeys = eventKeys.filter((key) => key.startsWith("form:")).length;
|
|
31258
|
-
const others = eventKeys.filter((key) => !key.startsWith("form:"));
|
|
31259
|
-
return [...others, ...formKeys > 0 ? [`${formKeys} Form ending(s)`] : []].join(" + ");
|
|
31260
|
-
}
|
|
31261
|
-
function trafficByForm(candidates) {
|
|
31262
|
-
const byForm = /* @__PURE__ */ new Map();
|
|
31263
|
-
for (const row of candidates) {
|
|
31264
|
-
const form = byForm.get(row.flowSlug) ?? { "endings seen": 0, "endings counted": 0, events: 0, lastSeen: "" };
|
|
31265
|
-
form["endings seen"] += 1;
|
|
31266
|
-
if (row.isCounted) form["endings counted"] += 1;
|
|
31267
|
-
form.events += row.events;
|
|
31268
|
-
if (row.lastSeen && row.lastSeen.slice(0, 10) > form.lastSeen) form.lastSeen = row.lastSeen.slice(0, 10);
|
|
31269
|
-
byForm.set(row.flowSlug, form);
|
|
31270
|
-
}
|
|
31271
|
-
return byForm;
|
|
31272
|
-
}
|
|
31273
|
-
var NO_TRAFFIC = { "endings seen": 0, "endings counted": 0, events: 0, lastSeen: "" };
|
|
31274
|
-
var FORM_KEYS_HINT = "A Form's candidates are one row per Form: `baker analytics conversions --flow <slug>` lists that Form's event keys, and `--candidates --output json` lists every key.";
|
|
31275
|
-
function renderConversionsMarkdown(envelope) {
|
|
31276
|
-
const { definitions, flow, flows, candidates } = envelope.data;
|
|
31277
|
-
const data = {
|
|
31278
|
-
definitions: definitions.map(({ name, eventKeys, ...row }) => ({ name, eventKeys: eventKeysCell(eventKeys), ...row }))
|
|
31279
|
-
};
|
|
31280
|
-
if (flow) {
|
|
31281
|
-
data.flow = { slug: flow.slug, noConversionReason: flow.noConversionReason };
|
|
31282
|
-
data.flowEndings = flow.endings;
|
|
31283
|
-
}
|
|
31284
|
-
const traffic = candidates ? trafficByForm(candidates.filter((row) => row.flowSlug !== "")) : /* @__PURE__ */ new Map();
|
|
31285
|
-
if (flows) {
|
|
31286
|
-
data.flows = flows.map((row) => ({
|
|
31287
|
-
slug: row.slug,
|
|
31288
|
-
counted: row.counted.map((entry) => `${entry.name} @ ${entry.step}`).join("; "),
|
|
31289
|
-
noConversion: row.noConversion,
|
|
31290
|
-
...candidates ? traffic.get(row.slug) ?? NO_TRAFFIC : {}
|
|
31291
|
-
}));
|
|
31292
|
-
}
|
|
31293
|
-
const hints2 = [...envelope.hints ?? []];
|
|
31294
|
-
if (candidates) {
|
|
31295
|
-
const listed2 = new Set(flows?.map((row) => row.slug));
|
|
31296
|
-
const unlisted = [...traffic].filter(([slug]) => !listed2.has(slug));
|
|
31297
|
-
if (unlisted.length > 0) data.formCandidates = unlisted.map(([form, row]) => ({ form, ...row }));
|
|
31298
|
-
data.candidates = candidates.filter((row) => row.flowSlug === "").map(({ doors, flowSlug: _flowSlug, nodeType: _nodeType, ...row }) => ({
|
|
31299
|
-
...row,
|
|
31300
|
-
"doors (events/sessions)": doorsCell(doors)
|
|
31301
|
-
}));
|
|
31302
|
-
if (traffic.size > 0) hints2.push(FORM_KEYS_HINT);
|
|
31303
|
-
}
|
|
31304
|
-
return renderMarkdown3({ data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
31305
|
-
}
|
|
31306
|
-
|
|
31307
30630
|
// src/commands/analytics/errorEnvelope.ts
|
|
31308
30631
|
function analyticsErrorEnvelope(err) {
|
|
31309
30632
|
if (err instanceof ApiError) {
|
|
@@ -31795,6 +31118,223 @@ var ANALYTICS_PRESET_INFO = [
|
|
|
31795
31118
|
}
|
|
31796
31119
|
];
|
|
31797
31120
|
|
|
31121
|
+
// src/commands/analytics/render.ts
|
|
31122
|
+
var SPARKLINE_POINTS = 30;
|
|
31123
|
+
var DASHBOARD_ONLY_FIELDS = /* @__PURE__ */ new Set([
|
|
31124
|
+
// The Convex row id. It exists so a dashboard can link to the row; an agent
|
|
31125
|
+
// addresses a landing by `landingId`, which is the id in its `_definition.md`.
|
|
31126
|
+
"landingRef"
|
|
31127
|
+
]);
|
|
31128
|
+
function isAbsent(value) {
|
|
31129
|
+
if (value === "") return true;
|
|
31130
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
31131
|
+
if (typeof value === "object" && value !== null) return Object.keys(value).length === 0;
|
|
31132
|
+
return false;
|
|
31133
|
+
}
|
|
31134
|
+
function resample(series, points) {
|
|
31135
|
+
if (series.length <= points || points < 1) return [...series];
|
|
31136
|
+
const out = [];
|
|
31137
|
+
for (let i = 0; i < points; i += 1) {
|
|
31138
|
+
const from = Math.floor(i * series.length / points);
|
|
31139
|
+
const to = Math.floor((i + 1) * series.length / points);
|
|
31140
|
+
let sum = 0;
|
|
31141
|
+
for (let j = from; j < to; j += 1) sum += series[j] ?? 0;
|
|
31142
|
+
out.push(sum);
|
|
31143
|
+
}
|
|
31144
|
+
return out;
|
|
31145
|
+
}
|
|
31146
|
+
function pruneValue(value, full) {
|
|
31147
|
+
if (Array.isArray(value)) return value.map((entry) => pruneValue(entry, full));
|
|
31148
|
+
if (typeof value === "object" && value !== null) {
|
|
31149
|
+
return pruneRow(value, full);
|
|
31150
|
+
}
|
|
31151
|
+
return value;
|
|
31152
|
+
}
|
|
31153
|
+
function pruneRow(row, full) {
|
|
31154
|
+
const out = {};
|
|
31155
|
+
for (const [key, value] of Object.entries(row)) {
|
|
31156
|
+
if (DASHBOARD_ONLY_FIELDS.has(key)) continue;
|
|
31157
|
+
if (key === "sparkline" && Array.isArray(value)) {
|
|
31158
|
+
if (!full) continue;
|
|
31159
|
+
out[key] = resample(value, SPARKLINE_POINTS);
|
|
31160
|
+
continue;
|
|
31161
|
+
}
|
|
31162
|
+
if (isAbsent(value)) continue;
|
|
31163
|
+
out[key] = pruneValue(value, full);
|
|
31164
|
+
}
|
|
31165
|
+
return out;
|
|
31166
|
+
}
|
|
31167
|
+
function pruneForAgent(data, full) {
|
|
31168
|
+
return pruneRow(data, full);
|
|
31169
|
+
}
|
|
31170
|
+
function isTabular(rows) {
|
|
31171
|
+
return rows.every(
|
|
31172
|
+
(row) => typeof row === "object" && row !== null && !Array.isArray(row) && Object.values(row).every(
|
|
31173
|
+
(value) => value === null || typeof value !== "object" || Array.isArray(value) && value.every((e) => typeof e !== "object")
|
|
31174
|
+
)
|
|
31175
|
+
);
|
|
31176
|
+
}
|
|
31177
|
+
function cell2(value, key) {
|
|
31178
|
+
if (value === null || value === void 0) return "";
|
|
31179
|
+
if (Array.isArray(value)) return value.join(" ");
|
|
31180
|
+
if (typeof value === "number" && !Number.isInteger(value)) {
|
|
31181
|
+
if (key?.endsWith("Ms")) return String(Math.round(value));
|
|
31182
|
+
return value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
|
|
31183
|
+
}
|
|
31184
|
+
return String(value);
|
|
31185
|
+
}
|
|
31186
|
+
var IDENTITY_COLUMNS = [
|
|
31187
|
+
"landingId",
|
|
31188
|
+
"name",
|
|
31189
|
+
"slug",
|
|
31190
|
+
"path",
|
|
31191
|
+
"flowSlug",
|
|
31192
|
+
"stepId",
|
|
31193
|
+
"value",
|
|
31194
|
+
"key",
|
|
31195
|
+
"bucket",
|
|
31196
|
+
"tag",
|
|
31197
|
+
"eventName",
|
|
31198
|
+
"release",
|
|
31199
|
+
"place",
|
|
31200
|
+
"bot",
|
|
31201
|
+
"source",
|
|
31202
|
+
"medium",
|
|
31203
|
+
"campaign",
|
|
31204
|
+
"platform",
|
|
31205
|
+
"sessionId",
|
|
31206
|
+
"eventId"
|
|
31207
|
+
];
|
|
31208
|
+
function byIdentityFirst(a, b) {
|
|
31209
|
+
const ia = IDENTITY_COLUMNS.indexOf(a);
|
|
31210
|
+
const ib = IDENTITY_COLUMNS.indexOf(b);
|
|
31211
|
+
if (ia !== -1 || ib !== -1)
|
|
31212
|
+
return (ia === -1 ? Number.MAX_SAFE_INTEGER : ia) - (ib === -1 ? Number.MAX_SAFE_INTEGER : ib);
|
|
31213
|
+
return 0;
|
|
31214
|
+
}
|
|
31215
|
+
var BLOCK_ORDER = ["window", "totals", "previous", "pageInfo"];
|
|
31216
|
+
function byBlockOrder(a, b) {
|
|
31217
|
+
const rank = (key) => {
|
|
31218
|
+
const at = BLOCK_ORDER.indexOf(key);
|
|
31219
|
+
if (at !== -1) return at;
|
|
31220
|
+
return key === "preset" ? BLOCK_ORDER.length + 1 : BLOCK_ORDER.length;
|
|
31221
|
+
};
|
|
31222
|
+
return rank(a) - rank(b);
|
|
31223
|
+
}
|
|
31224
|
+
function columnsOf(rows) {
|
|
31225
|
+
const seen = [];
|
|
31226
|
+
for (const row of rows) {
|
|
31227
|
+
for (const key of Object.keys(row)) {
|
|
31228
|
+
if (!seen.includes(key)) seen.push(key);
|
|
31229
|
+
}
|
|
31230
|
+
}
|
|
31231
|
+
return seen.filter((key) => rows.some((row) => !isAbsent(row[key]) && row[key] !== null && row[key] !== void 0)).sort(byIdentityFirst);
|
|
31232
|
+
}
|
|
31233
|
+
function table2(rows) {
|
|
31234
|
+
const cols = columnsOf(rows);
|
|
31235
|
+
if (cols.length === 0) return "";
|
|
31236
|
+
const head = `| ${cols.join(" | ")} |`;
|
|
31237
|
+
const rule = `| ${cols.map(() => "---").join(" | ")} |`;
|
|
31238
|
+
const body = rows.map((row) => `| ${cols.map((col) => cell2(row[col], col)).join(" | ")} |`);
|
|
31239
|
+
return [head, rule, ...body].join("\n");
|
|
31240
|
+
}
|
|
31241
|
+
function isRowList(value) {
|
|
31242
|
+
return Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry));
|
|
31243
|
+
}
|
|
31244
|
+
function labelOf(row, index) {
|
|
31245
|
+
for (const key of IDENTITY_COLUMNS) {
|
|
31246
|
+
const value = row[key];
|
|
31247
|
+
if (typeof value === "string" && value !== "") return value;
|
|
31248
|
+
}
|
|
31249
|
+
return `#${index + 1}`;
|
|
31250
|
+
}
|
|
31251
|
+
function nestedBlock(name, rows) {
|
|
31252
|
+
const parents = rows.map(
|
|
31253
|
+
(row) => Object.fromEntries(Object.entries(row).filter(([, value]) => !isRowList(value) && !isPlainRow(value)))
|
|
31254
|
+
);
|
|
31255
|
+
const parts = [`### ${name}`, table2(parents)];
|
|
31256
|
+
rows.forEach((row, index) => {
|
|
31257
|
+
for (const [key, value] of Object.entries(row)) {
|
|
31258
|
+
if (isRowList(value)) parts.push(`#### ${name}[${labelOf(row, index)}].${key}`, table2(value));
|
|
31259
|
+
else if (isPlainRow(value)) parts.push(`#### ${name}[${labelOf(row, index)}].${key}`, table2([value]));
|
|
31260
|
+
}
|
|
31261
|
+
});
|
|
31262
|
+
return parts.filter((part) => part !== "").join("\n");
|
|
31263
|
+
}
|
|
31264
|
+
function isPlainRow(value) {
|
|
31265
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31266
|
+
}
|
|
31267
|
+
function block(name, value) {
|
|
31268
|
+
if (Array.isArray(value)) {
|
|
31269
|
+
if (value.length === 0) return "";
|
|
31270
|
+
if (isTabular(value)) return `### ${name}
|
|
31271
|
+
${table2(value)}`;
|
|
31272
|
+
if (isRowList(value)) return nestedBlock(name, value);
|
|
31273
|
+
return `### ${name}
|
|
31274
|
+
${JSON.stringify(value)}`;
|
|
31275
|
+
}
|
|
31276
|
+
if (typeof value === "object" && value !== null) {
|
|
31277
|
+
const entries = Object.entries(value);
|
|
31278
|
+
if (entries.length === 0) return "";
|
|
31279
|
+
if (entries.every(([, v]) => v === null || typeof v !== "object")) {
|
|
31280
|
+
return `### ${name}
|
|
31281
|
+
${entries.map(([k, v]) => `- ${k}: ${v === null ? "null" : cell2(v, k)}`).join("\n")}`;
|
|
31282
|
+
}
|
|
31283
|
+
return `### ${name}
|
|
31284
|
+
${JSON.stringify(value)}`;
|
|
31285
|
+
}
|
|
31286
|
+
return `### ${name}
|
|
31287
|
+
${cell2(value)}`;
|
|
31288
|
+
}
|
|
31289
|
+
function renderMarkdown3(envelope) {
|
|
31290
|
+
const parts = [];
|
|
31291
|
+
for (const warning of envelope.warnings ?? []) parts.push(`> **${warning.code}** \u2014 ${warning.message}`);
|
|
31292
|
+
for (const hint of envelope.hints ?? []) parts.push(`> ${hint}`);
|
|
31293
|
+
for (const [name, value] of Object.entries(envelope.data).sort(([a], [b]) => byBlockOrder(a, b))) {
|
|
31294
|
+
const rendered = block(name, value);
|
|
31295
|
+
if (rendered !== "") parts.push(rendered);
|
|
31296
|
+
}
|
|
31297
|
+
return `${parts.join("\n\n")}
|
|
31298
|
+
`;
|
|
31299
|
+
}
|
|
31300
|
+
function missingBreakdownHint(data, asked) {
|
|
31301
|
+
if (asked.eventName === void 0) return [];
|
|
31302
|
+
const breakdown = data.eventBreakdown;
|
|
31303
|
+
if (Array.isArray(breakdown) && breakdown.length > 0) return [];
|
|
31304
|
+
const known = Array.isArray(data.customEvents) ? data.customEvents.flatMap((row) => isPlainRow(row) && typeof row.eventName === "string" ? [row.eventName] : []) : [];
|
|
31305
|
+
return [
|
|
31306
|
+
`No rows came back for --event ${asked.eventName}${asked.property ? ` --property ${asked.property}` : ""}. That event or property does not exist on these pages${known.length > 0 ? `; the ones that do are: ${known.slice(0, 12).join(", ")}${known.length > 12 ? ", \u2026" : ""}` : ""}.`
|
|
31307
|
+
];
|
|
31308
|
+
}
|
|
31309
|
+
var ANALYTICS_OUTPUT_FORMATS = ["json", "md"];
|
|
31310
|
+
function isAnalyticsOutputFormat(value) {
|
|
31311
|
+
return ANALYTICS_OUTPUT_FORMATS.includes(value);
|
|
31312
|
+
}
|
|
31313
|
+
function writeAnalyticsReport(envelope, format) {
|
|
31314
|
+
if (format === "md") {
|
|
31315
|
+
process.stdout.write(renderMarkdown3(envelope));
|
|
31316
|
+
return;
|
|
31317
|
+
}
|
|
31318
|
+
process.stdout.write(`${JSON.stringify(envelope)}
|
|
31319
|
+
`);
|
|
31320
|
+
}
|
|
31321
|
+
var ROWS_BEFORE_FORMAT_HINT = 25;
|
|
31322
|
+
function rowCount(data) {
|
|
31323
|
+
let total = 0;
|
|
31324
|
+
for (const value of Object.values(data)) {
|
|
31325
|
+
if (Array.isArray(value)) total += value.length;
|
|
31326
|
+
}
|
|
31327
|
+
return total;
|
|
31328
|
+
}
|
|
31329
|
+
function formatHint(data, format) {
|
|
31330
|
+
if (format === "md") return [];
|
|
31331
|
+
const rows = rowCount(data);
|
|
31332
|
+
if (rows < ROWS_BEFORE_FORMAT_HINT) return [];
|
|
31333
|
+
return [
|
|
31334
|
+
`This report is ${rows} rows. If you are going to read the numbers rather than pick one field out of them, --output md returns the same answer as tables, typically a third to a half smaller.`
|
|
31335
|
+
];
|
|
31336
|
+
}
|
|
31337
|
+
|
|
31798
31338
|
// src/commands/analytics/sends.ts
|
|
31799
31339
|
import { defineCommand as defineCommand97 } from "citty";
|
|
31800
31340
|
var SET_FLAGS = ["--source-event", "--platform", "--tag", "--event"];
|
|
@@ -32969,7 +32509,17 @@ async function runPreset(args5, options) {
|
|
|
32969
32509
|
const response = await apiPost("/api/analytics/query", requestBody(args5, options));
|
|
32970
32510
|
const requestedPlatform = args5.platform === void 0 ? "" : String(args5.platform);
|
|
32971
32511
|
const adPlatformScope = isAdPlatform(requestedPlatform) ? requestedPlatform : void 0;
|
|
32972
|
-
const format =
|
|
32512
|
+
const format = args5.output === void 0 ? "json" : String(args5.output);
|
|
32513
|
+
if (!isAnalyticsOutputFormat(format)) {
|
|
32514
|
+
writeJsonEnvelope({
|
|
32515
|
+
ok: false,
|
|
32516
|
+
error: {
|
|
32517
|
+
code: "VALIDATION_ERROR",
|
|
32518
|
+
message: `Unknown --output "${format}". Use one of: ${ANALYTICS_OUTPUT_FORMATS.join(", ")}.`
|
|
32519
|
+
}
|
|
32520
|
+
});
|
|
32521
|
+
process.exit(1);
|
|
32522
|
+
}
|
|
32973
32523
|
const data = pruneForAgent(response.data, args5.full === true);
|
|
32974
32524
|
const feed = "stream" in data ? shapeFeed(data.stream, args5.everything === true) : void 0;
|
|
32975
32525
|
if (feed !== void 0) data.stream = feed.rows;
|
|
@@ -32999,20 +32549,6 @@ async function runPreset(args5, options) {
|
|
|
32999
32549
|
handleError3(err);
|
|
33000
32550
|
}
|
|
33001
32551
|
}
|
|
33002
|
-
function outputFormatOrExit(raw) {
|
|
33003
|
-
const format = raw === void 0 ? "json" : String(raw);
|
|
33004
|
-
if (!isAnalyticsOutputFormat(format)) {
|
|
33005
|
-
writeJsonEnvelope({
|
|
33006
|
-
ok: false,
|
|
33007
|
-
error: {
|
|
33008
|
-
code: "VALIDATION_ERROR",
|
|
33009
|
-
message: `Unknown --output "${format}". Use one of: ${ANALYTICS_OUTPUT_FORMATS.join(", ")}.`
|
|
33010
|
-
}
|
|
33011
|
-
});
|
|
33012
|
-
process.exit(1);
|
|
33013
|
-
}
|
|
33014
|
-
return format;
|
|
33015
|
-
}
|
|
33016
32552
|
function presetCommand(options) {
|
|
33017
32553
|
registerSchema({
|
|
33018
32554
|
command: `analytics.${options.name}`,
|
|
@@ -33514,8 +33050,7 @@ var conversionsCommand3 = (() => {
|
|
|
33514
33050
|
type: "string",
|
|
33515
33051
|
description: "Lookback for the counts and for --candidates. Default 30",
|
|
33516
33052
|
required: false
|
|
33517
|
-
}
|
|
33518
|
-
output: SHARED_ARGS.output
|
|
33053
|
+
}
|
|
33519
33054
|
};
|
|
33520
33055
|
registerSchema({
|
|
33521
33056
|
command: "analytics.conversions",
|
|
@@ -33530,23 +33065,22 @@ var conversionsCommand3 = (() => {
|
|
|
33530
33065
|
args: args5,
|
|
33531
33066
|
run: async ({ args: raw }) => {
|
|
33532
33067
|
try {
|
|
33533
|
-
const format = outputFormatOrExit(raw.output);
|
|
33534
33068
|
const args6 = parseConversionsArgs(raw, process.argv);
|
|
33535
33069
|
for (const eventKey of args6.eventKeys) refuseUnmatchableKey(eventKey);
|
|
33536
33070
|
const before = await apiPost("/api/analytics/conversions", {});
|
|
33537
|
-
const
|
|
33538
|
-
const stored =
|
|
33071
|
+
const write = conversionsWrite(args6, before.data.definitions);
|
|
33072
|
+
const stored = write ? (await apiPost("/api/analytics/conversions", write)).data.definitions : before.data.definitions;
|
|
33539
33073
|
const report = await apiPost("/api/analytics/query", {
|
|
33540
33074
|
preset: "conversions",
|
|
33541
33075
|
days: args6.days
|
|
33542
33076
|
});
|
|
33543
|
-
|
|
33544
|
-
|
|
33545
|
-
|
|
33546
|
-
|
|
33077
|
+
writeJsonEnvelope(
|
|
33078
|
+
conversionsEnvelope(
|
|
33079
|
+
args6,
|
|
33080
|
+
mergeStoredWithCounts(stored, report.data.conversions ?? []),
|
|
33081
|
+
report.data.eventCatalog ?? []
|
|
33082
|
+
)
|
|
33547
33083
|
);
|
|
33548
|
-
if (format === "md") process.stdout.write(renderConversionsMarkdown(envelope));
|
|
33549
|
-
else writeJsonEnvelope(envelope);
|
|
33550
33084
|
} catch (err) {
|
|
33551
33085
|
if (err instanceof ConversionArgsError) {
|
|
33552
33086
|
handleError3(new ApiError("VALIDATION_ERROR", err.message));
|
|
@@ -33911,11 +33445,7 @@ function rosterRow(avatar) {
|
|
|
33911
33445
|
};
|
|
33912
33446
|
}
|
|
33913
33447
|
function chatIdFromEnv() {
|
|
33914
|
-
|
|
33915
|
-
return getEnv().BAKER_CHAT_ID || void 0;
|
|
33916
|
-
} catch {
|
|
33917
|
-
return void 0;
|
|
33918
|
-
}
|
|
33448
|
+
return optionalChatId();
|
|
33919
33449
|
}
|
|
33920
33450
|
function rosterHints(roster, statusFilter) {
|
|
33921
33451
|
if (roster.length === 0) {
|
|
@@ -39444,7 +38974,7 @@ function sceneSpokenText(scene) {
|
|
|
39444
38974
|
return (scene.dialogue ?? []).map((d) => d.line?.trim()).filter((l) => Boolean(l)).join(" ") || null;
|
|
39445
38975
|
}
|
|
39446
38976
|
function buildMotionBoard(blueprint) {
|
|
39447
|
-
const
|
|
38977
|
+
const round4 = (n) => Math.round(n * 100) / 100;
|
|
39448
38978
|
let cursor = 0;
|
|
39449
38979
|
return blueprint.scenes.map((scene, i) => {
|
|
39450
38980
|
const start_s = scene.start_s ?? cursor;
|
|
@@ -39456,15 +38986,15 @@ function buildMotionBoard(blueprint) {
|
|
|
39456
38986
|
const graphics = [
|
|
39457
38987
|
...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
|
|
39458
38988
|
kind: "text",
|
|
39459
|
-
at_s:
|
|
39460
|
-
dur_s:
|
|
38989
|
+
at_s: round4(ov.appears_at_s ?? start_s),
|
|
38990
|
+
dur_s: round4(ov.duration_s ?? 2.5),
|
|
39461
38991
|
position: ov.position ?? "bottom_center",
|
|
39462
38992
|
text: ov.text?.trim()
|
|
39463
38993
|
})),
|
|
39464
38994
|
...(floats.success ? floats.data : []).map((fe) => ({
|
|
39465
38995
|
kind: "graphic",
|
|
39466
|
-
at_s:
|
|
39467
|
-
dur_s:
|
|
38996
|
+
at_s: round4(fe.appears_at_s ?? start_s),
|
|
38997
|
+
dur_s: round4(fe.duration_s ?? 2.5),
|
|
39468
38998
|
position: fe.position ?? "bottom_center",
|
|
39469
38999
|
label: fe.brand_name || fe.what_it_represents || fe.description || fe.kind || "element"
|
|
39470
39000
|
}))
|
|
@@ -39472,7 +39002,7 @@ function buildMotionBoard(blueprint) {
|
|
|
39472
39002
|
return {
|
|
39473
39003
|
scene: i,
|
|
39474
39004
|
role: resolveSceneRole(scene, i, blueprint.scenes.length),
|
|
39475
|
-
window_s: [
|
|
39005
|
+
window_s: [round4(start_s), round4(end_s)],
|
|
39476
39006
|
// A continuation b-roll scene shares the previous scene's end frame as its start
|
|
39477
39007
|
// (no own `s<i>_start` node), so point the storyboard at that shared keyframe.
|
|
39478
39008
|
storyboard_frames: [scene.continues_previous && i > 0 ? `s${i - 1}_end` : `s${i}_start`],
|
|
@@ -41235,7 +40765,7 @@ ${describeRewrites(healed.rewrites)}
|
|
|
41235
40765
|
// "edited since last render". Computed from the on-disk canvas.json +
|
|
41236
40766
|
// prompt.json — the same helper the edit-sync uses, so the two are comparable.
|
|
41237
40767
|
sourceSha: await computeSourceSha(filePath),
|
|
41238
|
-
chatId:
|
|
40768
|
+
chatId: optionalChatId(),
|
|
41239
40769
|
canvasSnapshotUrl
|
|
41240
40770
|
};
|
|
41241
40771
|
if (client) {
|
|
@@ -45226,11 +44756,7 @@ function detectCreativeContentType(filePath) {
|
|
|
45226
44756
|
});
|
|
45227
44757
|
}
|
|
45228
44758
|
function chatIdFromEnv2() {
|
|
45229
|
-
|
|
45230
|
-
return getEnv().BAKER_CHAT_ID || void 0;
|
|
45231
|
-
} catch {
|
|
45232
|
-
return void 0;
|
|
45233
|
-
}
|
|
44759
|
+
return optionalChatId();
|
|
45234
44760
|
}
|
|
45235
44761
|
function parseOptionalUrl(value) {
|
|
45236
44762
|
if (value === void 0 || value.trim() === "") {
|
|
@@ -53147,7 +52673,7 @@ var extractCommand = defineCommand149({
|
|
|
53147
52673
|
import { defineCommand as defineCommand150 } from "citty";
|
|
53148
52674
|
|
|
53149
52675
|
// src/commands/images/providerHits.ts
|
|
53150
|
-
function
|
|
52676
|
+
function asRecord2(value) {
|
|
53151
52677
|
return value && typeof value === "object" ? value : {};
|
|
53152
52678
|
}
|
|
53153
52679
|
function str(value) {
|
|
@@ -53172,7 +52698,7 @@ function providerHitNormalizer(record, full) {
|
|
|
53172
52698
|
if (!full) {
|
|
53173
52699
|
return compact3;
|
|
53174
52700
|
}
|
|
53175
|
-
const group =
|
|
52701
|
+
const group = asRecord2(record.group);
|
|
53176
52702
|
return {
|
|
53177
52703
|
...compact3,
|
|
53178
52704
|
externalUrl: str(record.externalUrl),
|
|
@@ -57077,7 +56603,7 @@ function dedupe(findings) {
|
|
|
57077
56603
|
|
|
57078
56604
|
// src/engine/landing/lib/critique.ts
|
|
57079
56605
|
var FAMILIES = ["typography", "color", "borders_depth", "motion", "spacing", "copy", "integrity"];
|
|
57080
|
-
function
|
|
56606
|
+
function round2(n) {
|
|
57081
56607
|
return Math.round(n * 100) / 100;
|
|
57082
56608
|
}
|
|
57083
56609
|
function clamp012(n) {
|
|
@@ -57114,11 +56640,11 @@ function critiqueLanding(input) {
|
|
|
57114
56640
|
const dimensions = FAMILIES.map((family) => {
|
|
57115
56641
|
const fam = findings.filter((f) => f.family === family);
|
|
57116
56642
|
const penalty = fam.reduce((s, f) => s + SEVERITY_WEIGHT[f.severity], 0);
|
|
57117
|
-
const score =
|
|
56643
|
+
const score = round2(clamp012(1 - penalty));
|
|
57118
56644
|
const note = fam.length === 0 ? "clean" : `${fam.length} finding(s): ${describeCounts(fam)}`;
|
|
57119
56645
|
return { dimension: family, score, note };
|
|
57120
56646
|
});
|
|
57121
|
-
const overall =
|
|
56647
|
+
const overall = round2(dimensions.reduce((s, d) => s + d.score, 0) / dimensions.length);
|
|
57122
56648
|
const counts = {
|
|
57123
56649
|
block: findings.filter((f) => f.severity === "block").length,
|
|
57124
56650
|
warn: findings.filter((f) => f.severity === "warn").length,
|
|
@@ -61277,7 +60803,7 @@ function writeJsonl(data) {
|
|
|
61277
60803
|
`);
|
|
61278
60804
|
}
|
|
61279
60805
|
}
|
|
61280
|
-
function
|
|
60806
|
+
function writeMd(data, fields) {
|
|
61281
60807
|
if (data.length === 0) return;
|
|
61282
60808
|
const cols = fields ?? Object.keys(data[0] ?? {});
|
|
61283
60809
|
process.stdout.write(`| ${cols.join(" | ")} |
|
|
@@ -61299,7 +60825,7 @@ function writeResearchOutput(data, format, fields) {
|
|
|
61299
60825
|
writeJsonl(data);
|
|
61300
60826
|
break;
|
|
61301
60827
|
case "md":
|
|
61302
|
-
|
|
60828
|
+
writeMd(data, fields);
|
|
61303
60829
|
break;
|
|
61304
60830
|
default:
|
|
61305
60831
|
writeResearchJson({ ok: true, data });
|
|
@@ -67754,6 +67280,7 @@ function commandFor(root, argv) {
|
|
|
67754
67280
|
const { command, resolved } = resolveCommand2(root, argv);
|
|
67755
67281
|
return resolved ? command : null;
|
|
67756
67282
|
}
|
|
67283
|
+
var OUTPUT_EXPLANATION = "This command has no --output option: `--output json` is accepted by every command that prints the JSON envelope, and md or files only where `baker schema` lists `output`. Drop the option and read the default output. ";
|
|
67757
67284
|
function unknownFlagEnvelope(unknown, commandPath, suggestion, hasSchema) {
|
|
67758
67285
|
const list = unknown.join(", ");
|
|
67759
67286
|
return {
|
|
@@ -67763,7 +67290,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion, hasSchema) {
|
|
|
67763
67290
|
message: `${list} ${unknown.length > 1 ? "are not options" : "is not an option"} of \`baker ${commandPath}\`.`,
|
|
67764
67291
|
fix: {
|
|
67765
67292
|
action: hasSchema ? "check_schema" : "check_help",
|
|
67766
|
-
explanation: (suggestion ? `Did you mean ${suggestion}? ` : "") + `Run \`${hasSchema ? `baker schema ${commandPath}` : `baker ${commandPath} --help`}\` to see every option this command takes. Do not re-run the same call: until this version an unrecognised option was accepted and ignored, so a command that looked like it had filtered or narrowed the result was in fact answering the unfiltered question.`
|
|
67293
|
+
explanation: (unknown.some((flag) => flag === "--output" || flag.startsWith("--output=")) ? OUTPUT_EXPLANATION : "") + (suggestion ? `Did you mean ${suggestion}? ` : "") + `Run \`${hasSchema ? `baker schema ${commandPath}` : `baker ${commandPath} --help`}\` to see every option this command takes. Do not re-run the same call: until this version an unrecognised option was accepted and ignored, so a command that looked like it had filtered or narrowed the result was in fact answering the unfiltered question.`
|
|
67767
67294
|
},
|
|
67768
67295
|
retryable: false
|
|
67769
67296
|
}
|
|
@@ -67802,6 +67329,58 @@ function refuseUnknownFlags(root, argv) {
|
|
|
67802
67329
|
process.exit(1);
|
|
67803
67330
|
}
|
|
67804
67331
|
|
|
67332
|
+
// src/output-flag.ts
|
|
67333
|
+
var FLAG = "--output";
|
|
67334
|
+
var ENVELOPE = "json";
|
|
67335
|
+
var PRINTS_NO_ENVELOPE = /* @__PURE__ */ new Set([
|
|
67336
|
+
"analytics sending-events",
|
|
67337
|
+
"canvas run",
|
|
67338
|
+
"canvas rerun",
|
|
67339
|
+
"canvas sync-definition"
|
|
67340
|
+
]);
|
|
67341
|
+
function declaredArg(command, name) {
|
|
67342
|
+
const args5 = command.args;
|
|
67343
|
+
if (!args5 || typeof args5 !== "object" || !(name in args5)) {
|
|
67344
|
+
return null;
|
|
67345
|
+
}
|
|
67346
|
+
const def = args5[name];
|
|
67347
|
+
return def && typeof def === "object" ? def : {};
|
|
67348
|
+
}
|
|
67349
|
+
function envelopeRequests(argv) {
|
|
67350
|
+
const end = argv.indexOf("--");
|
|
67351
|
+
const limit = end === -1 ? argv.length : end;
|
|
67352
|
+
const found = [];
|
|
67353
|
+
for (let index = 0; index < limit; index++) {
|
|
67354
|
+
const token = argv[index];
|
|
67355
|
+
if (token === `${FLAG}=${ENVELOPE}`) {
|
|
67356
|
+
found.push({ index, length: 1 });
|
|
67357
|
+
} else if (token === FLAG && argv[index + 1] === ENVELOPE && index + 1 < limit) {
|
|
67358
|
+
found.push({ index, length: 2 });
|
|
67359
|
+
index++;
|
|
67360
|
+
}
|
|
67361
|
+
}
|
|
67362
|
+
return found;
|
|
67363
|
+
}
|
|
67364
|
+
function outputFlagForCommand(root, argv) {
|
|
67365
|
+
const requests = envelopeRequests(argv);
|
|
67366
|
+
if (requests.length === 0) {
|
|
67367
|
+
return argv;
|
|
67368
|
+
}
|
|
67369
|
+
const command = commandFor(root, argv);
|
|
67370
|
+
if (!command || declaredArg(command, "output") || PRINTS_NO_ENVELOPE.has(commandPathOf(root, argv))) {
|
|
67371
|
+
return argv;
|
|
67372
|
+
}
|
|
67373
|
+
const jsonSwitch = declaredArg(command, "json")?.type === "boolean";
|
|
67374
|
+
const dropped = new Set(requests.flatMap(({ index, length }) => length === 2 ? [index, index + 1] : [index]));
|
|
67375
|
+
const first = requests[0]?.index;
|
|
67376
|
+
return argv.flatMap((token, index) => {
|
|
67377
|
+
if (!dropped.has(index)) {
|
|
67378
|
+
return [token];
|
|
67379
|
+
}
|
|
67380
|
+
return jsonSwitch && index === first ? ["--json"] : [];
|
|
67381
|
+
});
|
|
67382
|
+
}
|
|
67383
|
+
|
|
67805
67384
|
// src/version.ts
|
|
67806
67385
|
import { readFileSync as readFileSync21 } from "fs";
|
|
67807
67386
|
function packageJsonUrl() {
|
|
@@ -67828,7 +67407,7 @@ var main = defineCommand245({
|
|
|
67828
67407
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
67829
67408
|
Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
|
|
67830
67409
|
Output: All commands return JSON envelopes: { ok: true, data: ... } or { ok: false, error: { code, message } }.
|
|
67831
|
-
Formats:
|
|
67410
|
+
Formats: --output json works on every command that prints the envelope. --output md|files only where 'baker schema <command>' lists output. (The research commands additionally accept csv and jsonl.)
|
|
67832
67411
|
Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
67833
67412
|
},
|
|
67834
67413
|
subCommands: {
|
|
@@ -67866,6 +67445,7 @@ process.argv = [...process.argv.slice(0, 2), ...normalizeCacheFlag(process.argv.
|
|
|
67866
67445
|
installStreamTaps();
|
|
67867
67446
|
logInvocation(process.argv.slice(2));
|
|
67868
67447
|
installExitRecord();
|
|
67448
|
+
process.argv = [...process.argv.slice(0, 2), ...outputFlagForCommand(main, process.argv.slice(2))];
|
|
67869
67449
|
refuseUnknownFlags(main, process.argv.slice(2));
|
|
67870
67450
|
process.argv = [...process.argv.slice(0, 2), ...cacheFlagForParser(process.argv.slice(2))];
|
|
67871
67451
|
runMain(main);
|