@koda-sl/baker-cli 0.383.0-dev.2caa8a15e → 0.383.0-dev.9779e8b49
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 +43 -9
- package/dist/{chunk-CHJOTJTZ.js → chunk-ZW6DHSDG.js} +8 -2
- package/dist/chunk-ZW6DHSDG.js.map +1 -0
- package/dist/cli.js +925 -553
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CHJOTJTZ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
validateCanvasDeep,
|
|
71
71
|
withoutCastName,
|
|
72
72
|
ytDlpBlockSignal
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-ZW6DHSDG.js";
|
|
74
74
|
import {
|
|
75
75
|
NAME_CONTAINS_ARG,
|
|
76
76
|
csvOrJson,
|
|
@@ -143,7 +143,7 @@ import {
|
|
|
143
143
|
} from "./chunk-HJEMOSPH.js";
|
|
144
144
|
|
|
145
145
|
// src/cli.ts
|
|
146
|
-
import { defineCommand as
|
|
146
|
+
import { defineCommand as defineCommand255, runMain } from "citty";
|
|
147
147
|
|
|
148
148
|
// src/cache-flag.ts
|
|
149
149
|
var NO_CACHE_ARG = {
|
|
@@ -299,7 +299,6 @@ var chatActionDraftOpViewSchema = z.object({
|
|
|
299
299
|
targetActionId: z.string().optional(),
|
|
300
300
|
tempId: z.string().optional(),
|
|
301
301
|
tags: z.array(z.string()).optional(),
|
|
302
|
-
priority: actionPrioritySchema.nullable().optional(),
|
|
303
302
|
reason: z.string().optional(),
|
|
304
303
|
note: z.string().optional(),
|
|
305
304
|
name: z.string().optional(),
|
|
@@ -976,9 +975,6 @@ var OBJECTIVE_CAMPAIGN_TYPES = {
|
|
|
976
975
|
ENGAGEMENT: ["SPONSORED_UPDATES", "DYNAMIC"]
|
|
977
976
|
};
|
|
978
977
|
var STAGEABLE_CREATE_STATUSES = ["DRAFT", "ACTIVE", "PAUSED"];
|
|
979
|
-
var CAMPAIGN_GROUP_CREATE_STATUSES = ["DRAFT", "ACTIVE"];
|
|
980
|
-
var CAMPAIGN_GROUP_STATUSES = ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT"];
|
|
981
|
-
var POLITICAL_INTENTS = ["NOT_DECLARED", "NOT_POLITICAL", "POLITICAL"];
|
|
982
978
|
var CREATIVE_INTENDED_STATUSES = ["ACTIVE", "PAUSED", "DRAFT"];
|
|
983
979
|
var CTA_TYPES = [
|
|
984
980
|
"APPLY",
|
|
@@ -1109,26 +1105,17 @@ var entityStatusSchema = z3.enum(["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "D
|
|
|
1109
1105
|
function currencyMinimums(currencyCode) {
|
|
1110
1106
|
return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;
|
|
1111
1107
|
}
|
|
1112
|
-
var
|
|
1108
|
+
var campaignGroupCreateSchema = z3.object({
|
|
1113
1109
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax),
|
|
1114
1110
|
runSchedule: runScheduleSchema,
|
|
1115
1111
|
totalBudget: moneySchema.optional(),
|
|
1116
|
-
status:
|
|
1117
|
-
});
|
|
1118
|
-
var campaignGroupCreateSchema = campaignGroupFieldsSchema.superRefine((p, ctx) => {
|
|
1119
|
-
if (p.totalBudget && !p.runSchedule.end) {
|
|
1120
|
-
ctx.addIssue({
|
|
1121
|
-
code: "custom",
|
|
1122
|
-
path: ["runSchedule", "end"],
|
|
1123
|
-
message: "a group with totalBudget needs runSchedule.end"
|
|
1124
|
-
});
|
|
1125
|
-
}
|
|
1112
|
+
status: stageableStatusSchema.default("DRAFT")
|
|
1126
1113
|
});
|
|
1127
1114
|
var campaignGroupUpdateSchema = z3.object({
|
|
1128
1115
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax).optional(),
|
|
1129
1116
|
runSchedule: runScheduleSchema.optional(),
|
|
1130
1117
|
totalBudget: moneySchema.optional(),
|
|
1131
|
-
status:
|
|
1118
|
+
status: entityStatusSchema.optional()
|
|
1132
1119
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
1133
1120
|
var campaignFields = {
|
|
1134
1121
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaign.nameMax),
|
|
@@ -1147,7 +1134,6 @@ var campaignFields = {
|
|
|
1147
1134
|
connectedTelevisionOnly: z3.boolean().default(false),
|
|
1148
1135
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1149
1136
|
associatedEntity: z3.string().regex(ORGANIZATION_URN_REGEX).optional(),
|
|
1150
|
-
politicalIntent: z3.enum(POLITICAL_INTENTS).default("NOT_DECLARED"),
|
|
1151
1137
|
status: stageableStatusSchema.default("DRAFT")
|
|
1152
1138
|
};
|
|
1153
1139
|
function validateCampaignBudgets(p, ctx, { requireBudget }) {
|
|
@@ -1205,7 +1191,6 @@ var campaignUpdateSchema = z3.object({
|
|
|
1205
1191
|
offsiteDeliveryEnabled: z3.boolean().optional(),
|
|
1206
1192
|
connectedTelevisionOnly: z3.boolean().optional(),
|
|
1207
1193
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1208
|
-
politicalIntent: z3.enum(POLITICAL_INTENTS).optional(),
|
|
1209
1194
|
status: entityStatusSchema.optional(),
|
|
1210
1195
|
// Create-only on LinkedIn — a live campaign can't change these in place.
|
|
1211
1196
|
// Accepted here only so `draft amend` can carry them into a staged CREATE
|
|
@@ -1831,17 +1816,6 @@ var linkedinDraftOpInputSchema = z3.discriminatedUnion("kind", [
|
|
|
1831
1816
|
updateOp("leadForm.update", leadFormUpdateSchema)
|
|
1832
1817
|
]);
|
|
1833
1818
|
|
|
1834
|
-
// ../api/src/ads-linkedin/search-statuses.ts
|
|
1835
|
-
var LINKEDIN_SEARCH_STATUSES = {
|
|
1836
|
-
campaignGroups: ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"],
|
|
1837
|
-
campaigns: ["ACTIVE", "PAUSED", "ARCHIVED", "COMPLETED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"],
|
|
1838
|
-
creatives: ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"]
|
|
1839
|
-
};
|
|
1840
|
-
function unsupportedLinkedinSearchStatuses(level, statuses) {
|
|
1841
|
-
const accepted = LINKEDIN_SEARCH_STATUSES[level];
|
|
1842
|
-
return statuses.filter((status) => !accepted.includes(status));
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
1819
|
// ../api/src/ads-linkedin/wire.ts
|
|
1846
1820
|
import { z as z7 } from "zod";
|
|
1847
1821
|
|
|
@@ -4560,6 +4534,9 @@ var chatChangeTypeSchema = z13.enum([
|
|
|
4560
4534
|
"image",
|
|
4561
4535
|
"video",
|
|
4562
4536
|
"followed-advertiser",
|
|
4537
|
+
// A connected social account feeding the image and video libraries, keyed
|
|
4538
|
+
// on `platform:handle`. Immediate — see convex/mediaSources/mutations.ts.
|
|
4539
|
+
"media-source",
|
|
4563
4540
|
// A landing page saved to the reference library, keyed on the page.
|
|
4564
4541
|
"landing-reference",
|
|
4565
4542
|
// One Studio batch — the takes of one brief, as a set. See convex/lib/validators.ts.
|
|
@@ -6424,6 +6401,10 @@ var imageSourceSchema = z20.enum([
|
|
|
6424
6401
|
"google_testimonial",
|
|
6425
6402
|
"trustpilot_testimonial",
|
|
6426
6403
|
"instagram",
|
|
6404
|
+
"tiktok",
|
|
6405
|
+
"linkedin",
|
|
6406
|
+
"facebook",
|
|
6407
|
+
"google_drive",
|
|
6427
6408
|
"pexels",
|
|
6428
6409
|
"pixabay",
|
|
6429
6410
|
// Retired stock provider — kept so existing library rows stay filterable.
|
|
@@ -8234,7 +8215,9 @@ var videoSourceSchema = z30.enum([
|
|
|
8234
8215
|
"bluesky",
|
|
8235
8216
|
"dailymotion",
|
|
8236
8217
|
"facebook",
|
|
8218
|
+
"google_drive",
|
|
8237
8219
|
"instagram",
|
|
8220
|
+
"linkedin",
|
|
8238
8221
|
"loom",
|
|
8239
8222
|
"newgrounds",
|
|
8240
8223
|
"ok",
|
|
@@ -12128,24 +12111,6 @@ function adCopyHints(payload) {
|
|
|
12128
12111
|
return tells.slice(0, MAX_HINTS).map(hintFor);
|
|
12129
12112
|
}
|
|
12130
12113
|
|
|
12131
|
-
// src/commands/ads/hints.ts
|
|
12132
|
-
function backendHints(envelope) {
|
|
12133
|
-
const hints2 = envelope.hints;
|
|
12134
|
-
return Array.isArray(hints2) ? hints2.filter((hint) => typeof hint === "string") : [];
|
|
12135
|
-
}
|
|
12136
|
-
function withHints(envelope, extra) {
|
|
12137
|
-
const hints2 = [...backendHints(envelope), ...extra];
|
|
12138
|
-
return hints2.length > 0 ? { ...envelope, hints: hints2 } : envelope;
|
|
12139
|
-
}
|
|
12140
|
-
function hintLines(envelope) {
|
|
12141
|
-
return backendHints(envelope).map((hint) => `
|
|
12142
|
-
> ${hint}`).join("");
|
|
12143
|
-
}
|
|
12144
|
-
function splitHints(response) {
|
|
12145
|
-
const { hints: hints2, ...data } = response;
|
|
12146
|
-
return { data, hints: hints2 ?? [] };
|
|
12147
|
-
}
|
|
12148
|
-
|
|
12149
12114
|
// src/commands/ads/google/copy-list-usage.ts
|
|
12150
12115
|
var AD_COPY_LIST_USAGE = `repeat the flag once per item, or pass one comma-separated list and wrap an item that contains a comma in double quotes: '"Fast, free quotes",Book today'. A flag given once is read as a list, so a lone item with a comma needs its double quotes too: '"Fast, free quotes"'`;
|
|
12151
12116
|
var COPY_LIST_FLAG = {
|
|
@@ -12153,9 +12118,9 @@ var COPY_LIST_FLAG = {
|
|
|
12153
12118
|
descriptions: "--descriptions",
|
|
12154
12119
|
longHeadlines: "--long-headlines"
|
|
12155
12120
|
};
|
|
12156
|
-
function valueAt(root,
|
|
12121
|
+
function valueAt(root, path49) {
|
|
12157
12122
|
let node = root;
|
|
12158
|
-
for (const key of
|
|
12123
|
+
for (const key of path49) {
|
|
12159
12124
|
if (node === null || typeof node !== "object") return void 0;
|
|
12160
12125
|
node = node[key];
|
|
12161
12126
|
}
|
|
@@ -12388,11 +12353,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
12388
12353
|
function rawTextEntries(value, rawArgs) {
|
|
12389
12354
|
return repeatedValues(rawArgs, "text", value).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
12390
12355
|
}
|
|
12391
|
-
function rawFileEntries(
|
|
12392
|
-
if (typeof
|
|
12356
|
+
function rawFileEntries(path49) {
|
|
12357
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12393
12358
|
return [];
|
|
12394
12359
|
}
|
|
12395
|
-
return readFileSync2(
|
|
12360
|
+
return readFileSync2(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12396
12361
|
}
|
|
12397
12362
|
function keywordEntries(args5, rawArgs) {
|
|
12398
12363
|
const defaultMatch = typeof args5["match-type"] === "string" ? args5["match-type"].toUpperCase() : void 0;
|
|
@@ -12415,14 +12380,14 @@ function keywordEntries(args5, rawArgs) {
|
|
|
12415
12380
|
}
|
|
12416
12381
|
return entries;
|
|
12417
12382
|
}
|
|
12418
|
-
function loadJsonFileArg(
|
|
12419
|
-
if (typeof
|
|
12383
|
+
function loadJsonFileArg(path49) {
|
|
12384
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12420
12385
|
return {};
|
|
12421
12386
|
}
|
|
12422
|
-
const inline =
|
|
12423
|
-
const source = inline ? "inline JSON" :
|
|
12387
|
+
const inline = path49.trimStart().startsWith("{");
|
|
12388
|
+
const source = inline ? "inline JSON" : path49;
|
|
12424
12389
|
try {
|
|
12425
|
-
const parsed = JSON.parse(inline ?
|
|
12390
|
+
const parsed = JSON.parse(inline ? path49 : readFileSync2(path49, "utf8"));
|
|
12426
12391
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12427
12392
|
failWriteValidation(`${source} must contain a JSON object`);
|
|
12428
12393
|
}
|
|
@@ -12510,7 +12475,7 @@ async function stageGoogleOp(raw, hints2) {
|
|
|
12510
12475
|
const chatId = requireChatId();
|
|
12511
12476
|
const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
|
|
12512
12477
|
const allHints = [...noopHints(response.data), ...hints2 ?? [], ...adCopyHints(preflight.data)];
|
|
12513
|
-
writeJsonEnvelope(
|
|
12478
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
12514
12479
|
} catch (err) {
|
|
12515
12480
|
handleGoogleError(err);
|
|
12516
12481
|
}
|
|
@@ -12548,7 +12513,7 @@ async function stageGoogleOps(rawOps, hints2) {
|
|
|
12548
12513
|
const chatId = requireChatId();
|
|
12549
12514
|
const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
|
|
12550
12515
|
const allHints = [...skippedHints(response.data.skipped ?? [], ops.length), ...hints2 ?? [], ...adCopyHints(ops)];
|
|
12551
|
-
writeJsonEnvelope(
|
|
12516
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
12552
12517
|
} catch (err) {
|
|
12553
12518
|
handleGoogleError(err);
|
|
12554
12519
|
}
|
|
@@ -12559,10 +12524,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
12559
12524
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
12560
12525
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
12561
12526
|
}
|
|
12562
|
-
async function draftAction(
|
|
12527
|
+
async function draftAction(path49, body, chat) {
|
|
12563
12528
|
try {
|
|
12564
12529
|
const chatId = resolveChatId(chat);
|
|
12565
|
-
const response = await apiPost(
|
|
12530
|
+
const response = await apiPost(path49, { chatId, ...body });
|
|
12566
12531
|
writeJsonEnvelope(response);
|
|
12567
12532
|
} catch (err) {
|
|
12568
12533
|
handleGoogleError(err);
|
|
@@ -12576,7 +12541,7 @@ async function draftListAction(json, chat) {
|
|
|
12576
12541
|
writeJsonEnvelope(response);
|
|
12577
12542
|
return;
|
|
12578
12543
|
}
|
|
12579
|
-
process.stdout.write(`${renderDraftStatus(response.data)}
|
|
12544
|
+
process.stdout.write(`${renderDraftStatus(response.data)}
|
|
12580
12545
|
`);
|
|
12581
12546
|
} catch (err) {
|
|
12582
12547
|
handleGoogleError(err);
|
|
@@ -14980,14 +14945,14 @@ function mappingRowProblem(row) {
|
|
|
14980
14945
|
|
|
14981
14946
|
// ../api/src/event-sources/template.ts
|
|
14982
14947
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
14983
|
-
function mentionOf(
|
|
14984
|
-
return `{{${
|
|
14948
|
+
function mentionOf(path49) {
|
|
14949
|
+
return `{{${path49}}}`;
|
|
14985
14950
|
}
|
|
14986
14951
|
function templateMentions(template) {
|
|
14987
14952
|
const seen = [];
|
|
14988
14953
|
for (const match of template.matchAll(MENTION)) {
|
|
14989
|
-
const
|
|
14990
|
-
if (
|
|
14954
|
+
const path49 = (match[1] ?? "").trim();
|
|
14955
|
+
if (path49 !== "" && !seen.includes(path49)) seen.push(path49);
|
|
14991
14956
|
}
|
|
14992
14957
|
return seen;
|
|
14993
14958
|
}
|
|
@@ -18342,17 +18307,17 @@ function ignoredColumnHints(columns) {
|
|
|
18342
18307
|
`Ignored ${columns.length} column(s) that are not part of a conversion: ${columns.join(", ")}. A conversion carries an order id, a date, and something to match on: a click id (gclid / gbraid / wbraid), an email, a phone, or all four of givenName + familyName + country + postalCode. Optionally a value + currency, conversionCount, and eventSource (WEB / APP / IN_STORE / PHONE / OTHER). A column named just \`Name\` is ignored on purpose \u2014 Google needs the first and last name separately, so split it before re-running.`
|
|
18343
18308
|
];
|
|
18344
18309
|
}
|
|
18345
|
-
function readRowsFile(
|
|
18346
|
-
const inline =
|
|
18310
|
+
function readRowsFile(path49) {
|
|
18311
|
+
const inline = path49.trimStart().startsWith("[") || path49.trimStart().startsWith("{");
|
|
18347
18312
|
let text2;
|
|
18348
18313
|
try {
|
|
18349
|
-
text2 = inline ?
|
|
18314
|
+
text2 = inline ? path49 : readFileSync4(path49, "utf8");
|
|
18350
18315
|
} catch (err) {
|
|
18351
|
-
failWriteValidation(`could not read ${
|
|
18316
|
+
failWriteValidation(`could not read ${path49}: ${err instanceof Error ? err.message : String(err)}`);
|
|
18352
18317
|
}
|
|
18353
18318
|
const parsed = parseConversionRowsText(text2);
|
|
18354
18319
|
if (!parsed.ok) {
|
|
18355
|
-
failWriteValidation(`${inline ? "the conversions passed inline" :
|
|
18320
|
+
failWriteValidation(`${inline ? "the conversions passed inline" : path49}: ${parsed.error}`);
|
|
18356
18321
|
}
|
|
18357
18322
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
18358
18323
|
}
|
|
@@ -20110,6 +20075,10 @@ Full guide: __tooling__/docs/tools/baker/ads-google.md`
|
|
|
20110
20075
|
// src/commands/ads/linkedin/index.ts
|
|
20111
20076
|
import { defineCommand as defineCommand53 } from "citty";
|
|
20112
20077
|
|
|
20078
|
+
// src/commands/ads/linkedin/write-shared.ts
|
|
20079
|
+
import { createHash } from "crypto";
|
|
20080
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
20081
|
+
|
|
20113
20082
|
// src/commands/ads/linkedin/shared.ts
|
|
20114
20083
|
var DAY_MS2 = 864e5;
|
|
20115
20084
|
function handleLinkedinError(err) {
|
|
@@ -20202,48 +20171,18 @@ function daysAgoIso2(days) {
|
|
|
20202
20171
|
function csvOrJson2(args5) {
|
|
20203
20172
|
return args5.output ?? "json";
|
|
20204
20173
|
}
|
|
20205
|
-
function
|
|
20206
|
-
return `CSV of statuses (${LINKEDIN_SEARCH_STATUSES[level].join(",")})`;
|
|
20207
|
-
}
|
|
20208
|
-
function statusFilterError(level, statuses) {
|
|
20209
|
-
const unsupported = unsupportedLinkedinSearchStatuses(level, statuses);
|
|
20210
|
-
if (unsupported.length === 0) {
|
|
20211
|
-
return null;
|
|
20212
|
-
}
|
|
20213
|
-
const accepted = LINKEDIN_SEARCH_STATUSES[level].join(",");
|
|
20214
|
-
return {
|
|
20215
|
-
ok: false,
|
|
20216
|
-
error: {
|
|
20217
|
-
code: "INVALID_STATUS",
|
|
20218
|
-
message: `LinkedIn does not accept status ${unsupported.join(", ")} for this listing.`,
|
|
20219
|
-
fix: {
|
|
20220
|
-
action: "retry_with_flag",
|
|
20221
|
-
explanation: `Re-run with --statuses from ${accepted}, or --all-statuses to drop the filter.`
|
|
20222
|
-
},
|
|
20223
|
-
retryable: false
|
|
20224
|
-
}
|
|
20225
|
-
};
|
|
20226
|
-
}
|
|
20227
|
-
function resolveStatusFilter(args5, level) {
|
|
20174
|
+
function resolveStatusFilter(args5) {
|
|
20228
20175
|
if (args5["all-statuses"]) {
|
|
20229
20176
|
return void 0;
|
|
20230
20177
|
}
|
|
20231
20178
|
const explicit = args5.statuses;
|
|
20232
|
-
if (
|
|
20233
|
-
return
|
|
20234
|
-
}
|
|
20235
|
-
const statuses = explicit.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
20236
|
-
const error = statusFilterError(level, statuses);
|
|
20237
|
-
if (error) {
|
|
20238
|
-
writeAdsJson(error);
|
|
20239
|
-
process.exit(1);
|
|
20179
|
+
if (explicit) {
|
|
20180
|
+
return explicit.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
20240
20181
|
}
|
|
20241
|
-
return
|
|
20182
|
+
return ["ACTIVE"];
|
|
20242
20183
|
}
|
|
20243
20184
|
|
|
20244
20185
|
// src/commands/ads/linkedin/write-shared.ts
|
|
20245
|
-
import { createHash } from "crypto";
|
|
20246
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
20247
20186
|
var TOTAL_BUDGET_HELP = "Lifetime budget \u2014 on something already running it must exceed spend to date, or LinkedIn rejects it";
|
|
20248
20187
|
function bareAccountId(args5) {
|
|
20249
20188
|
const raw = resolveAccountIdArg2(args5);
|
|
@@ -20253,19 +20192,19 @@ function failWriteValidation2(message) {
|
|
|
20253
20192
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
20254
20193
|
process.exit(1);
|
|
20255
20194
|
}
|
|
20256
|
-
function loadJsonFileArg2(
|
|
20257
|
-
if (typeof
|
|
20195
|
+
function loadJsonFileArg2(path49) {
|
|
20196
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20258
20197
|
return {};
|
|
20259
20198
|
}
|
|
20260
20199
|
try {
|
|
20261
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20200
|
+
const parsed = JSON.parse(readFileSync5(path49, "utf8"));
|
|
20262
20201
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
20263
|
-
failWriteValidation2(`${
|
|
20202
|
+
failWriteValidation2(`${path49} must contain a JSON object`);
|
|
20264
20203
|
}
|
|
20265
20204
|
return parsed;
|
|
20266
20205
|
} catch (err) {
|
|
20267
20206
|
if (err instanceof SyntaxError) {
|
|
20268
|
-
failWriteValidation2(`${
|
|
20207
|
+
failWriteValidation2(`${path49} is not valid JSON: ${err.message}`);
|
|
20269
20208
|
}
|
|
20270
20209
|
throw err;
|
|
20271
20210
|
}
|
|
@@ -20350,15 +20289,15 @@ function parseLocaleFlag(value) {
|
|
|
20350
20289
|
}
|
|
20351
20290
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
20352
20291
|
}
|
|
20353
|
-
function loadTargetingFileArg(
|
|
20354
|
-
if (typeof
|
|
20292
|
+
function loadTargetingFileArg(path49) {
|
|
20293
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20355
20294
|
return void 0;
|
|
20356
20295
|
}
|
|
20357
|
-
const parsed = loadJsonFileArg2(
|
|
20296
|
+
const parsed = loadJsonFileArg2(path49);
|
|
20358
20297
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
20359
20298
|
if (!criteria.include) {
|
|
20360
20299
|
failWriteValidation2(
|
|
20361
|
-
`${
|
|
20300
|
+
`${path49} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
20362
20301
|
);
|
|
20363
20302
|
}
|
|
20364
20303
|
return criteria;
|
|
@@ -20393,14 +20332,14 @@ function parseCsvLine(line) {
|
|
|
20393
20332
|
cells.push(current);
|
|
20394
20333
|
return cells.map((cell3) => cell3.trim());
|
|
20395
20334
|
}
|
|
20396
|
-
function parseListFileArg(
|
|
20397
|
-
if (typeof
|
|
20335
|
+
function parseListFileArg(path49, maxRows) {
|
|
20336
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20398
20337
|
return void 0;
|
|
20399
20338
|
}
|
|
20400
|
-
const raw = readFileSync5(
|
|
20339
|
+
const raw = readFileSync5(path49, "utf8");
|
|
20401
20340
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
20402
20341
|
if (lines.length < 2) {
|
|
20403
|
-
failWriteValidation2(`${
|
|
20342
|
+
failWriteValidation2(`${path49} needs a header row and at least one data row`);
|
|
20404
20343
|
}
|
|
20405
20344
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
20406
20345
|
const rows = [];
|
|
@@ -20419,7 +20358,7 @@ function parseListFileArg(path48, maxRows) {
|
|
|
20419
20358
|
}
|
|
20420
20359
|
}
|
|
20421
20360
|
if (rows.length > maxRows) {
|
|
20422
|
-
failWriteValidation2(`${
|
|
20361
|
+
failWriteValidation2(`${path49} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
20423
20362
|
}
|
|
20424
20363
|
return { columns, rows };
|
|
20425
20364
|
}
|
|
@@ -20451,7 +20390,7 @@ async function stageOp(raw, hints2) {
|
|
|
20451
20390
|
op: preflight.data
|
|
20452
20391
|
});
|
|
20453
20392
|
const allHints = [...batchNudge(response.data), ...hints2 ?? [], ...adCopyHints(preflight.data)];
|
|
20454
|
-
writeJsonEnvelope(
|
|
20393
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
20455
20394
|
} catch (err) {
|
|
20456
20395
|
handleLinkedinError(err);
|
|
20457
20396
|
}
|
|
@@ -20478,7 +20417,7 @@ async function stageLinkedinOps(rawOps, hints2) {
|
|
|
20478
20417
|
const chatId = requireChatId();
|
|
20479
20418
|
const response = await apiPost("/api/ads/linkedin/draft/stage-batch", { chatId, ops });
|
|
20480
20419
|
const allHints = [...hints2 ?? [], ...adCopyHints(ops)];
|
|
20481
|
-
writeJsonEnvelope(
|
|
20420
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
20482
20421
|
} catch (err) {
|
|
20483
20422
|
handleLinkedinError(err);
|
|
20484
20423
|
}
|
|
@@ -20515,11 +20454,11 @@ function readPositionals(args5) {
|
|
|
20515
20454
|
function splitIdList(raw) {
|
|
20516
20455
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
20517
20456
|
}
|
|
20518
|
-
function idsFileEntries(
|
|
20519
|
-
if (typeof
|
|
20457
|
+
function idsFileEntries(path49) {
|
|
20458
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20520
20459
|
return [];
|
|
20521
20460
|
}
|
|
20522
|
-
return readFileSync5(
|
|
20461
|
+
return readFileSync5(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
20523
20462
|
}
|
|
20524
20463
|
function requireTargets(args5, entity) {
|
|
20525
20464
|
const positionals = readPositionals(args5);
|
|
@@ -20570,7 +20509,7 @@ registerSchema({
|
|
|
20570
20509
|
"account-id": { type: "string", description: "Account ID", required: false },
|
|
20571
20510
|
"account-urn": { type: "string", description: "Alias for --account-id", required: false },
|
|
20572
20511
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20573
|
-
statuses: { type: "string", description:
|
|
20512
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20574
20513
|
limit: { type: "string", description: "Max rows (default 500)", required: false },
|
|
20575
20514
|
"no-cache": NO_CACHE_ARG,
|
|
20576
20515
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20584,7 +20523,7 @@ registerSchema({
|
|
|
20584
20523
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20585
20524
|
"campaign-group-id": { type: "string", description: "Filter by campaign group", required: false },
|
|
20586
20525
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20587
|
-
statuses: { type: "string", description:
|
|
20526
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20588
20527
|
limit: { type: "string", description: "Max rows", required: false },
|
|
20589
20528
|
"no-cache": NO_CACHE_ARG,
|
|
20590
20529
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20598,7 +20537,7 @@ registerSchema({
|
|
|
20598
20537
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20599
20538
|
"campaign-id": { type: "string", description: "Filter by campaign", required: false },
|
|
20600
20539
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20601
|
-
statuses: { type: "string", description:
|
|
20540
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20602
20541
|
fields: {
|
|
20603
20542
|
type: "string",
|
|
20604
20543
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage",
|
|
@@ -20871,11 +20810,7 @@ registerSchema({
|
|
|
20871
20810
|
description: "3-letter currency code (defaults to the ad account currency)",
|
|
20872
20811
|
required: false
|
|
20873
20812
|
},
|
|
20874
|
-
status: {
|
|
20875
|
-
type: "string",
|
|
20876
|
-
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED",
|
|
20877
|
-
required: false
|
|
20878
|
-
},
|
|
20813
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
|
|
20879
20814
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20880
20815
|
}
|
|
20881
20816
|
});
|
|
@@ -20933,16 +20868,7 @@ registerSchema({
|
|
|
20933
20868
|
ctv: { type: "string", description: "Connected TV on|off (default off)", required: false },
|
|
20934
20869
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20935
20870
|
"associated-entity": { type: "string", description: "Organization URN", required: false },
|
|
20936
|
-
"
|
|
20937
|
-
type: "string",
|
|
20938
|
-
description: "NOT_DECLARED (default)|NOT_POLITICAL|POLITICAL \u2014 the advertiser's declaration; NOT_POLITICAL only after the user confirms their ads are not political advertising",
|
|
20939
|
-
required: false
|
|
20940
|
-
},
|
|
20941
|
-
status: {
|
|
20942
|
-
type: "string",
|
|
20943
|
-
description: "DRAFT|ACTIVE|PAUSED (default DRAFT) \u2014 PAUSED needs a group that is not DRAFT",
|
|
20944
|
-
required: false
|
|
20945
|
-
},
|
|
20871
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
|
|
20946
20872
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20947
20873
|
}
|
|
20948
20874
|
});
|
|
@@ -20970,11 +20896,6 @@ registerSchema({
|
|
|
20970
20896
|
lan: { type: "string", description: "on|off", required: false },
|
|
20971
20897
|
ctv: { type: "string", description: "on|off", required: false },
|
|
20972
20898
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20973
|
-
"political-intent": {
|
|
20974
|
-
type: "string",
|
|
20975
|
-
description: "NOT_DECLARED (default)|NOT_POLITICAL|POLITICAL \u2014 the advertiser's declaration; NOT_POLITICAL only after the user confirms their ads are not political advertising",
|
|
20976
|
-
required: false
|
|
20977
|
-
},
|
|
20978
20899
|
status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED", required: false },
|
|
20979
20900
|
file: { type: "string", description: "JSON file with fields to change", required: false }
|
|
20980
20901
|
}
|
|
@@ -21370,8 +21291,7 @@ var campaignGroupsCreateCommand = defineCommand33({
|
|
|
21370
21291
|
meta: {
|
|
21371
21292
|
name: "create",
|
|
21372
21293
|
description: `Stage a new campaign group. ${STAGED_NOTE}
|
|
21373
|
-
|
|
21374
|
-
Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-07-10 --end 2026-09-30 --total-budget 5000 --currency EUR`
|
|
21294
|
+
Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-07-10 --total-budget 5000 --currency EUR`
|
|
21375
21295
|
},
|
|
21376
21296
|
args: {
|
|
21377
21297
|
...accountArgs,
|
|
@@ -21380,10 +21300,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
|
|
|
21380
21300
|
end: { type: "string", description: "Run schedule end" },
|
|
21381
21301
|
"total-budget": { type: "string", description: TOTAL_BUDGET_HELP },
|
|
21382
21302
|
currency: { type: "string", description: "3-letter currency code (defaults to the ad account currency)" },
|
|
21383
|
-
status: {
|
|
21384
|
-
type: "string",
|
|
21385
|
-
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED; pause it once it exists"
|
|
21386
|
-
},
|
|
21303
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)" },
|
|
21387
21304
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21388
21305
|
},
|
|
21389
21306
|
run: async ({ args: args5 }) => {
|
|
@@ -21449,11 +21366,9 @@ function campaignPayloadFromFlags(args5) {
|
|
|
21449
21366
|
connectedTelevisionOnly: parseOnOffFlag(args5.ctv, "--ctv"),
|
|
21450
21367
|
creativeSelection: args5["creative-selection"] ? String(args5["creative-selection"]).toUpperCase() : void 0,
|
|
21451
21368
|
associatedEntity: args5["associated-entity"],
|
|
21452
|
-
politicalIntent: args5["political-intent"] ? String(args5["political-intent"]).toUpperCase() : void 0,
|
|
21453
21369
|
status: args5.status ? String(args5.status).toUpperCase() : void 0
|
|
21454
21370
|
};
|
|
21455
21371
|
}
|
|
21456
|
-
var POLITICAL_INTENT_HELP = `NOT_DECLARED (default)|NOT_POLITICAL|POLITICAL \u2014 the advertiser's own declaration. Pass NOT_POLITICAL only after the user confirms: "I confirm this is not political advertising. None of my ads qualify as political advertising under the law of the targeted countries, including EU law for ads targeted to the EU."`;
|
|
21457
21372
|
var campaignFlagArgs = {
|
|
21458
21373
|
...accountArgs,
|
|
21459
21374
|
name: { type: "string", description: "Campaign name (\u2264255 chars)" },
|
|
@@ -21474,8 +21389,7 @@ var campaignFlagArgs = {
|
|
|
21474
21389
|
ctv: { type: "string", description: "Connected TV on|off" },
|
|
21475
21390
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN" },
|
|
21476
21391
|
"associated-entity": { type: "string", description: "Organization URN" },
|
|
21477
|
-
|
|
21478
|
-
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED \u2014 PAUSED needs a group that is not DRAFT" },
|
|
21392
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED" },
|
|
21479
21393
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21480
21394
|
};
|
|
21481
21395
|
var campaignsCreateCommand = defineCommand33({
|
|
@@ -22992,7 +22906,7 @@ var listArgs = {
|
|
|
22992
22906
|
"account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
|
|
22993
22907
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
22994
22908
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
22995
|
-
statuses: { type: "string", description:
|
|
22909
|
+
statuses: { type: "string", description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)" },
|
|
22996
22910
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
22997
22911
|
"no-cache": NO_CACHE_ARG,
|
|
22998
22912
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -23007,7 +22921,7 @@ var campaignGroupsListCommand = defineCommand40({
|
|
|
23007
22921
|
const accountId = resolveAccountIdArg2(args5);
|
|
23008
22922
|
try {
|
|
23009
22923
|
const params = { "account-id": accountId };
|
|
23010
|
-
const statuses = resolveStatusFilter(args5
|
|
22924
|
+
const statuses = resolveStatusFilter(args5);
|
|
23011
22925
|
if (statuses) params.statuses = statuses.join(",");
|
|
23012
22926
|
if (args5.limit) params.limit = String(args5.limit);
|
|
23013
22927
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
@@ -23058,7 +22972,7 @@ var listArgs2 = {
|
|
|
23058
22972
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
23059
22973
|
"campaign-group-id": { type: "string", description: "Filter by campaign group" },
|
|
23060
22974
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
23061
|
-
statuses: { type: "string", description:
|
|
22975
|
+
statuses: { type: "string", description: "CSV of statuses" },
|
|
23062
22976
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
23063
22977
|
"no-cache": NO_CACHE_ARG,
|
|
23064
22978
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -23073,7 +22987,7 @@ var campaignsListCommand = defineCommand41({
|
|
|
23073
22987
|
const accountId = resolveAccountIdArg2(args5);
|
|
23074
22988
|
try {
|
|
23075
22989
|
const params = { "account-id": accountId };
|
|
23076
|
-
const statuses = resolveStatusFilter(args5
|
|
22990
|
+
const statuses = resolveStatusFilter(args5);
|
|
23077
22991
|
if (statuses) params.statuses = statuses.join(",");
|
|
23078
22992
|
if (args5["campaign-group-id"]) params["campaign-group-id"] = String(args5["campaign-group-id"]);
|
|
23079
22993
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -23306,9 +23220,9 @@ import { defineCommand as defineCommand44 } from "citty";
|
|
|
23306
23220
|
function asRecord(value) {
|
|
23307
23221
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
23308
23222
|
}
|
|
23309
|
-
function readPath2(row,
|
|
23223
|
+
function readPath2(row, path49) {
|
|
23310
23224
|
let current = row;
|
|
23311
|
-
for (const segment of
|
|
23225
|
+
for (const segment of path49.split(".")) {
|
|
23312
23226
|
const record = asRecord(current);
|
|
23313
23227
|
if (!record) return void 0;
|
|
23314
23228
|
current = record[segment];
|
|
@@ -23318,10 +23232,10 @@ function readPath2(row, path48) {
|
|
|
23318
23232
|
function projectFields(rows, paths) {
|
|
23319
23233
|
return rows.map((row) => {
|
|
23320
23234
|
const projected = {};
|
|
23321
|
-
for (const
|
|
23322
|
-
const value = readPath2(row,
|
|
23235
|
+
for (const path49 of paths) {
|
|
23236
|
+
const value = readPath2(row, path49);
|
|
23323
23237
|
if (value !== void 0) {
|
|
23324
|
-
projected[
|
|
23238
|
+
projected[path49] = value;
|
|
23325
23239
|
}
|
|
23326
23240
|
}
|
|
23327
23241
|
return projected;
|
|
@@ -23334,16 +23248,16 @@ function shapeListRows(rows, args5, compact4) {
|
|
|
23334
23248
|
const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
|
|
23335
23249
|
if (paths.length > 0) {
|
|
23336
23250
|
const projected = projectFields(raw, paths).map((row, i) => {
|
|
23337
|
-
const missing = paths.filter((
|
|
23251
|
+
const missing = paths.filter((path49) => row[path49] === void 0);
|
|
23338
23252
|
const source = rows[i];
|
|
23339
23253
|
if (missing.length === 0 || source === void 0) return row;
|
|
23340
23254
|
const compactRow3 = compact4.row(source);
|
|
23341
|
-
for (const
|
|
23342
|
-
if (compactRow3[
|
|
23255
|
+
for (const path49 of missing) {
|
|
23256
|
+
if (compactRow3[path49] !== void 0) row[path49] = compactRow3[path49];
|
|
23343
23257
|
}
|
|
23344
23258
|
return row;
|
|
23345
23259
|
});
|
|
23346
|
-
const unmatched = paths.filter((
|
|
23260
|
+
const unmatched = paths.filter((path49) => projected.every((row) => row[path49] === void 0));
|
|
23347
23261
|
if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
|
|
23348
23262
|
const carried = /* @__PURE__ */ new Set([...compact4.columns, ...raw.flatMap((row) => Object.keys(row))]);
|
|
23349
23263
|
return {
|
|
@@ -23423,7 +23337,7 @@ var listArgs3 = {
|
|
|
23423
23337
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
23424
23338
|
"campaign-id": { type: "string", description: "Filter by campaign ID" },
|
|
23425
23339
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
23426
|
-
statuses: { type: "string", description:
|
|
23340
|
+
statuses: { type: "string", description: "CSV of intended statuses (ACTIVE,PAUSED,DRAFT,ARCHIVED)" },
|
|
23427
23341
|
fields: {
|
|
23428
23342
|
type: "string",
|
|
23429
23343
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage"
|
|
@@ -23443,7 +23357,7 @@ var creativesListCommand = defineCommand44({
|
|
|
23443
23357
|
const accountId = resolveAccountIdArg2(args5);
|
|
23444
23358
|
try {
|
|
23445
23359
|
const params = { "account-id": accountId };
|
|
23446
|
-
const statuses = resolveStatusFilter(args5
|
|
23360
|
+
const statuses = resolveStatusFilter(args5);
|
|
23447
23361
|
if (statuses) params.statuses = statuses.join(",");
|
|
23448
23362
|
if (args5["campaign-id"]) params["campaign-id"] = String(args5["campaign-id"]);
|
|
23449
23363
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -23750,7 +23664,7 @@ async function listDraft(json, chat) {
|
|
|
23750
23664
|
writeJsonEnvelope(response);
|
|
23751
23665
|
return;
|
|
23752
23666
|
}
|
|
23753
|
-
process.stdout.write(`${renderDraftStatus2(response.data)}
|
|
23667
|
+
process.stdout.write(`${renderDraftStatus2(response.data)}
|
|
23754
23668
|
`);
|
|
23755
23669
|
} catch (err) {
|
|
23756
23670
|
handleLinkedinError(err);
|
|
@@ -24713,54 +24627,54 @@ function buildCustomConversionRule(input) {
|
|
|
24713
24627
|
function customConversionRuleRefusal(rule) {
|
|
24714
24628
|
return ruleNodeRefusal(rule, "rule");
|
|
24715
24629
|
}
|
|
24716
|
-
function branchRefusal(key, value,
|
|
24630
|
+
function branchRefusal(key, value, path49) {
|
|
24717
24631
|
if (!Array.isArray(value) || value.length === 0) {
|
|
24718
|
-
return `${
|
|
24632
|
+
return `${path49}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
24719
24633
|
}
|
|
24720
24634
|
for (const [index, child] of value.entries()) {
|
|
24721
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
24635
|
+
const refusal = ruleNodeRefusal(child, `${path49}.${key}[${index}]`);
|
|
24722
24636
|
if (refusal) {
|
|
24723
24637
|
return refusal;
|
|
24724
24638
|
}
|
|
24725
24639
|
}
|
|
24726
24640
|
return void 0;
|
|
24727
24641
|
}
|
|
24728
|
-
function conditionRefusal(key, value,
|
|
24729
|
-
return key === "and" || key === "or" ? branchRefusal(key, value,
|
|
24642
|
+
function conditionRefusal(key, value, path49) {
|
|
24643
|
+
return key === "and" || key === "or" ? branchRefusal(key, value, path49) : leafRefusal(key, value, path49);
|
|
24730
24644
|
}
|
|
24731
|
-
function ruleNodeRefusal(node,
|
|
24645
|
+
function ruleNodeRefusal(node, path49) {
|
|
24732
24646
|
if (!isRecord2(node)) {
|
|
24733
|
-
return `${
|
|
24647
|
+
return `${path49} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
24734
24648
|
}
|
|
24735
24649
|
const entries = Object.entries(node);
|
|
24736
24650
|
if (entries.length === 0) {
|
|
24737
|
-
return `${
|
|
24651
|
+
return `${path49} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
24738
24652
|
}
|
|
24739
24653
|
if (entries.length > 1) {
|
|
24740
|
-
return `${
|
|
24654
|
+
return `${path49} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
|
|
24741
24655
|
}
|
|
24742
24656
|
for (const [key, value] of entries) {
|
|
24743
|
-
const refusal = conditionRefusal(key, value,
|
|
24657
|
+
const refusal = conditionRefusal(key, value, path49);
|
|
24744
24658
|
if (refusal) {
|
|
24745
24659
|
return refusal;
|
|
24746
24660
|
}
|
|
24747
24661
|
}
|
|
24748
24662
|
return void 0;
|
|
24749
24663
|
}
|
|
24750
|
-
function leafRefusal(field, condition,
|
|
24664
|
+
function leafRefusal(field, condition, path49) {
|
|
24751
24665
|
if (!isRecord2(condition)) {
|
|
24752
|
-
return `${
|
|
24666
|
+
return `${path49}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
24753
24667
|
}
|
|
24754
24668
|
const tests = Object.entries(condition);
|
|
24755
24669
|
if (tests.length === 0) {
|
|
24756
|
-
return `${
|
|
24670
|
+
return `${path49}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
24757
24671
|
}
|
|
24758
24672
|
if (tests.length > 1) {
|
|
24759
|
-
return `${
|
|
24673
|
+
return `${path49}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
|
|
24760
24674
|
}
|
|
24761
24675
|
for (const [operator] of tests) {
|
|
24762
24676
|
if (!RULE_OPERATORS[operator]) {
|
|
24763
|
-
return `${
|
|
24677
|
+
return `${path49}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
|
|
24764
24678
|
}
|
|
24765
24679
|
}
|
|
24766
24680
|
return void 0;
|
|
@@ -25476,11 +25390,11 @@ var updateStatusSchema = z37.enum(UPDATE_STATUSES);
|
|
|
25476
25390
|
function currencyMinimums2(currencyCode) {
|
|
25477
25391
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
25478
25392
|
}
|
|
25479
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
25393
|
+
function validateDailyBudgetFloor(money, ctx, path49) {
|
|
25480
25394
|
if (money?.currencyCode) {
|
|
25481
25395
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
25482
25396
|
if (Number(money.amount) < min) {
|
|
25483
|
-
ctx.addIssue({ code: "custom", path:
|
|
25397
|
+
ctx.addIssue({ code: "custom", path: path49, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
25484
25398
|
}
|
|
25485
25399
|
}
|
|
25486
25400
|
}
|
|
@@ -26352,19 +26266,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
26352
26266
|
);
|
|
26353
26267
|
}
|
|
26354
26268
|
}
|
|
26355
|
-
function loadJsonFileArg3(
|
|
26356
|
-
if (typeof
|
|
26269
|
+
function loadJsonFileArg3(path49) {
|
|
26270
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
26357
26271
|
return {};
|
|
26358
26272
|
}
|
|
26359
26273
|
try {
|
|
26360
|
-
const parsed = JSON.parse(readFileSync9(
|
|
26274
|
+
const parsed = JSON.parse(readFileSync9(path49, "utf8"));
|
|
26361
26275
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
26362
|
-
failWriteValidation3(`${
|
|
26276
|
+
failWriteValidation3(`${path49} must contain a JSON object`);
|
|
26363
26277
|
}
|
|
26364
26278
|
return parsed;
|
|
26365
26279
|
} catch (err) {
|
|
26366
26280
|
if (err instanceof SyntaxError) {
|
|
26367
|
-
failWriteValidation3(`${
|
|
26281
|
+
failWriteValidation3(`${path49} is not valid JSON: ${err.message}`);
|
|
26368
26282
|
}
|
|
26369
26283
|
throw err;
|
|
26370
26284
|
}
|
|
@@ -26455,7 +26369,7 @@ async function stageOp2(raw) {
|
|
|
26455
26369
|
const chatId = requireChatId();
|
|
26456
26370
|
const response = await apiPost("/api/ads/meta/draft/stage", { chatId, op: preflight.data });
|
|
26457
26371
|
const copyHints = adCopyHints(preflight.data);
|
|
26458
|
-
writeJsonEnvelope(
|
|
26372
|
+
writeJsonEnvelope(copyHints.length > 0 ? { ...response, hints: copyHints } : response);
|
|
26459
26373
|
} catch (err) {
|
|
26460
26374
|
handleMetaError(err);
|
|
26461
26375
|
}
|
|
@@ -27728,7 +27642,7 @@ async function listDraft2(json, chat) {
|
|
|
27728
27642
|
writeJsonEnvelope(response);
|
|
27729
27643
|
return;
|
|
27730
27644
|
}
|
|
27731
|
-
process.stdout.write(`${renderDraftStatus3(response.data)}
|
|
27645
|
+
process.stdout.write(`${renderDraftStatus3(response.data)}
|
|
27732
27646
|
`);
|
|
27733
27647
|
} catch (err) {
|
|
27734
27648
|
handleMetaError(err);
|
|
@@ -28398,10 +28312,19 @@ var metaMediaCommand = defineCommand68({
|
|
|
28398
28312
|
|
|
28399
28313
|
// src/commands/ads/meta/pages.ts
|
|
28400
28314
|
import { defineCommand as defineCommand69 } from "citty";
|
|
28315
|
+
function advertisablePages(data) {
|
|
28316
|
+
return data.filter((p) => Array.isArray(p.tasks) && p.tasks.includes("ADVERTISE"));
|
|
28317
|
+
}
|
|
28401
28318
|
function pageSelectionHints(data) {
|
|
28402
|
-
|
|
28319
|
+
const advertisable = advertisablePages(data);
|
|
28320
|
+
if (advertisable.length > 1) {
|
|
28321
|
+
return [
|
|
28322
|
+
"MULTIPLE Pages can run ads \u2014 do NOT guess. Confirm with the user which Page an ad should run from before passing --page to `creatives create`; a wrong Page publishes the ad under the wrong brand identity and staging will not catch it."
|
|
28323
|
+
];
|
|
28324
|
+
}
|
|
28325
|
+
if (data.length > 0 && advertisable.length === 0) {
|
|
28403
28326
|
return [
|
|
28404
|
-
"
|
|
28327
|
+
"NO Page can run ads \u2014 none of the connected user's Pages carry the ADVERTISE task. Ask the user to grant Advertise access to the right Page before creating an ad; a readable-but-non-advertising Page still passes staging and would fail or run under the wrong identity."
|
|
28405
28328
|
];
|
|
28406
28329
|
}
|
|
28407
28330
|
return [];
|
|
@@ -28409,7 +28332,7 @@ function pageSelectionHints(data) {
|
|
|
28409
28332
|
var pagesCommand = defineCommand69({
|
|
28410
28333
|
meta: {
|
|
28411
28334
|
name: "pages",
|
|
28412
|
-
description: `List the Facebook Pages
|
|
28335
|
+
description: `List the Facebook Pages the connected user manages. Every Meta ad publishes from a Page, so use this to identify the Page an ad should run from. The 'tasks' field shows what the user can do on each Page (ADVERTISE means it can back ads). If exactly one Page can ADVERTISE, use it; if more than one can, confirm with the user which Page to use; if none can, ask the user to grant Advertise access \u2014 a wrong or non-advertising Page publishes under the wrong brand identity.
|
|
28413
28336
|
|
|
28414
28337
|
Examples:
|
|
28415
28338
|
baker ads meta pages`
|
|
@@ -28670,7 +28593,7 @@ Discovery:
|
|
|
28670
28593
|
baker ads meta accounts \u2014 accounts in this company's connected scope
|
|
28671
28594
|
baker ads meta accounts --include-all \u2014 every account the token can see
|
|
28672
28595
|
baker ads meta businesses \u2014 Business Manager IDs
|
|
28673
|
-
baker ads meta pages \u2014 Facebook Pages the
|
|
28596
|
+
baker ads meta pages \u2014 Facebook Pages the user manages (an ad's identity)
|
|
28674
28597
|
baker ads meta lead-forms --page-id 100635183117758 \u2014 instant (lead) forms on a Page, with lead counts
|
|
28675
28598
|
baker ads meta leads --form-id 987654321 \u2014 the leads one form collected (contact details masked)
|
|
28676
28599
|
|
|
@@ -32051,12 +31974,12 @@ function flowExists(slug) {
|
|
|
32051
31974
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
32052
31975
|
}
|
|
32053
31976
|
function readFlowTree(slug) {
|
|
32054
|
-
const
|
|
32055
|
-
if (!existsSync3(
|
|
31977
|
+
const path49 = join2(flowsDir(), slug, "_data.json");
|
|
31978
|
+
if (!existsSync3(path49)) {
|
|
32056
31979
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
32057
31980
|
}
|
|
32058
31981
|
try {
|
|
32059
|
-
return JSON.parse(readFileSync11(
|
|
31982
|
+
return JSON.parse(readFileSync11(path49, "utf-8"));
|
|
32060
31983
|
} catch (error) {
|
|
32061
31984
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
32062
31985
|
}
|
|
@@ -33016,12 +32939,12 @@ function readPeopleFile(args5) {
|
|
|
33016
32939
|
}
|
|
33017
32940
|
function unreadablePeopleFile(args5) {
|
|
33018
32941
|
if (!args5["people-file"]) return void 0;
|
|
33019
|
-
const
|
|
32942
|
+
const path49 = String(args5["people-file"]);
|
|
33020
32943
|
try {
|
|
33021
|
-
readFileSync12(
|
|
32944
|
+
readFileSync12(path49, "utf8");
|
|
33022
32945
|
return void 0;
|
|
33023
32946
|
} catch {
|
|
33024
|
-
return `Couldn't read --people-file ${
|
|
32947
|
+
return `Couldn't read --people-file ${path49}. Check the path, or pass the people inline with --person.`;
|
|
33025
32948
|
}
|
|
33026
32949
|
}
|
|
33027
32950
|
function peopleLimitError(args5) {
|
|
@@ -33993,11 +33916,11 @@ function parseFieldArgs(argv) {
|
|
|
33993
33916
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
33994
33917
|
const eq = pair.indexOf("=");
|
|
33995
33918
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
33996
|
-
const
|
|
33919
|
+
const path49 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
33997
33920
|
const problem = mappingRowProblem(field);
|
|
33998
33921
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
33999
|
-
if (
|
|
34000
|
-
mapping[field] =
|
|
33922
|
+
if (path49 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
33923
|
+
mapping[field] = path49;
|
|
34001
33924
|
}
|
|
34002
33925
|
return mapping;
|
|
34003
33926
|
}
|
|
@@ -35599,11 +35522,11 @@ function unwrap(response) {
|
|
|
35599
35522
|
}
|
|
35600
35523
|
return response.data;
|
|
35601
35524
|
}
|
|
35602
|
-
async function readAvatars(
|
|
35603
|
-
return unwrap(await apiGet(
|
|
35525
|
+
async function readAvatars(path49, params) {
|
|
35526
|
+
return unwrap(await apiGet(path49, params));
|
|
35604
35527
|
}
|
|
35605
|
-
async function writeAvatars(
|
|
35606
|
-
return unwrap(await apiPost(
|
|
35528
|
+
async function writeAvatars(path49, body) {
|
|
35529
|
+
return unwrap(await apiPost(path49, body));
|
|
35607
35530
|
}
|
|
35608
35531
|
|
|
35609
35532
|
// src/commands/avatars/create.ts
|
|
@@ -36512,12 +36435,12 @@ function missingFontFiles(urls, available) {
|
|
|
36512
36435
|
function planFontAdoption(sources, families) {
|
|
36513
36436
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
36514
36437
|
const byFamily = /* @__PURE__ */ new Map();
|
|
36515
|
-
for (const { path:
|
|
36516
|
-
const dir = posix.dirname(
|
|
36438
|
+
for (const { path: path49, source } of sources) {
|
|
36439
|
+
const dir = posix.dirname(path49);
|
|
36517
36440
|
for (const face of declaredFontFaces(source)) {
|
|
36518
36441
|
if (!wanted.has(face.family)) continue;
|
|
36519
36442
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
36520
|
-
perFile.set(
|
|
36443
|
+
perFile.set(path49, [...perFile.get(path49) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
36521
36444
|
byFamily.set(face.family, perFile);
|
|
36522
36445
|
}
|
|
36523
36446
|
}
|
|
@@ -40782,18 +40705,10 @@ function dropUncastVoices(nodes) {
|
|
|
40782
40705
|
if (node && node.type === "voice_select" && !referenced.has(node.id)) nodes.splice(i, 1);
|
|
40783
40706
|
}
|
|
40784
40707
|
}
|
|
40785
|
-
function
|
|
40786
|
-
if (requested !== "reuse") return void 0;
|
|
40787
|
-
const showsPeople = (blueprint.global?.cast ?? []).length > 0 || elements.some((e) => e.type.toLowerCase() === "person");
|
|
40788
|
-
if (!showsPeople) return void 0;
|
|
40789
|
-
return "--frames reuse was not applied: this video shows people, and reusing its frames would put the source's actors into our ad. Every frame is generated instead, recast to the el_* references. Reuse applies only to a video with nobody in it.";
|
|
40790
|
-
}
|
|
40791
|
-
function scaffoldVideoCanvas(input, elementsInput, requested) {
|
|
40708
|
+
function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
40792
40709
|
const blueprint = VideoBlueprint.parse(input);
|
|
40793
40710
|
injectHookPhysicality(blueprint);
|
|
40794
40711
|
const elements = RecurringElements.parse(elementsInput);
|
|
40795
|
-
const reuseRefused = framesReuseRefusal(blueprint, elements, requested.frames);
|
|
40796
|
-
const opts = reuseRefused ? { ...requested, frames: "generate" } : requested;
|
|
40797
40712
|
const clock = spineClockFor(blueprint);
|
|
40798
40713
|
const nodes = [];
|
|
40799
40714
|
emitBlueprintIngests(opts, nodes);
|
|
@@ -40896,7 +40811,6 @@ function scaffoldVideoCanvas(input, elementsInput, requested) {
|
|
|
40896
40811
|
}
|
|
40897
40812
|
const todo = {
|
|
40898
40813
|
...buildVideoTodo(videoReport(input, elementsInput), overlays.length, floating.length, opts, blueprint),
|
|
40899
|
-
...reuseRefused ? { frames_reuse_refused: reuseRefused } : {},
|
|
40900
40814
|
...aspectRemapTodo(resolveAspect(blueprint.source?.aspect_ratio, opts.aspect, genAspectsFor(opts.videoModel))),
|
|
40901
40815
|
model_constraints: buildModelConstraints()
|
|
40902
40816
|
};
|
|
@@ -45823,12 +45737,6 @@ function videoDefinitionDescription(blueprint) {
|
|
|
45823
45737
|
const product = g.branding?.product;
|
|
45824
45738
|
return typeof product === "string" && product.trim() ? product.trim() : void 0;
|
|
45825
45739
|
}
|
|
45826
|
-
function framesModeReport(canvas, requested) {
|
|
45827
|
-
const todo = canvas.metadata?.todo;
|
|
45828
|
-
const mode = typeof todo?.frames_mode === "string" ? todo.frames_mode : requested;
|
|
45829
|
-
const refused = typeof todo?.frames_reuse_refused === "string" ? todo.frames_reuse_refused : void 0;
|
|
45830
|
-
return { frames_mode: mode, ...refused ? { frames_reuse_refused: refused } : {} };
|
|
45831
|
-
}
|
|
45832
45740
|
async function materializeReferenceVideo(fileArg2) {
|
|
45833
45741
|
if (!/^https?:\/\//i.test(fileArg2)) return path26.resolve(fileArg2);
|
|
45834
45742
|
let bytes;
|
|
@@ -45986,10 +45894,7 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
45986
45894
|
type: "string",
|
|
45987
45895
|
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
45988
45896
|
},
|
|
45989
|
-
frames: {
|
|
45990
|
-
type: "string",
|
|
45991
|
-
description: `"generate" (default, every frame regenerated for our ad) or "reuse" (wire the source's real frames in). Reuse applies only to a video with nobody in it \u2014 on a video showing people it is refused and every frame is generated, so the source's actors never reach our ad.`
|
|
45992
|
-
},
|
|
45897
|
+
frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
|
|
45993
45898
|
ambient: {
|
|
45994
45899
|
type: "boolean",
|
|
45995
45900
|
description: "Give silent b-roll scenes native diegetic ambient mixed deep under the music bed (off by default)"
|
|
@@ -46192,7 +46097,6 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
46192
46097
|
error: { code: "validation", issues: validation.issues },
|
|
46193
46098
|
canvas_path: outPath,
|
|
46194
46099
|
prompt_path: blueprintPath,
|
|
46195
|
-
...framesModeReport(canvas, frames),
|
|
46196
46100
|
note: "The canvas WAS written despite the blocking issue(s) \u2014 fix them in place, then `baker canvas validate` before running.",
|
|
46197
46101
|
...uncastHint
|
|
46198
46102
|
},
|
|
@@ -46244,7 +46148,7 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
46244
46148
|
composition_dir: compositionDest,
|
|
46245
46149
|
output: canvas.output,
|
|
46246
46150
|
...uncastHint,
|
|
46247
|
-
|
|
46151
|
+
frames_mode: frames,
|
|
46248
46152
|
models: {
|
|
46249
46153
|
deconstruct: deconstructModel,
|
|
46250
46154
|
select: selectModel,
|
|
@@ -49362,10 +49266,10 @@ function parseValueExpression(raw) {
|
|
|
49362
49266
|
return parts.map(parsePart);
|
|
49363
49267
|
}
|
|
49364
49268
|
function trackingFieldIds() {
|
|
49365
|
-
const
|
|
49366
|
-
if (!existsSync6(
|
|
49269
|
+
const path49 = join4(flowsDir(), "..", "tracking.ts");
|
|
49270
|
+
if (!existsSync6(path49)) return null;
|
|
49367
49271
|
try {
|
|
49368
|
-
const source = readFileSync15(
|
|
49272
|
+
const source = readFileSync15(path49, "utf-8");
|
|
49369
49273
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
49370
49274
|
if (!block2) return null;
|
|
49371
49275
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -49939,13 +49843,13 @@ function specsFromFile(parsed) {
|
|
|
49939
49843
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
49940
49844
|
});
|
|
49941
49845
|
}
|
|
49942
|
-
function readSpecFile(
|
|
49846
|
+
function readSpecFile(path49) {
|
|
49943
49847
|
let raw;
|
|
49944
49848
|
try {
|
|
49945
|
-
raw =
|
|
49849
|
+
raw = path49 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path49, "utf-8");
|
|
49946
49850
|
} catch (error) {
|
|
49947
49851
|
refuse(
|
|
49948
|
-
`Could not read ${
|
|
49852
|
+
`Could not read ${path49 === "-" ? "the mapping from stdin" : `"${path49}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
49949
49853
|
);
|
|
49950
49854
|
}
|
|
49951
49855
|
let parsed;
|
|
@@ -49953,7 +49857,7 @@ function readSpecFile(path48) {
|
|
|
49953
49857
|
parsed = JSON.parse(raw);
|
|
49954
49858
|
} catch (error) {
|
|
49955
49859
|
refuse(
|
|
49956
|
-
`${
|
|
49860
|
+
`${path49 === "-" ? "stdin" : `"${path49}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
49957
49861
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
49958
49862
|
);
|
|
49959
49863
|
}
|
|
@@ -50252,21 +50156,21 @@ var ARRAY_FIELDS = [
|
|
|
50252
50156
|
"tagIds"
|
|
50253
50157
|
];
|
|
50254
50158
|
var ARRAY_OWNERS = ["", "body"];
|
|
50255
|
-
function dropUnsetOptionals(sideEffect,
|
|
50159
|
+
function dropUnsetOptionals(sideEffect, path49) {
|
|
50256
50160
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
50257
50161
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
50258
50162
|
delete sideEffect[key];
|
|
50259
|
-
return [{ path:
|
|
50163
|
+
return [{ path: path49, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
50260
50164
|
});
|
|
50261
50165
|
}
|
|
50262
|
-
function fillNulledArrays(target2, prefix,
|
|
50166
|
+
function fillNulledArrays(target2, prefix, path49) {
|
|
50263
50167
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
50264
50168
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
50265
50169
|
target2[key] = [];
|
|
50266
|
-
return [{ path:
|
|
50170
|
+
return [{ path: path49, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
50267
50171
|
});
|
|
50268
50172
|
}
|
|
50269
|
-
function tidyEmailRecipients(sideEffect,
|
|
50173
|
+
function tidyEmailRecipients(sideEffect, path49) {
|
|
50270
50174
|
if (sideEffect.type !== "email") return [];
|
|
50271
50175
|
const config = sideEffect.encryptedConfig;
|
|
50272
50176
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -50277,7 +50181,7 @@ function tidyEmailRecipients(sideEffect, path48) {
|
|
|
50277
50181
|
const tidied = to.join(", ");
|
|
50278
50182
|
if (tidied === raw) return [];
|
|
50279
50183
|
config.email = tidied;
|
|
50280
|
-
return [{ path:
|
|
50184
|
+
return [{ path: path49, change: "tidied the recipient list's spacing and separators" }];
|
|
50281
50185
|
}
|
|
50282
50186
|
function sideEffectsOf(node) {
|
|
50283
50187
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -50286,13 +50190,13 @@ function sideEffectsOf(node) {
|
|
|
50286
50190
|
);
|
|
50287
50191
|
}
|
|
50288
50192
|
function normalizeSideEffect(sideEffect, where) {
|
|
50289
|
-
const
|
|
50193
|
+
const path49 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
50290
50194
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
50291
50195
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
50292
50196
|
if (!target2 || typeof target2 !== "object") return [];
|
|
50293
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
50197
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path49);
|
|
50294
50198
|
});
|
|
50295
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
50199
|
+
return [...dropUnsetOptionals(sideEffect, path49), ...arrays, ...tidyEmailRecipients(sideEffect, path49)];
|
|
50296
50200
|
}
|
|
50297
50201
|
function normalizeFlowTree(tree) {
|
|
50298
50202
|
const changes = [];
|
|
@@ -51654,11 +51558,11 @@ var WARNING_HINT = "Read the warnings above before telling the user this is read
|
|
|
51654
51558
|
async function stageOp3(op) {
|
|
51655
51559
|
const chatId = requireChatId();
|
|
51656
51560
|
try {
|
|
51657
|
-
const
|
|
51561
|
+
const data = await apiPost("/api/ga4/draft/stage", { chatId, op });
|
|
51658
51562
|
writeJsonEnvelope({
|
|
51659
51563
|
ok: true,
|
|
51660
51564
|
data,
|
|
51661
|
-
hints: [...
|
|
51565
|
+
hints: [...STAGE_HINTS, ...data.warnings.length > 0 ? [WARNING_HINT] : []]
|
|
51662
51566
|
});
|
|
51663
51567
|
} catch (err) {
|
|
51664
51568
|
handleError5(err);
|
|
@@ -51672,23 +51576,21 @@ async function stageOps(ops) {
|
|
|
51672
51576
|
}
|
|
51673
51577
|
const chatId = requireChatId();
|
|
51674
51578
|
try {
|
|
51675
|
-
const {
|
|
51676
|
-
await apiPost("/api/ga4/draft/stage-batch", { chatId, ops })
|
|
51677
|
-
);
|
|
51579
|
+
const data = await apiPost("/api/ga4/draft/stage-batch", { chatId, ops });
|
|
51678
51580
|
writeJsonEnvelope({
|
|
51679
51581
|
ok: true,
|
|
51680
51582
|
data,
|
|
51681
|
-
hints: [...
|
|
51583
|
+
hints: [...STAGE_HINTS, ...data.ops.some((op) => op.warnings.length > 0) ? [WARNING_HINT] : []]
|
|
51682
51584
|
});
|
|
51683
51585
|
} catch (err) {
|
|
51684
51586
|
handleError5(err);
|
|
51685
51587
|
}
|
|
51686
51588
|
}
|
|
51687
|
-
async function draftAction2(
|
|
51589
|
+
async function draftAction2(path49, body, chat) {
|
|
51688
51590
|
const chatId = resolveChatId(chat);
|
|
51689
51591
|
try {
|
|
51690
|
-
const
|
|
51691
|
-
writeJsonEnvelope({ ok: true, data
|
|
51592
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
51593
|
+
writeJsonEnvelope({ ok: true, data });
|
|
51692
51594
|
return data;
|
|
51693
51595
|
} catch (err) {
|
|
51694
51596
|
handleError5(err);
|
|
@@ -51720,13 +51622,12 @@ function renderDraft(response) {
|
|
|
51720
51622
|
async function draftList(json, chat) {
|
|
51721
51623
|
const chatId = resolveChatId(chat);
|
|
51722
51624
|
try {
|
|
51723
|
-
const
|
|
51724
|
-
const { data, hints: hints2 } = splitHints(response);
|
|
51625
|
+
const data = await apiPost("/api/ga4/draft", { chatId });
|
|
51725
51626
|
if (json) {
|
|
51726
|
-
writeJsonEnvelope({ ok: true, data
|
|
51627
|
+
writeJsonEnvelope({ ok: true, data });
|
|
51727
51628
|
return;
|
|
51728
51629
|
}
|
|
51729
|
-
process.stdout.write(`${renderDraft(data)}
|
|
51630
|
+
process.stdout.write(`${renderDraft(data)}
|
|
51730
51631
|
`);
|
|
51731
51632
|
} catch (err) {
|
|
51732
51633
|
handleError5(err);
|
|
@@ -54217,9 +54118,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
54217
54118
|
}
|
|
54218
54119
|
return readFile28(pathOrUrl);
|
|
54219
54120
|
}
|
|
54220
|
-
async function isDirectory(
|
|
54121
|
+
async function isDirectory(path49) {
|
|
54221
54122
|
try {
|
|
54222
|
-
const s = await stat7(
|
|
54123
|
+
const s = await stat7(path49);
|
|
54223
54124
|
return s.isDirectory();
|
|
54224
54125
|
} catch {
|
|
54225
54126
|
return false;
|
|
@@ -54647,13 +54548,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
54647
54548
|
}
|
|
54648
54549
|
function disambiguate(paths) {
|
|
54649
54550
|
const taken = /* @__PURE__ */ new Set();
|
|
54650
|
-
return paths.map((
|
|
54651
|
-
if (!taken.has(
|
|
54652
|
-
taken.add(
|
|
54653
|
-
return
|
|
54551
|
+
return paths.map((path49) => {
|
|
54552
|
+
if (!taken.has(path49)) {
|
|
54553
|
+
taken.add(path49);
|
|
54554
|
+
return path49;
|
|
54654
54555
|
}
|
|
54655
|
-
const ext = extname3(
|
|
54656
|
-
const stem =
|
|
54556
|
+
const ext = extname3(path49);
|
|
54557
|
+
const stem = path49.slice(0, path49.length - ext.length);
|
|
54657
54558
|
let n = 2;
|
|
54658
54559
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
54659
54560
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -54779,10 +54680,10 @@ async function runDownloads(plan) {
|
|
|
54779
54680
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
54780
54681
|
const downloaded = [];
|
|
54781
54682
|
for (const [index, item] of fetched.entries()) {
|
|
54782
|
-
const
|
|
54683
|
+
const path49 = paths[index] ?? item.path;
|
|
54783
54684
|
try {
|
|
54784
|
-
await atomicWrite(
|
|
54785
|
-
downloaded.push({ input: item.input, output:
|
|
54685
|
+
await atomicWrite(path49, item.buffer);
|
|
54686
|
+
downloaded.push({ input: item.input, output: path49, bytes: item.buffer.length, contentType: item.contentType });
|
|
54786
54687
|
} catch (err) {
|
|
54787
54688
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
54788
54689
|
}
|
|
@@ -62969,11 +62870,365 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
|
62969
62870
|
}
|
|
62970
62871
|
});
|
|
62971
62872
|
|
|
62873
|
+
// src/commands/media-sources/index.ts
|
|
62874
|
+
import { defineCommand as defineCommand189 } from "citty";
|
|
62875
|
+
|
|
62876
|
+
// ../api/src/media-sources.ts
|
|
62877
|
+
import { z as z51 } from "zod";
|
|
62878
|
+
var mediaSourcePlatformSchema = z51.enum([
|
|
62879
|
+
"instagram",
|
|
62880
|
+
"tiktok",
|
|
62881
|
+
"youtube",
|
|
62882
|
+
"linkedin",
|
|
62883
|
+
"facebook",
|
|
62884
|
+
"google_drive"
|
|
62885
|
+
]);
|
|
62886
|
+
var mediaSourceRefreshIntervalSchema = z51.enum(["never", "daily", "weekly", "monthly"]);
|
|
62887
|
+
var mediaSourceSyncStatusSchema = z51.enum(["idle", "fetching", "processing", "error"]);
|
|
62888
|
+
var mediaSourceHalfSchema = z51.object({
|
|
62889
|
+
sourceId: z51.string(),
|
|
62890
|
+
syncStatus: mediaSourceSyncStatusSchema,
|
|
62891
|
+
storedCount: z51.number().optional(),
|
|
62892
|
+
pendingItems: z51.number().optional(),
|
|
62893
|
+
failedItems: z51.number().optional(),
|
|
62894
|
+
lastSyncedAt: z51.number().optional(),
|
|
62895
|
+
errorMessage: z51.string().optional()
|
|
62896
|
+
});
|
|
62897
|
+
var mediaSourceSummarySchema = z51.object({
|
|
62898
|
+
key: z51.string(),
|
|
62899
|
+
platform: mediaSourcePlatformSchema,
|
|
62900
|
+
platformLabel: z51.string(),
|
|
62901
|
+
handle: z51.string(),
|
|
62902
|
+
label: z51.string(),
|
|
62903
|
+
profileUrl: z51.string(),
|
|
62904
|
+
profileImageUrl: z51.string().optional(),
|
|
62905
|
+
refreshInterval: mediaSourceRefreshIntervalSchema,
|
|
62906
|
+
/** Absent for a platform that feeds no images (YouTube). */
|
|
62907
|
+
images: mediaSourceHalfSchema.optional(),
|
|
62908
|
+
videos: mediaSourceHalfSchema.optional(),
|
|
62909
|
+
createdAt: z51.number()
|
|
62910
|
+
});
|
|
62911
|
+
var mediaSourceProfileSchema = z51.object({
|
|
62912
|
+
platform: mediaSourcePlatformSchema,
|
|
62913
|
+
handle: z51.string(),
|
|
62914
|
+
displayName: z51.string(),
|
|
62915
|
+
avatarUrl: z51.string(),
|
|
62916
|
+
bio: z51.string(),
|
|
62917
|
+
followers: z51.number().optional(),
|
|
62918
|
+
postCount: z51.number().optional(),
|
|
62919
|
+
isPrivate: z51.boolean(),
|
|
62920
|
+
profileUrl: z51.string(),
|
|
62921
|
+
channelId: z51.string().optional()
|
|
62922
|
+
});
|
|
62923
|
+
var mediaSourcesAddRequestSchema = z51.object({
|
|
62924
|
+
/** A profile URL or a Drive folder link, or an @handle together with `platform`. */
|
|
62925
|
+
input: z51.string().trim().min(1, "Pass the account's profile URL or @handle"),
|
|
62926
|
+
/** Needed only when `input` is a bare handle; a URL names its own platform. */
|
|
62927
|
+
platform: mediaSourcePlatformSchema.optional(),
|
|
62928
|
+
/** Auto-sync cadence. Omitted = weekly, for every platform. */
|
|
62929
|
+
every: mediaSourceRefreshIntervalSchema.optional()
|
|
62930
|
+
});
|
|
62931
|
+
var mediaSourceKeySchema = z51.string().trim().regex(/^(instagram|tiktok|youtube|linkedin|facebook|google_drive):.+$/, "Pass a source key like tiktok:nike");
|
|
62932
|
+
var mediaSourcesSyncRequestSchema = z51.object({ key: mediaSourceKeySchema });
|
|
62933
|
+
var mediaSourcesRemoveRequestSchema = z51.object({ key: mediaSourceKeySchema });
|
|
62934
|
+
var mediaSourcesScheduleRequestSchema = z51.object({
|
|
62935
|
+
key: mediaSourceKeySchema,
|
|
62936
|
+
every: mediaSourceRefreshIntervalSchema
|
|
62937
|
+
});
|
|
62938
|
+
|
|
62939
|
+
// src/commands/media-sources/add.ts
|
|
62940
|
+
import { defineCommand as defineCommand184 } from "citty";
|
|
62941
|
+
|
|
62942
|
+
// src/commands/media-sources/shared.ts
|
|
62943
|
+
function driveRefusalFix(input, code) {
|
|
62944
|
+
if (!/drive\.google\.com/i.test(input) || code !== "BAD_REQUEST") return void 0;
|
|
62945
|
+
return `A Google Drive folder is never added by link \u2014 don't retry. Call request_connection with platform "google-drive" and choose "media-folder": the card lets the user pick the folder in the chat (only the Baker team can for now; anyone else is told the team will set it up). A connected result carries the new source's mediaSourceKey; if it is declined, carry on with the rest of the task.`;
|
|
62946
|
+
}
|
|
62947
|
+
function reportError2(err, input) {
|
|
62948
|
+
if (err instanceof ApiError) {
|
|
62949
|
+
const fix = input ? driveRefusalFix(input, err.code) : void 0;
|
|
62950
|
+
writeJson({ ok: false, error: { code: err.code, message: err.message, ...fix ? { fix } : {} } });
|
|
62951
|
+
process.exit(1);
|
|
62952
|
+
}
|
|
62953
|
+
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
62954
|
+
process.exit(1);
|
|
62955
|
+
}
|
|
62956
|
+
function halfState(half) {
|
|
62957
|
+
if (!half) return null;
|
|
62958
|
+
return {
|
|
62959
|
+
status: half.syncStatus === "fetching" || half.syncStatus === "processing" ? "importing" : half.syncStatus,
|
|
62960
|
+
stored: half.storedCount ?? 0,
|
|
62961
|
+
...half.pendingItems ? { pending: half.pendingItems } : {},
|
|
62962
|
+
...half.failedItems ? { failed: half.failedItems } : {},
|
|
62963
|
+
...half.lastSyncedAt ? { lastSyncedAt: new Date(half.lastSyncedAt).toISOString() } : {},
|
|
62964
|
+
...half.errorMessage ? { error: half.errorMessage } : {}
|
|
62965
|
+
};
|
|
62966
|
+
}
|
|
62967
|
+
function compactSource(source) {
|
|
62968
|
+
return {
|
|
62969
|
+
key: source.key,
|
|
62970
|
+
platform: source.platform,
|
|
62971
|
+
label: source.label,
|
|
62972
|
+
url: source.profileUrl,
|
|
62973
|
+
autoSync: source.refreshInterval,
|
|
62974
|
+
images: halfState(source.images),
|
|
62975
|
+
videos: halfState(source.videos)
|
|
62976
|
+
};
|
|
62977
|
+
}
|
|
62978
|
+
function isImporting(source) {
|
|
62979
|
+
return [source.images, source.videos].some(
|
|
62980
|
+
(half) => half?.syncStatus === "fetching" || half?.syncStatus === "processing"
|
|
62981
|
+
);
|
|
62982
|
+
}
|
|
62983
|
+
|
|
62984
|
+
// src/commands/media-sources/add.ts
|
|
62985
|
+
registerSchema({
|
|
62986
|
+
command: "media-sources.add",
|
|
62987
|
+
description: "Connect a public social account as a source for the image and video libraries \u2014 Instagram, TikTok, YouTube (videos only), LinkedIn company pages, Facebook pages. Its recent posts (up to a year back) are imported. A Google Drive folder is not added here: ask for it with request_connection (platform google-drive, choose media-folder) and the user picks it in the chat. Everything is described and made searchable in the background. Applies immediately and shows on the chat as an already-applied change. Adding a source that is already connected is a no-op.",
|
|
62988
|
+
args: {
|
|
62989
|
+
input: {
|
|
62990
|
+
type: "string",
|
|
62991
|
+
description: "Profile URL (names its own platform), or @handle together with --platform",
|
|
62992
|
+
required: true
|
|
62993
|
+
},
|
|
62994
|
+
platform: {
|
|
62995
|
+
type: "string",
|
|
62996
|
+
description: `Needed only for a bare handle: ${mediaSourcePlatformSchema.options.join("|")}`,
|
|
62997
|
+
required: false
|
|
62998
|
+
},
|
|
62999
|
+
every: {
|
|
63000
|
+
type: "string",
|
|
63001
|
+
description: `Auto-sync cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (default weekly for every source)`,
|
|
63002
|
+
required: false
|
|
63003
|
+
}
|
|
63004
|
+
}
|
|
63005
|
+
});
|
|
63006
|
+
var addCommand3 = defineCommand184({
|
|
63007
|
+
meta: {
|
|
63008
|
+
name: "add",
|
|
63009
|
+
description: "Connect a social account (Instagram, TikTok, YouTube, LinkedIn page, Facebook page) as a media source. Start here with the profile URL. A Google Drive folder is never added by link: call request_connection with platform google-drive and choose media-folder, and the user picks the folder in the chat.\n\nExamples:\n baker media-sources add https://www.tiktok.com/@acme\n baker media-sources add @acme --platform instagram --every daily"
|
|
63010
|
+
},
|
|
63011
|
+
args: {
|
|
63012
|
+
input: { type: "positional", description: "Profile URL or @handle", required: true },
|
|
63013
|
+
platform: {
|
|
63014
|
+
type: "string",
|
|
63015
|
+
description: "instagram|tiktok|youtube|linkedin|facebook \u2014 only for a bare handle",
|
|
63016
|
+
required: false
|
|
63017
|
+
},
|
|
63018
|
+
every: { type: "string", description: "Auto-sync: never|daily|weekly|monthly", required: false }
|
|
63019
|
+
},
|
|
63020
|
+
run: async ({ args: args5 }) => {
|
|
63021
|
+
const parsed = mediaSourcesAddRequestSchema.safeParse({
|
|
63022
|
+
input: String(args5.input ?? ""),
|
|
63023
|
+
platform: args5.platform ? String(args5.platform).toLowerCase() : void 0,
|
|
63024
|
+
every: args5.every ? String(args5.every).toLowerCase() : void 0
|
|
63025
|
+
});
|
|
63026
|
+
if (!parsed.success) {
|
|
63027
|
+
const issue = parsed.error.issues[0];
|
|
63028
|
+
writeJson({
|
|
63029
|
+
ok: false,
|
|
63030
|
+
error: {
|
|
63031
|
+
code: "VALIDATION_ERROR",
|
|
63032
|
+
message: issue ? `${issue.path.join(".") || "input"}: ${issue.message}` : "Invalid request"
|
|
63033
|
+
}
|
|
63034
|
+
});
|
|
63035
|
+
process.exit(1);
|
|
63036
|
+
}
|
|
63037
|
+
try {
|
|
63038
|
+
const data = await apiPost("/api/media-sources/add", parsed.data, {
|
|
63039
|
+
timeoutMs: 12e4
|
|
63040
|
+
});
|
|
63041
|
+
const hints2 = [
|
|
63042
|
+
data.created ? `Connected ${data.source.label} on ${data.source.platformLabel}. Its posts are importing in the background \u2014 they become searchable with \`baker images search\` / \`baker videos search\` as each one is analysed. Check progress with \`baker media-sources list\`.` : `${data.source.label} on ${data.source.platformLabel} was already connected; a fresh import was started if one wasn't running.`
|
|
63043
|
+
];
|
|
63044
|
+
if (data.source.platform === "youtube") {
|
|
63045
|
+
hints2.push(
|
|
63046
|
+
"YouTube feeds the video library only, newest first, a batch per sync; videos over 20 minutes are skipped."
|
|
63047
|
+
);
|
|
63048
|
+
}
|
|
63049
|
+
if (data.source.refreshInterval === "never") {
|
|
63050
|
+
hints2.push(
|
|
63051
|
+
`Auto-sync is off. If the user wants new posts to keep arriving: \`baker media-sources schedule ${data.source.key} --every weekly\`.`
|
|
63052
|
+
);
|
|
63053
|
+
}
|
|
63054
|
+
writeJson({
|
|
63055
|
+
ok: true,
|
|
63056
|
+
data: { created: data.created, source: compactSource(data.source), name: data.profile.displayName },
|
|
63057
|
+
hints: hints2
|
|
63058
|
+
});
|
|
63059
|
+
} catch (err) {
|
|
63060
|
+
reportError2(err, parsed.data.input);
|
|
63061
|
+
}
|
|
63062
|
+
}
|
|
63063
|
+
});
|
|
63064
|
+
|
|
63065
|
+
// src/commands/media-sources/list.ts
|
|
63066
|
+
import { defineCommand as defineCommand185 } from "citty";
|
|
63067
|
+
registerSchema({
|
|
63068
|
+
command: "media-sources.list",
|
|
63069
|
+
description: "List the social accounts connected as image/video sources, with each one's key, import status and how many images and videos it has brought in.",
|
|
63070
|
+
args: {}
|
|
63071
|
+
});
|
|
63072
|
+
var listCommand17 = defineCommand185({
|
|
63073
|
+
meta: {
|
|
63074
|
+
name: "list",
|
|
63075
|
+
description: "List connected media sources (key, platform, import status, stored images/videos).\n\nExample: baker media-sources list"
|
|
63076
|
+
},
|
|
63077
|
+
args: {},
|
|
63078
|
+
run: async () => {
|
|
63079
|
+
try {
|
|
63080
|
+
const { sources } = await apiGet("/api/media-sources/list");
|
|
63081
|
+
const hints2 = [];
|
|
63082
|
+
if (sources.length === 0) {
|
|
63083
|
+
hints2.push(
|
|
63084
|
+
"No sources connected. Connect the brand's own accounts with `baker media-sources add <profile URL>` to fill the image and video libraries."
|
|
63085
|
+
);
|
|
63086
|
+
} else if (sources.some(isImporting)) {
|
|
63087
|
+
hints2.push("Some sources are still importing \u2014 their counts will grow over the next minutes.");
|
|
63088
|
+
}
|
|
63089
|
+
writeJson({ ok: true, data: sources.map(compactSource), hints: hints2.length > 0 ? hints2 : void 0 });
|
|
63090
|
+
} catch (err) {
|
|
63091
|
+
reportError2(err);
|
|
63092
|
+
}
|
|
63093
|
+
}
|
|
63094
|
+
});
|
|
63095
|
+
|
|
63096
|
+
// src/commands/media-sources/remove.ts
|
|
63097
|
+
import { defineCommand as defineCommand186 } from "citty";
|
|
63098
|
+
registerSchema({
|
|
63099
|
+
command: "media-sources.remove",
|
|
63100
|
+
description: "Disconnect a media source. Stops future imports; images and videos it already brought in stay in the library. Applies immediately.",
|
|
63101
|
+
args: { key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true } }
|
|
63102
|
+
});
|
|
63103
|
+
var removeCommand6 = defineCommand186({
|
|
63104
|
+
meta: {
|
|
63105
|
+
name: "remove",
|
|
63106
|
+
description: "Disconnect a media source (already-imported media stays).\n\nExample: baker media-sources remove tiktok:acme"
|
|
63107
|
+
},
|
|
63108
|
+
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
63109
|
+
run: async ({ args: args5 }) => {
|
|
63110
|
+
const parsed = mediaSourcesRemoveRequestSchema.safeParse({ key: String(args5.key ?? "") });
|
|
63111
|
+
if (!parsed.success) {
|
|
63112
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
63113
|
+
process.exit(1);
|
|
63114
|
+
}
|
|
63115
|
+
try {
|
|
63116
|
+
const data = await apiPost("/api/media-sources/remove", parsed.data);
|
|
63117
|
+
writeJson({ ok: true, data });
|
|
63118
|
+
} catch (err) {
|
|
63119
|
+
reportError2(err);
|
|
63120
|
+
}
|
|
63121
|
+
}
|
|
63122
|
+
});
|
|
63123
|
+
|
|
63124
|
+
// src/commands/media-sources/schedule.ts
|
|
63125
|
+
import { defineCommand as defineCommand187 } from "citty";
|
|
63126
|
+
registerSchema({
|
|
63127
|
+
command: "media-sources.schedule",
|
|
63128
|
+
description: "Set how often a connected source imports new posts on its own.",
|
|
63129
|
+
args: {
|
|
63130
|
+
key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true },
|
|
63131
|
+
every: {
|
|
63132
|
+
type: "string",
|
|
63133
|
+
description: `Cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (never = only on demand)`,
|
|
63134
|
+
required: true
|
|
63135
|
+
}
|
|
63136
|
+
}
|
|
63137
|
+
});
|
|
63138
|
+
var scheduleCommand = defineCommand187({
|
|
63139
|
+
meta: {
|
|
63140
|
+
name: "schedule",
|
|
63141
|
+
description: "Set a source's auto-sync cadence.\n\nExample: baker media-sources schedule tiktok:acme --every weekly"
|
|
63142
|
+
},
|
|
63143
|
+
args: {
|
|
63144
|
+
key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true },
|
|
63145
|
+
every: { type: "string", description: "never|daily|weekly|monthly", required: true }
|
|
63146
|
+
},
|
|
63147
|
+
run: async ({ args: args5 }) => {
|
|
63148
|
+
const parsed = mediaSourcesScheduleRequestSchema.safeParse({
|
|
63149
|
+
key: String(args5.key ?? ""),
|
|
63150
|
+
every: String(args5.every ?? "").toLowerCase()
|
|
63151
|
+
});
|
|
63152
|
+
if (!parsed.success) {
|
|
63153
|
+
const issue = parsed.error.issues[0];
|
|
63154
|
+
writeJson({
|
|
63155
|
+
ok: false,
|
|
63156
|
+
error: { code: "VALIDATION_ERROR", message: issue ? `${issue.path.join(".")}: ${issue.message}` : "" }
|
|
63157
|
+
});
|
|
63158
|
+
process.exit(1);
|
|
63159
|
+
}
|
|
63160
|
+
try {
|
|
63161
|
+
const data = await apiPost("/api/media-sources/schedule", parsed.data);
|
|
63162
|
+
writeJson({ ok: true, data: { ...data, autoSync: parsed.data.every } });
|
|
63163
|
+
} catch (err) {
|
|
63164
|
+
reportError2(err);
|
|
63165
|
+
}
|
|
63166
|
+
}
|
|
63167
|
+
});
|
|
63168
|
+
|
|
63169
|
+
// src/commands/media-sources/sync.ts
|
|
63170
|
+
import { defineCommand as defineCommand188 } from "citty";
|
|
63171
|
+
registerSchema({
|
|
63172
|
+
command: "media-sources.sync",
|
|
63173
|
+
description: "Import a connected source's new posts now. Runs in the background; only posts not yet in the library are fetched.",
|
|
63174
|
+
args: {
|
|
63175
|
+
key: { type: "string", description: "Source key from `media-sources list`, e.g. tiktok:acme", required: true }
|
|
63176
|
+
}
|
|
63177
|
+
});
|
|
63178
|
+
var syncCommand = defineCommand188({
|
|
63179
|
+
meta: {
|
|
63180
|
+
name: "sync",
|
|
63181
|
+
description: "Import a source's new posts now.\n\nExample: baker media-sources sync tiktok:acme"
|
|
63182
|
+
},
|
|
63183
|
+
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
63184
|
+
run: async ({ args: args5 }) => {
|
|
63185
|
+
const parsed = mediaSourcesSyncRequestSchema.safeParse({ key: String(args5.key ?? "") });
|
|
63186
|
+
if (!parsed.success) {
|
|
63187
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
63188
|
+
process.exit(1);
|
|
63189
|
+
}
|
|
63190
|
+
try {
|
|
63191
|
+
const data = await apiPost("/api/media-sources/sync", parsed.data);
|
|
63192
|
+
writeJson({
|
|
63193
|
+
ok: true,
|
|
63194
|
+
data,
|
|
63195
|
+
hints: data.started ? void 0 : ["An import was already running for this source; nothing new was started."]
|
|
63196
|
+
});
|
|
63197
|
+
} catch (err) {
|
|
63198
|
+
reportError2(err);
|
|
63199
|
+
}
|
|
63200
|
+
}
|
|
63201
|
+
});
|
|
63202
|
+
|
|
63203
|
+
// src/commands/media-sources/index.ts
|
|
63204
|
+
var mediaSourcesCommand = defineCommand189({
|
|
63205
|
+
meta: {
|
|
63206
|
+
name: "media-sources",
|
|
63207
|
+
description: `Connect social accounts whose images and videos fill the libraries: Instagram, TikTok, YouTube (videos), LinkedIn company pages, Facebook pages. A Google Drive folder is picked by the user in the chat (request_connection, platform google-drive, choose media-folder), never added here; once connected, list, sync, schedule and remove manage it like any source. Subcommands: add, list, sync, schedule, remove.
|
|
63208
|
+
|
|
63209
|
+
Examples:
|
|
63210
|
+
baker media-sources add https://www.tiktok.com/@acme
|
|
63211
|
+
baker media-sources add @acme --platform instagram --every daily
|
|
63212
|
+
baker media-sources list
|
|
63213
|
+
baker media-sources sync youtube:acme
|
|
63214
|
+
baker media-sources schedule linkedin:acme --every monthly
|
|
63215
|
+
baker media-sources remove facebook:acme
|
|
63216
|
+
Full guide: __tooling__/docs/tools/baker/media-sources.md`
|
|
63217
|
+
},
|
|
63218
|
+
subCommands: {
|
|
63219
|
+
add: addCommand3,
|
|
63220
|
+
list: listCommand17,
|
|
63221
|
+
sync: syncCommand,
|
|
63222
|
+
schedule: scheduleCommand,
|
|
63223
|
+
remove: removeCommand6
|
|
63224
|
+
}
|
|
63225
|
+
});
|
|
63226
|
+
|
|
62972
63227
|
// src/commands/research/index.ts
|
|
62973
|
-
import { defineCommand as
|
|
63228
|
+
import { defineCommand as defineCommand202 } from "citty";
|
|
62974
63229
|
|
|
62975
63230
|
// src/commands/research/advertisers.ts
|
|
62976
|
-
import { defineCommand as
|
|
63231
|
+
import { defineCommand as defineCommand190 } from "citty";
|
|
62977
63232
|
|
|
62978
63233
|
// src/commands/research/hints.ts
|
|
62979
63234
|
var AD_COPY_ROUTE = 'This returns competing domains and their SERP economics \u2014 no ad copy, no headlines, no creative. For the actual copy of a competitor\'s ads: `baker winning-ads advertisers "<brand>"` \u2192 `baker winning-ads search "<brief>" --advertiser-id <id>` \u2192 `baker winning-ads content <adId>` (`primary_text` / `headline` / `cta`, plus the spoken transcript and on-screen text for video). That corpus is Meta and LinkedIn only \u2014 Google SERP ad copy is not available through any Baker command, so do not keep querying for it here.';
|
|
@@ -63175,7 +63430,7 @@ var FIELDS3 = {
|
|
|
63175
63430
|
etv: "Estimated traffic value (USD)",
|
|
63176
63431
|
visibility: "SERP visibility score (0-1)"
|
|
63177
63432
|
};
|
|
63178
|
-
var advertisersCommand =
|
|
63433
|
+
var advertisersCommand = defineCommand190({
|
|
63179
63434
|
meta: {
|
|
63180
63435
|
name: "advertisers",
|
|
63181
63436
|
description: `Domains competing for a keyword in Google SERPs, with position, relevance, traffic value and visibility. Returns NO ad copy \u2014 for a competitor's headlines and body copy use \`baker winning-ads content <adId>\` (Meta/LinkedIn only).
|
|
@@ -63231,7 +63486,7 @@ Examples:
|
|
|
63231
63486
|
});
|
|
63232
63487
|
|
|
63233
63488
|
// src/commands/research/autocomplete.ts
|
|
63234
|
-
import { defineCommand as
|
|
63489
|
+
import { defineCommand as defineCommand191 } from "citty";
|
|
63235
63490
|
registerSchema({
|
|
63236
63491
|
command: "research.autocomplete",
|
|
63237
63492
|
description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. If --location and --language are omitted, defaults to United States (us) and English (en).",
|
|
@@ -63254,7 +63509,7 @@ registerSchema({
|
|
|
63254
63509
|
var FIELDS4 = {
|
|
63255
63510
|
suggestion: "Autocomplete suggestion from Google"
|
|
63256
63511
|
};
|
|
63257
|
-
var autocompleteCommand =
|
|
63512
|
+
var autocompleteCommand = defineCommand191({
|
|
63258
63513
|
meta: {
|
|
63259
63514
|
name: "autocomplete",
|
|
63260
63515
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -63309,7 +63564,7 @@ Examples:
|
|
|
63309
63564
|
});
|
|
63310
63565
|
|
|
63311
63566
|
// src/commands/research/countries.ts
|
|
63312
|
-
import { defineCommand as
|
|
63567
|
+
import { defineCommand as defineCommand192 } from "citty";
|
|
63313
63568
|
registerSchema({
|
|
63314
63569
|
command: "research.countries",
|
|
63315
63570
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -63366,7 +63621,7 @@ var FIELDS5 = {
|
|
|
63366
63621
|
code: "Country code to pass as --location",
|
|
63367
63622
|
name: "Country name"
|
|
63368
63623
|
};
|
|
63369
|
-
var countriesCommand =
|
|
63624
|
+
var countriesCommand = defineCommand192({
|
|
63370
63625
|
meta: {
|
|
63371
63626
|
name: "countries",
|
|
63372
63627
|
description: "List all supported country codes for --location flag."
|
|
@@ -63377,7 +63632,7 @@ var countriesCommand = defineCommand186({
|
|
|
63377
63632
|
});
|
|
63378
63633
|
|
|
63379
63634
|
// src/commands/research/fetch.ts
|
|
63380
|
-
import { defineCommand as
|
|
63635
|
+
import { defineCommand as defineCommand193 } from "citty";
|
|
63381
63636
|
var CONTENT_PREVIEW_CHARS = 2e4;
|
|
63382
63637
|
var TIMEOUT_MS = 18e4;
|
|
63383
63638
|
registerSchema({
|
|
@@ -63450,7 +63705,7 @@ function fetchFix(code) {
|
|
|
63450
63705
|
explanation: "This read failed. Don't build a retry ladder around it \u2014 finish the rest of the job with what you can reach and name this page as a gap."
|
|
63451
63706
|
};
|
|
63452
63707
|
}
|
|
63453
|
-
var fetchCommand =
|
|
63708
|
+
var fetchCommand = defineCommand193({
|
|
63454
63709
|
meta: {
|
|
63455
63710
|
name: "fetch",
|
|
63456
63711
|
description: `Read a page an ordinary web fetch could not. Bot walls and JavaScript-rendered pages are resolved for you \u2014 you never have to retry, wait, or drive a browser yourself.
|
|
@@ -63527,7 +63782,7 @@ Examples:
|
|
|
63527
63782
|
});
|
|
63528
63783
|
|
|
63529
63784
|
// src/commands/research/intent.ts
|
|
63530
|
-
import { defineCommand as
|
|
63785
|
+
import { defineCommand as defineCommand194 } from "citty";
|
|
63531
63786
|
registerSchema({
|
|
63532
63787
|
command: "research.intent",
|
|
63533
63788
|
description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
|
|
@@ -63550,7 +63805,7 @@ var FIELDS7 = {
|
|
|
63550
63805
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
63551
63806
|
probability: "Confidence score 0.0-1.0"
|
|
63552
63807
|
};
|
|
63553
|
-
var intentCommand =
|
|
63808
|
+
var intentCommand = defineCommand194({
|
|
63554
63809
|
meta: {
|
|
63555
63810
|
name: "intent",
|
|
63556
63811
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -63598,7 +63853,7 @@ Examples:
|
|
|
63598
63853
|
});
|
|
63599
63854
|
|
|
63600
63855
|
// src/commands/research/keyword-gap.ts
|
|
63601
|
-
import { defineCommand as
|
|
63856
|
+
import { defineCommand as defineCommand195 } from "citty";
|
|
63602
63857
|
registerSchema({
|
|
63603
63858
|
command: "research.keyword-gap",
|
|
63604
63859
|
description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
|
|
@@ -63627,7 +63882,7 @@ var FIELDS8 = {
|
|
|
63627
63882
|
cpc: "Cost per click USD",
|
|
63628
63883
|
their_position: "Competitor's ranking position"
|
|
63629
63884
|
};
|
|
63630
|
-
var keywordGapCommand =
|
|
63885
|
+
var keywordGapCommand = defineCommand195({
|
|
63631
63886
|
meta: {
|
|
63632
63887
|
name: "keyword-gap",
|
|
63633
63888
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -63702,7 +63957,7 @@ Examples:
|
|
|
63702
63957
|
});
|
|
63703
63958
|
|
|
63704
63959
|
// src/commands/research/keyword-metrics.ts
|
|
63705
|
-
import { defineCommand as
|
|
63960
|
+
import { defineCommand as defineCommand196 } from "citty";
|
|
63706
63961
|
|
|
63707
63962
|
// src/commands/research/keyword-metrics-rows.ts
|
|
63708
63963
|
var KEYWORD_METRICS_SOURCE = "keyword_planner_estimate_via_dataforseo";
|
|
@@ -63782,7 +64037,7 @@ registerSchema({
|
|
|
63782
64037
|
"no-cache": { type: "boolean", description: "Skip server cache, hit API directly", required: false }
|
|
63783
64038
|
}
|
|
63784
64039
|
});
|
|
63785
|
-
var keywordMetricsCommand =
|
|
64040
|
+
var keywordMetricsCommand = defineCommand196({
|
|
63786
64041
|
meta: {
|
|
63787
64042
|
name: "keyword-metrics",
|
|
63788
64043
|
description: `Volume, CPC and competition for keywords you name. No domain required.
|
|
@@ -63864,7 +64119,7 @@ Examples:
|
|
|
63864
64119
|
});
|
|
63865
64120
|
|
|
63866
64121
|
// src/commands/research/keywords-for-site.ts
|
|
63867
|
-
import { defineCommand as
|
|
64122
|
+
import { defineCommand as defineCommand197 } from "citty";
|
|
63868
64123
|
registerSchema({
|
|
63869
64124
|
command: "research.keywords-for-site",
|
|
63870
64125
|
description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
|
|
@@ -63897,7 +64152,7 @@ var FIELDS9 = {
|
|
|
63897
64152
|
competition: "LOW, MEDIUM, or HIGH",
|
|
63898
64153
|
competition_index: "Competition score 0-100"
|
|
63899
64154
|
};
|
|
63900
|
-
var keywordsForSiteCommand =
|
|
64155
|
+
var keywordsForSiteCommand = defineCommand197({
|
|
63901
64156
|
meta: {
|
|
63902
64157
|
name: "keywords-for-site",
|
|
63903
64158
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -63959,7 +64214,7 @@ Examples:
|
|
|
63959
64214
|
});
|
|
63960
64215
|
|
|
63961
64216
|
// src/commands/research/languages.ts
|
|
63962
|
-
import { defineCommand as
|
|
64217
|
+
import { defineCommand as defineCommand198 } from "citty";
|
|
63963
64218
|
registerSchema({
|
|
63964
64219
|
command: "research.languages",
|
|
63965
64220
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -63989,7 +64244,7 @@ var FIELDS10 = {
|
|
|
63989
64244
|
code: "Language code to pass as --language",
|
|
63990
64245
|
name: "Language name (also accepted by --language)"
|
|
63991
64246
|
};
|
|
63992
|
-
var languagesCommand2 =
|
|
64247
|
+
var languagesCommand2 = defineCommand198({
|
|
63993
64248
|
meta: {
|
|
63994
64249
|
name: "languages",
|
|
63995
64250
|
description: "List all supported language codes for --language flag."
|
|
@@ -64000,7 +64255,7 @@ var languagesCommand2 = defineCommand192({
|
|
|
64000
64255
|
});
|
|
64001
64256
|
|
|
64002
64257
|
// src/commands/research/lighthouse.ts
|
|
64003
|
-
import { defineCommand as
|
|
64258
|
+
import { defineCommand as defineCommand199 } from "citty";
|
|
64004
64259
|
registerSchema({
|
|
64005
64260
|
command: "research.lighthouse",
|
|
64006
64261
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -64019,7 +64274,7 @@ var FIELDS11 = {
|
|
|
64019
64274
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
64020
64275
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
64021
64276
|
};
|
|
64022
|
-
var lighthouseCommand =
|
|
64277
|
+
var lighthouseCommand = defineCommand199({
|
|
64023
64278
|
meta: {
|
|
64024
64279
|
name: "lighthouse",
|
|
64025
64280
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -64057,7 +64312,7 @@ Examples:
|
|
|
64057
64312
|
});
|
|
64058
64313
|
|
|
64059
64314
|
// src/commands/research/relevant-pages.ts
|
|
64060
|
-
import { defineCommand as
|
|
64315
|
+
import { defineCommand as defineCommand200 } from "citty";
|
|
64061
64316
|
registerSchema({
|
|
64062
64317
|
command: "research.relevant-pages",
|
|
64063
64318
|
description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. If --location and --language are omitted, defaults to United States (us) and English (en).",
|
|
@@ -64083,7 +64338,7 @@ var FIELDS12 = {
|
|
|
64083
64338
|
keywords: "Total organic keywords the page ranks for",
|
|
64084
64339
|
top_10: "Keywords in positions 1-10"
|
|
64085
64340
|
};
|
|
64086
|
-
var relevantPagesCommand =
|
|
64341
|
+
var relevantPagesCommand = defineCommand200({
|
|
64087
64342
|
meta: {
|
|
64088
64343
|
name: "relevant-pages",
|
|
64089
64344
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -64130,7 +64385,7 @@ Examples:
|
|
|
64130
64385
|
});
|
|
64131
64386
|
|
|
64132
64387
|
// src/commands/research/web.ts
|
|
64133
|
-
import { defineCommand as
|
|
64388
|
+
import { defineCommand as defineCommand201 } from "citty";
|
|
64134
64389
|
registerSchema({
|
|
64135
64390
|
command: "research.web",
|
|
64136
64391
|
description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
|
|
@@ -64181,7 +64436,7 @@ async function runDeepResearch(question) {
|
|
|
64181
64436
|
}
|
|
64182
64437
|
throw new Error("Deep research timed out");
|
|
64183
64438
|
}
|
|
64184
|
-
var webCommand =
|
|
64439
|
+
var webCommand = defineCommand201({
|
|
64185
64440
|
meta: {
|
|
64186
64441
|
name: "web",
|
|
64187
64442
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -64243,7 +64498,7 @@ Examples:
|
|
|
64243
64498
|
});
|
|
64244
64499
|
|
|
64245
64500
|
// src/commands/research/index.ts
|
|
64246
|
-
var researchCommand =
|
|
64501
|
+
var researchCommand = defineCommand202({
|
|
64247
64502
|
meta: {
|
|
64248
64503
|
name: "research",
|
|
64249
64504
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -64290,10 +64545,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
|
|
|
64290
64545
|
});
|
|
64291
64546
|
|
|
64292
64547
|
// src/commands/scheduled-agents/index.ts
|
|
64293
|
-
import { defineCommand as
|
|
64548
|
+
import { defineCommand as defineCommand213 } from "citty";
|
|
64294
64549
|
|
|
64295
64550
|
// src/commands/scheduled-agents/create.ts
|
|
64296
|
-
import { defineCommand as
|
|
64551
|
+
import { defineCommand as defineCommand203 } from "citty";
|
|
64297
64552
|
|
|
64298
64553
|
// src/commands/scheduled-agents/shared.ts
|
|
64299
64554
|
var TEMP_SCHEDULED_AGENT_PREFIX = "temp_agent_";
|
|
@@ -64660,7 +64915,7 @@ registerSchema({
|
|
|
64660
64915
|
}
|
|
64661
64916
|
}
|
|
64662
64917
|
});
|
|
64663
|
-
var createCommand3 =
|
|
64918
|
+
var createCommand3 = defineCommand203({
|
|
64664
64919
|
meta: {
|
|
64665
64920
|
name: "create",
|
|
64666
64921
|
description: 'Stage a scheduled agent. Examples: baker scheduled-agents create --name "Weekly report" --description "..." --prompt "..." --cron "0 9 * * MON" | baker scheduled-agents create --name "Chase a new lead" --description "..." --prompt "Research {{payload.answers.company}} and draft a reply" --trigger form.submitted --form quote | baker scheduled-agents create --name "Big deals" --description "..." --prompt "..." --trigger webhook.received --when "deal.stage = won AND deal.amount > 10000" --times 3'
|
|
@@ -64717,7 +64972,7 @@ var createCommand3 = defineCommand197({
|
|
|
64717
64972
|
});
|
|
64718
64973
|
|
|
64719
64974
|
// src/commands/scheduled-agents/delete.ts
|
|
64720
|
-
import { defineCommand as
|
|
64975
|
+
import { defineCommand as defineCommand204 } from "citty";
|
|
64721
64976
|
registerSchema({
|
|
64722
64977
|
command: "scheduled-agents.delete",
|
|
64723
64978
|
description: "Stage deletion of a published scheduled agent, or cancel one this chat staged (temp_agent_*).",
|
|
@@ -64725,7 +64980,7 @@ registerSchema({
|
|
|
64725
64980
|
id: { type: "string", description: "Published scheduled agent ID or temp_agent_* draft ID", required: true }
|
|
64726
64981
|
}
|
|
64727
64982
|
});
|
|
64728
|
-
var deleteCommand3 =
|
|
64983
|
+
var deleteCommand3 = defineCommand204({
|
|
64729
64984
|
meta: {
|
|
64730
64985
|
name: "delete",
|
|
64731
64986
|
description: "Stage a scheduled agent deletion. Example: baker scheduled-agents delete <id-or-temp_agent_id>"
|
|
@@ -64754,7 +65009,7 @@ var deleteCommand3 = defineCommand198({
|
|
|
64754
65009
|
});
|
|
64755
65010
|
|
|
64756
65011
|
// src/commands/scheduled-agents/get.ts
|
|
64757
|
-
import { defineCommand as
|
|
65012
|
+
import { defineCommand as defineCommand205 } from "citty";
|
|
64758
65013
|
registerSchema({
|
|
64759
65014
|
command: "scheduled-agents.get",
|
|
64760
65015
|
description: "Get a published scheduled agent, or one this chat has staged (temp_agent_*). A published one comes with runsAs: who each run acts as ({ name, personalTools, companyTools, notSignedIn?, toolsOff? }) \u2014 the tools a run loads, which decides whether a job like reading someone's inbox can work. Its recentRuns and any draftOps this chat staged on it come with it.",
|
|
@@ -64763,7 +65018,7 @@ registerSchema({
|
|
|
64763
65018
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
64764
65019
|
}
|
|
64765
65020
|
});
|
|
64766
|
-
var getCommand4 =
|
|
65021
|
+
var getCommand4 = defineCommand205({
|
|
64767
65022
|
meta: {
|
|
64768
65023
|
name: "get",
|
|
64769
65024
|
description: "Get a scheduled agent. Example: baker scheduled-agents get <id-or-temp_agent_id>"
|
|
@@ -64802,7 +65057,7 @@ var getCommand4 = defineCommand199({
|
|
|
64802
65057
|
});
|
|
64803
65058
|
|
|
64804
65059
|
// src/commands/scheduled-agents/list.ts
|
|
64805
|
-
import { defineCommand as
|
|
65060
|
+
import { defineCommand as defineCommand206 } from "citty";
|
|
64806
65061
|
var FULL_DESCRIPTION = "Return every item and staged change as stored, briefs included (tens of KB). Prefer `get <id>` for one item.";
|
|
64807
65062
|
registerSchema({
|
|
64808
65063
|
command: "scheduled-agents.list",
|
|
@@ -64812,7 +65067,7 @@ registerSchema({
|
|
|
64812
65067
|
full: { type: "boolean", description: FULL_DESCRIPTION, required: false }
|
|
64813
65068
|
}
|
|
64814
65069
|
});
|
|
64815
|
-
var
|
|
65070
|
+
var listCommand18 = defineCommand206({
|
|
64816
65071
|
meta: {
|
|
64817
65072
|
name: "list",
|
|
64818
65073
|
description: "List scheduled agents: id, name, trigger and status for each, plus this chat's staged changes when BAKER_CHAT_ID is set (or --chat <id> for an earlier chat's). Briefs are left out. Start here: baker scheduled-agents list; then baker scheduled-agents get <id> for one item's brief."
|
|
@@ -64838,7 +65093,7 @@ var listCommand17 = defineCommand200({
|
|
|
64838
65093
|
});
|
|
64839
65094
|
|
|
64840
65095
|
// src/commands/scheduled-agents/run.ts
|
|
64841
|
-
import { defineCommand as
|
|
65096
|
+
import { defineCommand as defineCommand207 } from "citty";
|
|
64842
65097
|
registerSchema({
|
|
64843
65098
|
command: "scheduled-agents.run",
|
|
64844
65099
|
description: "Run a published scheduled agent now, whatever its trigger says. Opens a Session immediately and returns its chatId. Does not need BAKER_CHAT_ID, and refuses a temp_agent_* id \u2014 a staged item has to be published before it can run.",
|
|
@@ -64846,7 +65101,7 @@ registerSchema({
|
|
|
64846
65101
|
id: { type: "string", description: "Published scheduled agent ID", required: true }
|
|
64847
65102
|
}
|
|
64848
65103
|
});
|
|
64849
|
-
var runCommand2 =
|
|
65104
|
+
var runCommand2 = defineCommand207({
|
|
64850
65105
|
meta: {
|
|
64851
65106
|
name: "run",
|
|
64852
65107
|
description: "Run a published scheduled agent now. Example: baker scheduled-agents run <id>"
|
|
@@ -64878,7 +65133,7 @@ var runCommand2 = defineCommand201({
|
|
|
64878
65133
|
});
|
|
64879
65134
|
|
|
64880
65135
|
// src/commands/scheduled-agents/targets.ts
|
|
64881
|
-
import { defineCommand as
|
|
65136
|
+
import { defineCommand as defineCommand208 } from "citty";
|
|
64882
65137
|
var ARGS2 = {
|
|
64883
65138
|
trigger: {
|
|
64884
65139
|
type: "string",
|
|
@@ -64912,7 +65167,7 @@ registerSchema({
|
|
|
64912
65167
|
description: "What a trigger can be pointed at: the open Tasks, the company's scheduled agents, its review sources, followed competitors, pages, Forms and their steps, Knowledge collections, tools. Returns each option's value (pass it to the matching flag on create/update) with its name.",
|
|
64913
65168
|
args: ARGS2
|
|
64914
65169
|
});
|
|
64915
|
-
var targetsCommand =
|
|
65170
|
+
var targetsCommand = defineCommand208({
|
|
64916
65171
|
meta: {
|
|
64917
65172
|
name: "targets",
|
|
64918
65173
|
description: `What a trigger can be pointed at \u2014 so "when a Task is picked up" becomes "when THIS Task is picked up".
|
|
@@ -64955,7 +65210,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
64955
65210
|
// src/commands/scheduled-agents/templates.ts
|
|
64956
65211
|
import { readFile as readFile32 } from "fs/promises";
|
|
64957
65212
|
import path46 from "path";
|
|
64958
|
-
import { defineCommand as
|
|
65213
|
+
import { defineCommand as defineCommand209 } from "citty";
|
|
64959
65214
|
registerSchema({
|
|
64960
65215
|
command: "scheduled-agents.templates",
|
|
64961
65216
|
description: "The recipes available to this company: the ones Baker ships plus the ones they wrote themselves, each with its id, what it produces and how often it is meant to run. Read this before proposing a company's automation, so every recipe you name is one that exists. Also how a company gets a recipe of its own \u2014 save a brief, prove it runs, then publish it.",
|
|
@@ -65010,7 +65265,7 @@ registerSchema({
|
|
|
65010
65265
|
}
|
|
65011
65266
|
}
|
|
65012
65267
|
});
|
|
65013
|
-
var templatesCommand =
|
|
65268
|
+
var templatesCommand = defineCommand209({
|
|
65014
65269
|
meta: {
|
|
65015
65270
|
name: "templates",
|
|
65016
65271
|
description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
|
|
@@ -65106,7 +65361,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65106
65361
|
});
|
|
65107
65362
|
|
|
65108
65363
|
// src/commands/scheduled-agents/triggers.ts
|
|
65109
|
-
import { defineCommand as
|
|
65364
|
+
import { defineCommand as defineCommand210 } from "citty";
|
|
65110
65365
|
var ARGS3 = {
|
|
65111
65366
|
trigger: {
|
|
65112
65367
|
type: "string",
|
|
@@ -65192,7 +65447,7 @@ function shapeTriggerCatalog(response, filter) {
|
|
|
65192
65447
|
}
|
|
65193
65448
|
return { ok: true, data: { groups, reacting: catalog.reacting } };
|
|
65194
65449
|
}
|
|
65195
|
-
var triggersCommand2 =
|
|
65450
|
+
var triggersCommand2 = defineCommand210({
|
|
65196
65451
|
meta: {
|
|
65197
65452
|
name: "triggers",
|
|
65198
65453
|
description: `Everything that can start a scheduled agent.
|
|
@@ -65222,7 +65477,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65222
65477
|
});
|
|
65223
65478
|
|
|
65224
65479
|
// src/commands/scheduled-agents/unstage.ts
|
|
65225
|
-
import { defineCommand as
|
|
65480
|
+
import { defineCommand as defineCommand211 } from "citty";
|
|
65226
65481
|
registerSchema({
|
|
65227
65482
|
command: "scheduled-agents.unstage",
|
|
65228
65483
|
description: "Take back what this chat staged on one scheduled agent, before Publish \u2014 the same as discarding its row in the change list. With --index, only that one change (its `index` in `baker scheduled-agents list` \u2192 draft.ops). Taking back a create also takes back the edits staged on it. Never touches a published item: to change or remove one, stage update/delete instead.",
|
|
@@ -65248,7 +65503,7 @@ function unstageBody(args5, chatId) {
|
|
|
65248
65503
|
}
|
|
65249
65504
|
return { chatId, ref: args5.ref, index };
|
|
65250
65505
|
}
|
|
65251
|
-
var unstageCommand =
|
|
65506
|
+
var unstageCommand = defineCommand211({
|
|
65252
65507
|
meta: {
|
|
65253
65508
|
name: "unstage",
|
|
65254
65509
|
description: "Take back what this chat staged on a scheduled agent, before Publish. Examples: baker scheduled-agents unstage temp_agent_abc123 | baker scheduled-agents unstage <id> --index 2"
|
|
@@ -65279,7 +65534,7 @@ var unstageCommand = defineCommand205({
|
|
|
65279
65534
|
});
|
|
65280
65535
|
|
|
65281
65536
|
// src/commands/scheduled-agents/update.ts
|
|
65282
|
-
import { defineCommand as
|
|
65537
|
+
import { defineCommand as defineCommand212 } from "citty";
|
|
65283
65538
|
registerSchema({
|
|
65284
65539
|
command: "scheduled-agents.update",
|
|
65285
65540
|
description: "Stage an update to a published scheduled agent, or to one this chat staged (temp_agent_*).",
|
|
@@ -65306,7 +65561,7 @@ registerSchema({
|
|
|
65306
65561
|
enabled: { type: "string", description: "Replacement enabled state", required: false, enum: ["true", "false"] }
|
|
65307
65562
|
}
|
|
65308
65563
|
});
|
|
65309
|
-
var updateCommand4 =
|
|
65564
|
+
var updateCommand4 = defineCommand212({
|
|
65310
65565
|
meta: {
|
|
65311
65566
|
name: "update",
|
|
65312
65567
|
description: "Stage a scheduled agent update. Examples: baker scheduled-agents update <id> --enabled false | baker scheduled-agents update <id> --trigger form.submitted --form quote"
|
|
@@ -65377,7 +65632,7 @@ var updateCommand4 = defineCommand206({
|
|
|
65377
65632
|
});
|
|
65378
65633
|
|
|
65379
65634
|
// src/commands/scheduled-agents/index.ts
|
|
65380
|
-
var scheduledAgentsCommand =
|
|
65635
|
+
var scheduledAgentsCommand = defineCommand213({
|
|
65381
65636
|
meta: {
|
|
65382
65637
|
name: "scheduled-agents",
|
|
65383
65638
|
description: `Manage Scheduled agents. Subcommands: list, get, triggers, targets, create, update, delete, unstage, run, templates.
|
|
@@ -65406,7 +65661,7 @@ Examples:
|
|
|
65406
65661
|
Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
65407
65662
|
},
|
|
65408
65663
|
subCommands: {
|
|
65409
|
-
list:
|
|
65664
|
+
list: listCommand18,
|
|
65410
65665
|
get: getCommand4,
|
|
65411
65666
|
triggers: triggersCommand2,
|
|
65412
65667
|
targets: targetsCommand,
|
|
@@ -65420,14 +65675,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65420
65675
|
});
|
|
65421
65676
|
|
|
65422
65677
|
// src/commands/schema.ts
|
|
65423
|
-
import { defineCommand as
|
|
65678
|
+
import { defineCommand as defineCommand214 } from "citty";
|
|
65424
65679
|
function narrowToFamily(commandName, available) {
|
|
65425
65680
|
const segments = commandName.split(".");
|
|
65426
65681
|
const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
|
|
65427
65682
|
const siblings = available.filter((name) => name.startsWith(prefix));
|
|
65428
65683
|
return siblings.length > 0 ? siblings : available;
|
|
65429
65684
|
}
|
|
65430
|
-
var schemaCommand2 =
|
|
65685
|
+
var schemaCommand2 = defineCommand214({
|
|
65431
65686
|
meta: {
|
|
65432
65687
|
name: "schema",
|
|
65433
65688
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images search (or images.search)"
|
|
@@ -65472,10 +65727,10 @@ var schemaCommand2 = defineCommand208({
|
|
|
65472
65727
|
});
|
|
65473
65728
|
|
|
65474
65729
|
// src/commands/studio/index.ts
|
|
65475
|
-
import { defineCommand as
|
|
65730
|
+
import { defineCommand as defineCommand223 } from "citty";
|
|
65476
65731
|
|
|
65477
65732
|
// src/commands/studio/animate.ts
|
|
65478
|
-
import { defineCommand as
|
|
65733
|
+
import { defineCommand as defineCommand215 } from "citty";
|
|
65479
65734
|
|
|
65480
65735
|
// src/commands/studio/spokenPace.ts
|
|
65481
65736
|
var WORDS_PER_SECOND3 = SPOKEN_WORDS_PER_SECOND;
|
|
@@ -65701,7 +65956,7 @@ function parseImageRefs(spec) {
|
|
|
65701
65956
|
}
|
|
65702
65957
|
var defaultDeps = {
|
|
65703
65958
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
65704
|
-
upload: (
|
|
65959
|
+
upload: (path49) => uploadLocalImage({ file: path49, contentType: detectImageContentType(path49), source: "uploaded" })
|
|
65705
65960
|
};
|
|
65706
65961
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
65707
65962
|
const refs = parseImageRefs(spec);
|
|
@@ -65721,10 +65976,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
65721
65976
|
}
|
|
65722
65977
|
return { imageIds, added };
|
|
65723
65978
|
}
|
|
65724
|
-
function uploadFailure(
|
|
65979
|
+
function uploadFailure(path49) {
|
|
65725
65980
|
return (error) => {
|
|
65726
65981
|
if (error instanceof ApiError) throw error;
|
|
65727
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
65982
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path49}" as an image.`);
|
|
65728
65983
|
};
|
|
65729
65984
|
}
|
|
65730
65985
|
|
|
@@ -65988,7 +66243,7 @@ async function adByHandHintFor(body) {
|
|
|
65988
66243
|
return null;
|
|
65989
66244
|
}
|
|
65990
66245
|
}
|
|
65991
|
-
var animateCommand =
|
|
66246
|
+
var animateCommand = defineCommand215({
|
|
65992
66247
|
meta: {
|
|
65993
66248
|
name: "animate",
|
|
65994
66249
|
description: "Render a clip. With an image the look is already fixed, so the prompt describes MOVEMENT \u2014 what the camera does, what the subject does, in what order. With --from text there is no image and the prompt is the whole shot.\n\nA rendered clip is NOT usable anywhere until you keep it: `baker studio keep <id> --slot N` is what puts it in the video library. Takes nobody keeps are never ingested, which is what makes a rejected batch cheap.\n\nFor anything longer than 15 seconds, or to build on footage that already exists, use --model bytedance/seedance-2.5: it renders 4-30s and is the only model that reads an existing clip or an existing soundtrack.\n\nExamples:\n baker studio animate 'slow push in, model turns to camera and smiles' --image j57abc123def456ghi789\n baker studio animate 'she looks to camera and says: \"Hola, soy Elena\"' --avatar elena --quality 720p --aspect-ratio 9:16\n baker studio animate 'handheld drift right, steam rising from the cup' --image './out/hero.png' --duration 6 --quality 1080p\n baker studio animate 'product rotates once on a turntable' --image j57abc\u2026,j57def\u2026 --from references\n baker studio animate 'she keeps walking, camera stays with her, then she stops and looks up' --image j57abc\u2026 --from references --from-clip j57batch\u2026:0 --model bytedance/seedance-2.5 --duration 20\n baker studio animate 'hold on the product, then a slow push-in' --from references --from-video j57vid\u2026 --model bytedance/seedance-2.5\n baker studio animate 'slow drone pull-back over a solar farm at golden hour, no people' --from text --model bytedance/seedance-2.5 --duration 12"
|
|
@@ -66113,7 +66368,7 @@ var animateCommand = defineCommand209({
|
|
|
66113
66368
|
});
|
|
66114
66369
|
|
|
66115
66370
|
// src/commands/studio/generate.ts
|
|
66116
|
-
import { defineCommand as
|
|
66371
|
+
import { defineCommand as defineCommand216 } from "citty";
|
|
66117
66372
|
var MODEL_LIST2 = IMAGE_MODEL_IDS;
|
|
66118
66373
|
var DEFAULT_MAX_WAIT_MS2 = 24e4;
|
|
66119
66374
|
registerSchema({
|
|
@@ -66249,7 +66504,7 @@ function buildGenerateBody(args5, prompt) {
|
|
|
66249
66504
|
}
|
|
66250
66505
|
return body;
|
|
66251
66506
|
}
|
|
66252
|
-
var generateCommand =
|
|
66507
|
+
var generateCommand = defineCommand216({
|
|
66253
66508
|
meta: {
|
|
66254
66509
|
name: "generate",
|
|
66255
66510
|
description: "Start here to make an image. Renders 1-8 takes of one brief, ingests each into the media library as it lands, and shows the batch in the dashboard Studio next to the ones the client ran.\n\nModel choice: google/gemini-3.1-flash-image-preview (default \u2014 fast, best at editing a reference and at extreme ratios), google/gemini-3-pro-image-preview (highest fidelity, slower), openai/gpt-image-2 (photoreal and the cleanest in-image text \u2014 no --image-size, no 4:5 / 5:4), recraft/recraft-v4.1-pro-vector (vector/flat marks with palette control).\n\n--reference is the biggest quality lever there is: a real logo, product shot, Pinterest pin or sandbox screenshot beats any amount of adjectives.\n\nExamples:\n baker studio generate 'matte black bottle on wet marble, hard studio light, 35mm' --aspect-ratio 3:2 --count 3\n baker studio generate 'this bottle on a sunlit kitchen counter' --reference './src/brand/product.png,https://\u2026/kitchen.jpg'\n baker studio generate 'founder-style selfie, kitchen background, natural light' --skill ugc-selfie-hook\n baker studio generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
|
|
@@ -66332,7 +66587,7 @@ var generateCommand = defineCommand210({
|
|
|
66332
66587
|
});
|
|
66333
66588
|
|
|
66334
66589
|
// src/commands/studio/get.ts
|
|
66335
|
-
import { defineCommand as
|
|
66590
|
+
import { defineCommand as defineCommand217 } from "citty";
|
|
66336
66591
|
registerSchema({
|
|
66337
66592
|
command: "studio.get",
|
|
66338
66593
|
description: "Read one Studio batch: every take, where it lives, and why a take is missing. This is how you pick up a batch that was still rendering when the start command returned.",
|
|
@@ -66341,7 +66596,7 @@ registerSchema({
|
|
|
66341
66596
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66342
66597
|
}
|
|
66343
66598
|
});
|
|
66344
|
-
var getCommand5 =
|
|
66599
|
+
var getCommand5 = defineCommand217({
|
|
66345
66600
|
meta: {
|
|
66346
66601
|
name: "get",
|
|
66347
66602
|
description: "Read one Studio batch \u2014 the takes, their urls, whether each is in the library, and the reason for any that failed.\n\nExample: baker studio get j57abc123def456ghi789\nExample: baker studio get j57abc123def456ghi789 --full"
|
|
@@ -66370,7 +66625,7 @@ var getCommand5 = defineCommand211({
|
|
|
66370
66625
|
});
|
|
66371
66626
|
|
|
66372
66627
|
// src/commands/studio/improve.ts
|
|
66373
|
-
import { defineCommand as
|
|
66628
|
+
import { defineCommand as defineCommand218 } from "citty";
|
|
66374
66629
|
var DESCRIPTION2 = "Sharpen a rough brief into directed art direction \u2014 the same rewrite the client gets from the wand in the Studio prompt bar. Reach for it when you are relaying the CLIENT's own words and want them shaped without substituting your voice; when you are writing the art direction yourself, just write it, because you will do a better job than this does.";
|
|
66375
66630
|
registerSchema({
|
|
66376
66631
|
command: "studio.improve",
|
|
@@ -66395,7 +66650,7 @@ registerSchema({
|
|
|
66395
66650
|
}
|
|
66396
66651
|
}
|
|
66397
66652
|
});
|
|
66398
|
-
var improveCommand =
|
|
66653
|
+
var improveCommand = defineCommand218({
|
|
66399
66654
|
meta: {
|
|
66400
66655
|
name: "improve",
|
|
66401
66656
|
description: `${DESCRIPTION2}
|
|
@@ -66439,7 +66694,7 @@ Examples:
|
|
|
66439
66694
|
});
|
|
66440
66695
|
|
|
66441
66696
|
// src/commands/studio/keep.ts
|
|
66442
|
-
import { defineCommand as
|
|
66697
|
+
import { defineCommand as defineCommand219 } from "citty";
|
|
66443
66698
|
registerSchema({
|
|
66444
66699
|
command: "studio.keep",
|
|
66445
66700
|
description: "Mark one take as the keeper. For an image this stars it, so the client reviewing the batch sees which one you used. For a CLIP it is the step that puts it in the video library \u2014 until then the clip cannot be used in a canvas, a landing, or an ad.",
|
|
@@ -66449,7 +66704,7 @@ registerSchema({
|
|
|
66449
66704
|
undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
|
|
66450
66705
|
}
|
|
66451
66706
|
});
|
|
66452
|
-
var keepCommand =
|
|
66707
|
+
var keepCommand = defineCommand219({
|
|
66453
66708
|
meta: {
|
|
66454
66709
|
name: "keep",
|
|
66455
66710
|
description: "Mark one take as the keeper. An image gets starred (it was already in the library); a clip gets INGESTED into the video library, which is what makes it usable anywhere else.\n\nExample: baker studio keep j57abc123def456ghi789 --slot 2\nExample: baker studio keep j57abc123def456ghi789 --slot 2 --undo"
|
|
@@ -66500,7 +66755,7 @@ var keepCommand = defineCommand213({
|
|
|
66500
66755
|
});
|
|
66501
66756
|
|
|
66502
66757
|
// src/commands/studio/list.ts
|
|
66503
|
-
import { defineCommand as
|
|
66758
|
+
import { defineCommand as defineCommand220 } from "citty";
|
|
66504
66759
|
registerSchema({
|
|
66505
66760
|
command: "studio.list",
|
|
66506
66761
|
description: "Recent Studio batches for THIS conversation, newest first \u2014 what you have already generated, so you re-use a take instead of paying for it twice. `--all` widens it to everything the company generated, including what people ran themselves in the dashboard.",
|
|
@@ -66511,7 +66766,7 @@ registerSchema({
|
|
|
66511
66766
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66512
66767
|
}
|
|
66513
66768
|
});
|
|
66514
|
-
var
|
|
66769
|
+
var listCommand19 = defineCommand220({
|
|
66515
66770
|
meta: {
|
|
66516
66771
|
name: "list",
|
|
66517
66772
|
description: "Recent Studio batches, newest first. Scoped to this conversation unless you pass --all.\n\nExample: baker studio list\nExample: baker studio list --kind video --limit 5\nExample: baker studio list --all # includes batches the client ran in the dashboard"
|
|
@@ -66545,7 +66800,7 @@ var listCommand18 = defineCommand214({
|
|
|
66545
66800
|
});
|
|
66546
66801
|
|
|
66547
66802
|
// src/commands/studio/models.ts
|
|
66548
|
-
import { defineCommand as
|
|
66803
|
+
import { defineCommand as defineCommand221 } from "citty";
|
|
66549
66804
|
var DESCRIPTION3 = "What each Studio model actually accepts: its shapes, resolutions, clip lengths, prompt character cap, how many reference images it takes, and which knobs it has. Read this before a batch you care about \u2014 the models disagree far more than they look like they do, and a setting the chosen model does not have is REFUSED, not ignored.";
|
|
66550
66805
|
registerSchema({
|
|
66551
66806
|
command: "studio.models",
|
|
@@ -66632,7 +66887,7 @@ function buildModelCards(kind, model) {
|
|
|
66632
66887
|
const selected = model ? ids.filter((id) => id === model) : ids;
|
|
66633
66888
|
return selected.map((id) => build(id));
|
|
66634
66889
|
}
|
|
66635
|
-
var modelsCommand =
|
|
66890
|
+
var modelsCommand = defineCommand221({
|
|
66636
66891
|
meta: {
|
|
66637
66892
|
name: "models",
|
|
66638
66893
|
description: `${DESCRIPTION3}
|
|
@@ -66679,13 +66934,13 @@ Examples:
|
|
|
66679
66934
|
});
|
|
66680
66935
|
|
|
66681
66936
|
// src/commands/studio/skills.ts
|
|
66682
|
-
import { defineCommand as
|
|
66937
|
+
import { defineCommand as defineCommand222 } from "citty";
|
|
66683
66938
|
registerSchema({
|
|
66684
66939
|
command: "studio.skills",
|
|
66685
66940
|
description: "The craft directions `studio generate --skill <id>` accepts. Each one carries directed art direction plus the model, shape and take count it wants, so you pick a look by name instead of writing the boilerplate yourself.",
|
|
66686
66941
|
args: {}
|
|
66687
66942
|
});
|
|
66688
|
-
var skillsCommand =
|
|
66943
|
+
var skillsCommand = defineCommand222({
|
|
66689
66944
|
meta: {
|
|
66690
66945
|
name: "skills",
|
|
66691
66946
|
description: "List the craft directions available to `baker studio generate --skill <id>` \u2014 what each one is for, whether it wants a reference image, and the model/shape/count it defaults to.\n\nExample: baker studio skills"
|
|
@@ -66709,7 +66964,7 @@ var skillsCommand = defineCommand216({
|
|
|
66709
66964
|
});
|
|
66710
66965
|
|
|
66711
66966
|
// src/commands/studio/index.ts
|
|
66712
|
-
var studioCommand =
|
|
66967
|
+
var studioCommand = defineCommand223({
|
|
66713
66968
|
meta: {
|
|
66714
66969
|
name: "studio",
|
|
66715
66970
|
description: `Make new imagery and clips. Every batch is recorded and shows up in the dashboard Studio for the client to review, labelled with this conversation.
|
|
@@ -66743,7 +66998,7 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
66743
66998
|
generate: generateCommand,
|
|
66744
66999
|
animate: animateCommand,
|
|
66745
67000
|
get: getCommand5,
|
|
66746
|
-
list:
|
|
67001
|
+
list: listCommand19,
|
|
66747
67002
|
keep: keepCommand,
|
|
66748
67003
|
models: modelsCommand,
|
|
66749
67004
|
skills: skillsCommand,
|
|
@@ -66752,10 +67007,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
66752
67007
|
});
|
|
66753
67008
|
|
|
66754
67009
|
// src/commands/tag-manager/index.ts
|
|
66755
|
-
import { defineCommand as
|
|
67010
|
+
import { defineCommand as defineCommand227 } from "citty";
|
|
66756
67011
|
|
|
66757
67012
|
// src/commands/tag-manager/draft.ts
|
|
66758
|
-
import { defineCommand as
|
|
67013
|
+
import { defineCommand as defineCommand224 } from "citty";
|
|
66759
67014
|
|
|
66760
67015
|
// src/commands/tag-manager/shared.ts
|
|
66761
67016
|
import { readFileSync as readFileSync21 } from "fs";
|
|
@@ -66816,19 +67071,17 @@ var STAGE_HINTS2 = [
|
|
|
66816
67071
|
async function stageOp4(op) {
|
|
66817
67072
|
const chatId = requireChatId();
|
|
66818
67073
|
try {
|
|
66819
|
-
const {
|
|
66820
|
-
|
|
66821
|
-
);
|
|
66822
|
-
writeJsonEnvelope({ ok: true, data, hints: [...hints2, ...STAGE_HINTS2] });
|
|
67074
|
+
const data = await apiPost("/api/tag-manager/draft/stage", { chatId, op });
|
|
67075
|
+
writeJsonEnvelope({ ok: true, data, hints: STAGE_HINTS2 });
|
|
66823
67076
|
} catch (err) {
|
|
66824
67077
|
handleError8(err);
|
|
66825
67078
|
}
|
|
66826
67079
|
}
|
|
66827
|
-
async function draftAction3(
|
|
67080
|
+
async function draftAction3(path49, body, chat) {
|
|
66828
67081
|
const chatId = resolveChatId(chat);
|
|
66829
67082
|
try {
|
|
66830
|
-
const
|
|
66831
|
-
writeJsonEnvelope({ ok: true, data
|
|
67083
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
67084
|
+
writeJsonEnvelope({ ok: true, data });
|
|
66832
67085
|
return data;
|
|
66833
67086
|
} catch (err) {
|
|
66834
67087
|
handleError8(err);
|
|
@@ -66859,13 +67112,12 @@ function renderDraft2(response) {
|
|
|
66859
67112
|
async function draftList2(json, chat) {
|
|
66860
67113
|
const chatId = resolveChatId(chat);
|
|
66861
67114
|
try {
|
|
66862
|
-
const
|
|
66863
|
-
const { data, hints: hints2 } = splitHints(response);
|
|
67115
|
+
const data = await apiPost("/api/tag-manager/draft", { chatId });
|
|
66864
67116
|
if (json) {
|
|
66865
|
-
writeJsonEnvelope({ ok: true, data
|
|
67117
|
+
writeJsonEnvelope({ ok: true, data });
|
|
66866
67118
|
return;
|
|
66867
67119
|
}
|
|
66868
|
-
process.stdout.write(`${renderDraft2(data)}
|
|
67120
|
+
process.stdout.write(`${renderDraft2(data)}
|
|
66869
67121
|
`);
|
|
66870
67122
|
} catch (err) {
|
|
66871
67123
|
handleError8(err);
|
|
@@ -66881,13 +67133,13 @@ registerSchema({
|
|
|
66881
67133
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
66882
67134
|
}
|
|
66883
67135
|
});
|
|
66884
|
-
var draftCommand5 =
|
|
67136
|
+
var draftCommand5 = defineCommand224({
|
|
66885
67137
|
meta: {
|
|
66886
67138
|
name: "draft",
|
|
66887
67139
|
description: "List, show, amend, remove, or clear staged Tag Manager changes for this chat. `list` and `show` take --chat <id> to read an earlier chat's changes instead."
|
|
66888
67140
|
},
|
|
66889
67141
|
subCommands: {
|
|
66890
|
-
list:
|
|
67142
|
+
list: defineCommand224({
|
|
66891
67143
|
meta: {
|
|
66892
67144
|
name: "list",
|
|
66893
67145
|
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
@@ -66900,7 +67152,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66900
67152
|
await draftList2(args5.json === true, args5.chat);
|
|
66901
67153
|
}
|
|
66902
67154
|
}),
|
|
66903
|
-
show:
|
|
67155
|
+
show: defineCommand224({
|
|
66904
67156
|
meta: {
|
|
66905
67157
|
name: "show",
|
|
66906
67158
|
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
@@ -66917,7 +67169,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66917
67169
|
);
|
|
66918
67170
|
}
|
|
66919
67171
|
}),
|
|
66920
|
-
amend:
|
|
67172
|
+
amend: defineCommand224({
|
|
66921
67173
|
meta: {
|
|
66922
67174
|
name: "amend",
|
|
66923
67175
|
description: "Update a staged change in place \u2014 merges a JSON patch into its payload (objects deep-merge, null deletes a key, arrays/scalars replace) and re-validates. Use this instead of remove + re-create."
|
|
@@ -66934,7 +67186,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66934
67186
|
});
|
|
66935
67187
|
}
|
|
66936
67188
|
}),
|
|
66937
|
-
remove:
|
|
67189
|
+
remove: defineCommand224({
|
|
66938
67190
|
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
66939
67191
|
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
66940
67192
|
run: async ({ args: args5 }) => {
|
|
@@ -66943,7 +67195,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66943
67195
|
});
|
|
66944
67196
|
}
|
|
66945
67197
|
}),
|
|
66946
|
-
clear:
|
|
67198
|
+
clear: defineCommand224({
|
|
66947
67199
|
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
66948
67200
|
run: async () => {
|
|
66949
67201
|
await draftAction3("/api/tag-manager/draft/clear", {});
|
|
@@ -66953,7 +67205,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66953
67205
|
});
|
|
66954
67206
|
|
|
66955
67207
|
// src/commands/tag-manager/read.ts
|
|
66956
|
-
import { defineCommand as
|
|
67208
|
+
import { defineCommand as defineCommand225 } from "citty";
|
|
66957
67209
|
registerSchema({
|
|
66958
67210
|
command: "tagManager.containers",
|
|
66959
67211
|
description: "List the Google Tag Manager containers this company's connection can reach. Every container the company connected is flagged `connected: true` \u2014 there can be several, and Baker may read and change all of them. Start here to confirm which containers you are managing.",
|
|
@@ -66994,7 +67246,7 @@ function containersHints(containers) {
|
|
|
66994
67246
|
}))
|
|
66995
67247
|
});
|
|
66996
67248
|
}
|
|
66997
|
-
var containersCommand =
|
|
67249
|
+
var containersCommand = defineCommand225({
|
|
66998
67250
|
meta: {
|
|
66999
67251
|
name: "containers",
|
|
67000
67252
|
description: `List Tag Manager containers reachable by this company's connection.
|
|
@@ -67011,7 +67263,7 @@ Start here:
|
|
|
67011
67263
|
}
|
|
67012
67264
|
}
|
|
67013
67265
|
});
|
|
67014
|
-
var readCommand =
|
|
67266
|
+
var readCommand = defineCommand225({
|
|
67015
67267
|
meta: {
|
|
67016
67268
|
name: "read",
|
|
67017
67269
|
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
@@ -67053,7 +67305,7 @@ Examples:
|
|
|
67053
67305
|
});
|
|
67054
67306
|
|
|
67055
67307
|
// src/commands/tag-manager/write-commands.ts
|
|
67056
|
-
import { defineCommand as
|
|
67308
|
+
import { defineCommand as defineCommand226 } from "citty";
|
|
67057
67309
|
var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
|
|
67058
67310
|
var ENTITIES = [
|
|
67059
67311
|
{
|
|
@@ -67109,10 +67361,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
|
|
|
67109
67361
|
});
|
|
67110
67362
|
}
|
|
67111
67363
|
function entityCommand(entity, noun, example) {
|
|
67112
|
-
return
|
|
67364
|
+
return defineCommand226({
|
|
67113
67365
|
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
67114
67366
|
subCommands: {
|
|
67115
|
-
create:
|
|
67367
|
+
create: defineCommand226({
|
|
67116
67368
|
meta: {
|
|
67117
67369
|
name: "create",
|
|
67118
67370
|
description: `Stage a new ${noun}
|
|
@@ -67134,7 +67386,7 @@ Examples:
|
|
|
67134
67386
|
});
|
|
67135
67387
|
}
|
|
67136
67388
|
}),
|
|
67137
|
-
update:
|
|
67389
|
+
update: defineCommand226({
|
|
67138
67390
|
meta: {
|
|
67139
67391
|
name: "update",
|
|
67140
67392
|
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
@@ -67154,7 +67406,7 @@ Examples:
|
|
|
67154
67406
|
});
|
|
67155
67407
|
}
|
|
67156
67408
|
}),
|
|
67157
|
-
delete:
|
|
67409
|
+
delete: defineCommand226({
|
|
67158
67410
|
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
67159
67411
|
args: {
|
|
67160
67412
|
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
@@ -67195,7 +67447,7 @@ function builtinTypes(args5) {
|
|
|
67195
67447
|
}
|
|
67196
67448
|
return raw.split(",").map((entry) => entry.trim());
|
|
67197
67449
|
}
|
|
67198
|
-
var builtinCommand =
|
|
67450
|
+
var builtinCommand = defineCommand226({
|
|
67199
67451
|
meta: {
|
|
67200
67452
|
name: "builtin",
|
|
67201
67453
|
description: `Enable or disable built-in variables
|
|
@@ -67205,7 +67457,7 @@ Examples:
|
|
|
67205
67457
|
baker tag-manager builtin disable --types formId`
|
|
67206
67458
|
},
|
|
67207
67459
|
subCommands: {
|
|
67208
|
-
enable:
|
|
67460
|
+
enable: defineCommand226({
|
|
67209
67461
|
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
67210
67462
|
args: {
|
|
67211
67463
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67219,7 +67471,7 @@ Examples:
|
|
|
67219
67471
|
});
|
|
67220
67472
|
}
|
|
67221
67473
|
}),
|
|
67222
|
-
disable:
|
|
67474
|
+
disable: defineCommand226({
|
|
67223
67475
|
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
67224
67476
|
args: {
|
|
67225
67477
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67237,7 +67489,7 @@ Examples:
|
|
|
67237
67489
|
});
|
|
67238
67490
|
|
|
67239
67491
|
// src/commands/tag-manager/index.ts
|
|
67240
|
-
var tagManagerCommand =
|
|
67492
|
+
var tagManagerCommand = defineCommand227({
|
|
67241
67493
|
meta: {
|
|
67242
67494
|
name: "tag-manager",
|
|
67243
67495
|
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
@@ -67274,7 +67526,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
|
67274
67526
|
});
|
|
67275
67527
|
|
|
67276
67528
|
// src/commands/tags/index.ts
|
|
67277
|
-
import { defineCommand as
|
|
67529
|
+
import { defineCommand as defineCommand228 } from "citty";
|
|
67278
67530
|
|
|
67279
67531
|
// src/commands/tags/shared.ts
|
|
67280
67532
|
function failApi3(err) {
|
|
@@ -67354,7 +67606,7 @@ async function listTags(json) {
|
|
|
67354
67606
|
var listArgs12 = {
|
|
67355
67607
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
|
|
67356
67608
|
};
|
|
67357
|
-
var
|
|
67609
|
+
var listCommand20 = defineCommand228({
|
|
67358
67610
|
meta: {
|
|
67359
67611
|
name: "list",
|
|
67360
67612
|
description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
|
|
@@ -67373,7 +67625,7 @@ async function listDraft4(chat) {
|
|
|
67373
67625
|
failApi3(err);
|
|
67374
67626
|
}
|
|
67375
67627
|
}
|
|
67376
|
-
var draftCommand6 =
|
|
67628
|
+
var draftCommand6 = defineCommand228({
|
|
67377
67629
|
meta: {
|
|
67378
67630
|
name: "draft",
|
|
67379
67631
|
description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create). Takes --chat <id> to read an earlier chat's staged changes instead."
|
|
@@ -67383,7 +67635,7 @@ var draftCommand6 = defineCommand222({
|
|
|
67383
67635
|
await listDraft4(args5.chat);
|
|
67384
67636
|
}
|
|
67385
67637
|
});
|
|
67386
|
-
var tagsCommand4 =
|
|
67638
|
+
var tagsCommand4 = defineCommand228({
|
|
67387
67639
|
meta: {
|
|
67388
67640
|
name: "tags",
|
|
67389
67641
|
description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
|
|
@@ -67400,7 +67652,7 @@ Examples:
|
|
|
67400
67652
|
Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
67401
67653
|
},
|
|
67402
67654
|
subCommands: {
|
|
67403
|
-
list:
|
|
67655
|
+
list: listCommand20,
|
|
67404
67656
|
draft: draftCommand6
|
|
67405
67657
|
},
|
|
67406
67658
|
// Bare `baker tags` lists the effective tags. `args` stays so citty knows this
|
|
@@ -67412,10 +67664,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
67412
67664
|
});
|
|
67413
67665
|
|
|
67414
67666
|
// src/commands/testimonials/index.ts
|
|
67415
|
-
import { defineCommand as
|
|
67667
|
+
import { defineCommand as defineCommand232 } from "citty";
|
|
67416
67668
|
|
|
67417
67669
|
// src/commands/testimonials/get.ts
|
|
67418
|
-
import { defineCommand as
|
|
67670
|
+
import { defineCommand as defineCommand229 } from "citty";
|
|
67419
67671
|
registerSchema({
|
|
67420
67672
|
command: "testimonials.get",
|
|
67421
67673
|
description: "Get a single testimonial by ID",
|
|
@@ -67423,7 +67675,7 @@ registerSchema({
|
|
|
67423
67675
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
67424
67676
|
}
|
|
67425
67677
|
});
|
|
67426
|
-
var getCommand6 =
|
|
67678
|
+
var getCommand6 = defineCommand229({
|
|
67427
67679
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
67428
67680
|
args: {
|
|
67429
67681
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -67460,7 +67712,7 @@ var getCommand6 = defineCommand223({
|
|
|
67460
67712
|
});
|
|
67461
67713
|
|
|
67462
67714
|
// src/commands/testimonials/list.ts
|
|
67463
|
-
import { defineCommand as
|
|
67715
|
+
import { defineCommand as defineCommand230 } from "citty";
|
|
67464
67716
|
|
|
67465
67717
|
// src/commands/testimonials/emptyCorpusHints.ts
|
|
67466
67718
|
function resolveEmptyReason({
|
|
@@ -67617,7 +67869,7 @@ function buildListParams(args5) {
|
|
|
67617
67869
|
}
|
|
67618
67870
|
return params;
|
|
67619
67871
|
}
|
|
67620
|
-
var
|
|
67872
|
+
var listCommand21 = defineCommand230({
|
|
67621
67873
|
meta: {
|
|
67622
67874
|
name: "list",
|
|
67623
67875
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -67677,7 +67929,7 @@ var listCommand20 = defineCommand224({
|
|
|
67677
67929
|
});
|
|
67678
67930
|
|
|
67679
67931
|
// src/commands/testimonials/search.ts
|
|
67680
|
-
import { defineCommand as
|
|
67932
|
+
import { defineCommand as defineCommand231 } from "citty";
|
|
67681
67933
|
var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
|
|
67682
67934
|
function languageBiasHint(results, requestedLanguage) {
|
|
67683
67935
|
if (requestedLanguage) {
|
|
@@ -67756,7 +68008,7 @@ function buildSearchRequest(query, args5) {
|
|
|
67756
68008
|
}
|
|
67757
68009
|
return body;
|
|
67758
68010
|
}
|
|
67759
|
-
var searchCommand3 =
|
|
68011
|
+
var searchCommand3 = defineCommand231({
|
|
67760
68012
|
meta: {
|
|
67761
68013
|
name: "search",
|
|
67762
68014
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -67820,7 +68072,7 @@ var searchCommand3 = defineCommand225({
|
|
|
67820
68072
|
var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
67821
68073
|
|
|
67822
68074
|
// src/commands/testimonials/index.ts
|
|
67823
|
-
var testimonialsCommand =
|
|
68075
|
+
var testimonialsCommand = defineCommand232({
|
|
67824
68076
|
meta: {
|
|
67825
68077
|
name: "testimonials",
|
|
67826
68078
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -67836,16 +68088,16 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
67836
68088
|
subCommands: {
|
|
67837
68089
|
get: getCommand6,
|
|
67838
68090
|
search: searchCommand3,
|
|
67839
|
-
list:
|
|
68091
|
+
list: listCommand21,
|
|
67840
68092
|
tags: tagsCommand5
|
|
67841
68093
|
}
|
|
67842
68094
|
});
|
|
67843
68095
|
|
|
67844
68096
|
// src/commands/videos/index.ts
|
|
67845
|
-
import { defineCommand as
|
|
68097
|
+
import { defineCommand as defineCommand241 } from "citty";
|
|
67846
68098
|
|
|
67847
68099
|
// src/commands/videos/delete.ts
|
|
67848
|
-
import { defineCommand as
|
|
68100
|
+
import { defineCommand as defineCommand233 } from "citty";
|
|
67849
68101
|
registerSchema({
|
|
67850
68102
|
command: "videos.delete",
|
|
67851
68103
|
description: "Delete a video by ID",
|
|
@@ -67859,7 +68111,7 @@ registerSchema({
|
|
|
67859
68111
|
}
|
|
67860
68112
|
}
|
|
67861
68113
|
});
|
|
67862
|
-
var deleteCommand4 =
|
|
68114
|
+
var deleteCommand4 = defineCommand233({
|
|
67863
68115
|
meta: {
|
|
67864
68116
|
name: "delete",
|
|
67865
68117
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -67900,7 +68152,7 @@ var deleteCommand4 = defineCommand227({
|
|
|
67900
68152
|
});
|
|
67901
68153
|
|
|
67902
68154
|
// src/commands/videos/describe.ts
|
|
67903
|
-
import { defineCommand as
|
|
68155
|
+
import { defineCommand as defineCommand234 } from "citty";
|
|
67904
68156
|
var DESCRIPTION_HELP2 = "What the clip actually shows, in the words someone would search for it by. This is what `baker videos search` retrieves on.";
|
|
67905
68157
|
registerSchema({
|
|
67906
68158
|
command: "videos.describe",
|
|
@@ -67917,7 +68169,7 @@ registerSchema({
|
|
|
67917
68169
|
full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
|
|
67918
68170
|
}
|
|
67919
68171
|
});
|
|
67920
|
-
var describeCommand2 =
|
|
68172
|
+
var describeCommand2 = defineCommand234({
|
|
67921
68173
|
meta: {
|
|
67922
68174
|
name: "describe",
|
|
67923
68175
|
description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
|
|
@@ -67974,108 +68226,12 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
67974
68226
|
}
|
|
67975
68227
|
});
|
|
67976
68228
|
|
|
67977
|
-
// src/commands/videos/
|
|
67978
|
-
import {
|
|
67979
|
-
|
|
67980
|
-
command: "videos.get",
|
|
67981
|
-
description: "Get a single video by ID",
|
|
67982
|
-
args: {
|
|
67983
|
-
id: { type: "string", description: "Video ID", required: true }
|
|
67984
|
-
}
|
|
67985
|
-
});
|
|
67986
|
-
var getCommand7 = defineCommand229({
|
|
67987
|
-
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
67988
|
-
args: {
|
|
67989
|
-
id: { type: "positional", description: "Video ID", required: false },
|
|
67990
|
-
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
67991
|
-
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
67992
|
-
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
67993
|
-
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
67994
|
-
},
|
|
67995
|
-
run: async ({ args: args5 }) => {
|
|
67996
|
-
try {
|
|
67997
|
-
const id = args5.id || args5["video-id"];
|
|
67998
|
-
if (!id) {
|
|
67999
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
68000
|
-
process.exit(1);
|
|
68001
|
-
}
|
|
68002
|
-
validateConvexId(id);
|
|
68003
|
-
const data = await apiGet("/api/videos/get", { id });
|
|
68004
|
-
writeOutput(
|
|
68005
|
-
{ ok: true, data },
|
|
68006
|
-
args5.output || "json",
|
|
68007
|
-
args5.fields ? args5.fields.split(",") : void 0,
|
|
68008
|
-
args5.full,
|
|
68009
|
-
videoNormalizer
|
|
68010
|
-
);
|
|
68011
|
-
} catch (err) {
|
|
68012
|
-
if (err instanceof ApiError) {
|
|
68013
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68014
|
-
process.exit(1);
|
|
68015
|
-
}
|
|
68016
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
68017
|
-
process.exit(1);
|
|
68018
|
-
}
|
|
68019
|
-
}
|
|
68020
|
-
});
|
|
68021
|
-
|
|
68022
|
-
// src/commands/videos/group.ts
|
|
68023
|
-
import { defineCommand as defineCommand230 } from "citty";
|
|
68024
|
-
registerSchema({
|
|
68025
|
-
command: "videos.group",
|
|
68026
|
-
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
68027
|
-
args: {
|
|
68028
|
-
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
68029
|
-
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
68030
|
-
}
|
|
68031
|
-
});
|
|
68032
|
-
var groupCommand2 = defineCommand230({
|
|
68033
|
-
meta: {
|
|
68034
|
-
name: "group",
|
|
68035
|
-
description: "List every asset that arrived in the same set as this clip \u2014 the other slides of the Instagram post it came from, stills included. A carousel is authored to be read in order, so a clip pulled out of one is usually missing half its meaning. Example: baker videos group <videoId>"
|
|
68036
|
-
},
|
|
68037
|
-
args: {
|
|
68038
|
-
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
68039
|
-
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
68040
|
-
},
|
|
68041
|
-
run: async ({ args: args5 }) => {
|
|
68042
|
-
await runMediaGroupLookup({
|
|
68043
|
-
id: args5.id,
|
|
68044
|
-
groupKey: args5["group-key"],
|
|
68045
|
-
path: "/api/videos/group",
|
|
68046
|
-
idLabel: "a video or image id"
|
|
68047
|
-
});
|
|
68048
|
-
}
|
|
68049
|
-
});
|
|
68050
|
-
|
|
68051
|
-
// src/commands/videos/ingest.ts
|
|
68052
|
-
import { mkdtemp as mkdtemp3, rm as rm9, stat as stat11 } from "fs/promises";
|
|
68229
|
+
// src/commands/videos/fetch.ts
|
|
68230
|
+
import { constants } from "fs";
|
|
68231
|
+
import { copyFile as copyFile2, mkdir as mkdir15, mkdtemp as mkdtemp3, rm as rm9 } from "fs/promises";
|
|
68053
68232
|
import { tmpdir as tmpdir4 } from "os";
|
|
68054
68233
|
import path47 from "path";
|
|
68055
|
-
import { defineCommand as
|
|
68056
|
-
|
|
68057
|
-
// src/lib/streamUpload.ts
|
|
68058
|
-
import { createHash as createHash2 } from "crypto";
|
|
68059
|
-
import { createReadStream } from "fs";
|
|
68060
|
-
import { Readable } from "stream";
|
|
68061
|
-
import { pipeline } from "stream/promises";
|
|
68062
|
-
async function hashFile(filePath) {
|
|
68063
|
-
const hash = createHash2("sha256");
|
|
68064
|
-
await pipeline(createReadStream(filePath), hash);
|
|
68065
|
-
return hash.digest("hex");
|
|
68066
|
-
}
|
|
68067
|
-
async function putFileStreamed(args5) {
|
|
68068
|
-
const body = Readable.toWeb(createReadStream(args5.filePath));
|
|
68069
|
-
return await fetch(args5.putUrl, {
|
|
68070
|
-
method: "PUT",
|
|
68071
|
-
body,
|
|
68072
|
-
headers: {
|
|
68073
|
-
"Content-Type": args5.contentType,
|
|
68074
|
-
"Content-Length": String(args5.sizeBytes)
|
|
68075
|
-
},
|
|
68076
|
-
duplex: "half"
|
|
68077
|
-
});
|
|
68078
|
-
}
|
|
68234
|
+
import { defineCommand as defineCommand235 } from "citty";
|
|
68079
68235
|
|
|
68080
68236
|
// src/commands/videos/videoPlatforms.ts
|
|
68081
68237
|
var PLATFORM_DOMAINS = {
|
|
@@ -68084,6 +68240,7 @@ var PLATFORM_DOMAINS = {
|
|
|
68084
68240
|
tiktok: ["tiktok.com"],
|
|
68085
68241
|
twitter: ["twitter.com", "x.com", "vxtwitter.com", "fixvx.com"],
|
|
68086
68242
|
facebook: ["facebook.com", "fb.watch", "fb.com"],
|
|
68243
|
+
linkedin: ["linkedin.com", "lnkd.in"],
|
|
68087
68244
|
reddit: ["reddit.com", "redd.it"],
|
|
68088
68245
|
vimeo: ["vimeo.com"],
|
|
68089
68246
|
dailymotion: ["dailymotion.com", "dai.ly"],
|
|
@@ -68188,6 +68345,218 @@ function safePathname(rawUrl) {
|
|
|
68188
68345
|
}
|
|
68189
68346
|
}
|
|
68190
68347
|
|
|
68348
|
+
// src/commands/videos/fetch.ts
|
|
68349
|
+
registerSchema({
|
|
68350
|
+
command: "videos.fetch",
|
|
68351
|
+
description: "Download a video page (YouTube, TikTok, Vimeo, \u2026) to a local .mp4 without adding it to the library. For editing a clip locally; use `videos ingest` to add one to the library.",
|
|
68352
|
+
args: {
|
|
68353
|
+
url: { type: "string", description: "Video page URL", required: true },
|
|
68354
|
+
out: { type: "string", description: "Directory to write the file into (created if missing)", required: true },
|
|
68355
|
+
"max-seconds": {
|
|
68356
|
+
type: "string",
|
|
68357
|
+
description: `Refuse videos longer than this many seconds (default ${MAX_VIDEO_INGEST_SECONDS})`,
|
|
68358
|
+
required: false
|
|
68359
|
+
},
|
|
68360
|
+
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
68361
|
+
"max-height": {
|
|
68362
|
+
type: "string",
|
|
68363
|
+
description: "Keep a version whose shorter side is at most this many pixels (e.g. 1080 \u2014 a vertical Short keeps 1080\xD71920) when the site offers one",
|
|
68364
|
+
required: false
|
|
68365
|
+
}
|
|
68366
|
+
}
|
|
68367
|
+
});
|
|
68368
|
+
function positiveInt(value) {
|
|
68369
|
+
const parsed = typeof value === "string" ? Number.parseInt(value, 10) : Number.NaN;
|
|
68370
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
68371
|
+
}
|
|
68372
|
+
var fetchCommand2 = defineCommand235({
|
|
68373
|
+
meta: {
|
|
68374
|
+
name: "fetch",
|
|
68375
|
+
description: "Download a video page to a local .mp4 without adding it to the library. Same downloader as `ingest` (proxy fallback, duration check).\n\nExample: baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips"
|
|
68376
|
+
},
|
|
68377
|
+
args: {
|
|
68378
|
+
url: { type: "positional", description: "Video page URL", required: true },
|
|
68379
|
+
out: { type: "string", description: "Directory to write the file into", required: true },
|
|
68380
|
+
"max-seconds": { type: "string", description: "Refuse videos longer than this", required: false },
|
|
68381
|
+
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
68382
|
+
"max-height": {
|
|
68383
|
+
type: "string",
|
|
68384
|
+
description: "Cap the shorter side at this many pixels (e.g. 1080)",
|
|
68385
|
+
required: false
|
|
68386
|
+
}
|
|
68387
|
+
},
|
|
68388
|
+
run: async ({ args: args5 }) => {
|
|
68389
|
+
const result = await fetchVideo({
|
|
68390
|
+
url: String(args5.url ?? ""),
|
|
68391
|
+
out: String(args5.out ?? ""),
|
|
68392
|
+
maxSeconds: positiveInt(args5["max-seconds"]),
|
|
68393
|
+
timeoutMs: positiveInt(args5["timeout-ms"]),
|
|
68394
|
+
maxHeight: positiveInt(args5["max-height"])
|
|
68395
|
+
});
|
|
68396
|
+
writeJson(result);
|
|
68397
|
+
if (!result.ok) process.exit(1);
|
|
68398
|
+
}
|
|
68399
|
+
});
|
|
68400
|
+
async function fetchVideo(args5) {
|
|
68401
|
+
const outDir = path47.resolve(args5.out);
|
|
68402
|
+
const workDir = await mkdtemp3(path47.join(tmpdir4(), "videos-fetch-"));
|
|
68403
|
+
try {
|
|
68404
|
+
await mkdir15(outDir, { recursive: true });
|
|
68405
|
+
const vimeoCookie = captureVimeoCookie();
|
|
68406
|
+
const probe = await probeYtDlp({ url: args5.url, vimeoCookie, cookieDir: workDir });
|
|
68407
|
+
if (isAudioOnly(probe.info)) {
|
|
68408
|
+
return { ok: false, error: { code: "VALIDATION_ERROR", message: "That link is audio, not video." } };
|
|
68409
|
+
}
|
|
68410
|
+
const seconds = durationSeconds(probe.info);
|
|
68411
|
+
const tooLong = refuseByDuration(seconds, args5.maxSeconds ?? MAX_VIDEO_INGEST_SECONDS);
|
|
68412
|
+
if (tooLong) {
|
|
68413
|
+
return { ok: false, error: { code: "VALIDATION_ERROR", message: tooLong } };
|
|
68414
|
+
}
|
|
68415
|
+
const { filePath, tier, reducedQuality } = await runYtDlp({
|
|
68416
|
+
url: args5.url,
|
|
68417
|
+
audioOnly: false,
|
|
68418
|
+
workDir,
|
|
68419
|
+
vimeoCookie,
|
|
68420
|
+
timeoutMs: args5.timeoutMs ?? downloadTimeoutMs(seconds),
|
|
68421
|
+
maxHeight: args5.maxHeight
|
|
68422
|
+
});
|
|
68423
|
+
return {
|
|
68424
|
+
ok: true,
|
|
68425
|
+
data: {
|
|
68426
|
+
file: await placeInto(outDir, filePath, fileStem(probe.info)),
|
|
68427
|
+
durationSeconds: seconds,
|
|
68428
|
+
egress: tier,
|
|
68429
|
+
...reducedQuality ? { reducedQuality: true } : {}
|
|
68430
|
+
}
|
|
68431
|
+
};
|
|
68432
|
+
} catch (err) {
|
|
68433
|
+
const message = err instanceof YtDlpError ? `${err.message}: ${err.stderrTail}`.trim() : err instanceof Error ? err.message : String(err);
|
|
68434
|
+
return { ok: false, error: { code: "DOWNLOAD_FAILED", message } };
|
|
68435
|
+
} finally {
|
|
68436
|
+
await rm9(workDir, { recursive: true, force: true }).catch(() => {
|
|
68437
|
+
});
|
|
68438
|
+
}
|
|
68439
|
+
}
|
|
68440
|
+
function fileStem(info) {
|
|
68441
|
+
const parts = [info.extractor_key, info.id].filter((part) => typeof part === "string" && part !== "");
|
|
68442
|
+
const stem = parts.join("-").toLowerCase().replace(/[^a-z0-9._-]+/g, "_").replace(/^[._-]+/, "");
|
|
68443
|
+
return stem === "" ? "video" : stem;
|
|
68444
|
+
}
|
|
68445
|
+
async function placeInto(outDir, source, stem) {
|
|
68446
|
+
for (let n = 1; ; n++) {
|
|
68447
|
+
const target2 = path47.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path47.extname(source)}`);
|
|
68448
|
+
try {
|
|
68449
|
+
await copyFile2(source, target2, constants.COPYFILE_EXCL);
|
|
68450
|
+
return target2;
|
|
68451
|
+
} catch (err) {
|
|
68452
|
+
if (!(err instanceof Error && "code" in err && err.code === "EEXIST")) throw err;
|
|
68453
|
+
}
|
|
68454
|
+
}
|
|
68455
|
+
}
|
|
68456
|
+
|
|
68457
|
+
// src/commands/videos/get.ts
|
|
68458
|
+
import { defineCommand as defineCommand236 } from "citty";
|
|
68459
|
+
registerSchema({
|
|
68460
|
+
command: "videos.get",
|
|
68461
|
+
description: "Get a single video by ID",
|
|
68462
|
+
args: {
|
|
68463
|
+
id: { type: "string", description: "Video ID", required: true }
|
|
68464
|
+
}
|
|
68465
|
+
});
|
|
68466
|
+
var getCommand7 = defineCommand236({
|
|
68467
|
+
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
68468
|
+
args: {
|
|
68469
|
+
id: { type: "positional", description: "Video ID", required: false },
|
|
68470
|
+
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
68471
|
+
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
68472
|
+
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
68473
|
+
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
68474
|
+
},
|
|
68475
|
+
run: async ({ args: args5 }) => {
|
|
68476
|
+
try {
|
|
68477
|
+
const id = args5.id || args5["video-id"];
|
|
68478
|
+
if (!id) {
|
|
68479
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
68480
|
+
process.exit(1);
|
|
68481
|
+
}
|
|
68482
|
+
validateConvexId(id);
|
|
68483
|
+
const data = await apiGet("/api/videos/get", { id });
|
|
68484
|
+
writeOutput(
|
|
68485
|
+
{ ok: true, data },
|
|
68486
|
+
args5.output || "json",
|
|
68487
|
+
args5.fields ? args5.fields.split(",") : void 0,
|
|
68488
|
+
args5.full,
|
|
68489
|
+
videoNormalizer
|
|
68490
|
+
);
|
|
68491
|
+
} catch (err) {
|
|
68492
|
+
if (err instanceof ApiError) {
|
|
68493
|
+
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68494
|
+
process.exit(1);
|
|
68495
|
+
}
|
|
68496
|
+
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
68497
|
+
process.exit(1);
|
|
68498
|
+
}
|
|
68499
|
+
}
|
|
68500
|
+
});
|
|
68501
|
+
|
|
68502
|
+
// src/commands/videos/group.ts
|
|
68503
|
+
import { defineCommand as defineCommand237 } from "citty";
|
|
68504
|
+
registerSchema({
|
|
68505
|
+
command: "videos.group",
|
|
68506
|
+
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
68507
|
+
args: {
|
|
68508
|
+
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
68509
|
+
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
68510
|
+
}
|
|
68511
|
+
});
|
|
68512
|
+
var groupCommand2 = defineCommand237({
|
|
68513
|
+
meta: {
|
|
68514
|
+
name: "group",
|
|
68515
|
+
description: "List every asset that arrived in the same set as this clip \u2014 the other slides of the Instagram post it came from, stills included. A carousel is authored to be read in order, so a clip pulled out of one is usually missing half its meaning. Example: baker videos group <videoId>"
|
|
68516
|
+
},
|
|
68517
|
+
args: {
|
|
68518
|
+
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
68519
|
+
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
68520
|
+
},
|
|
68521
|
+
run: async ({ args: args5 }) => {
|
|
68522
|
+
await runMediaGroupLookup({
|
|
68523
|
+
id: args5.id,
|
|
68524
|
+
groupKey: args5["group-key"],
|
|
68525
|
+
path: "/api/videos/group",
|
|
68526
|
+
idLabel: "a video or image id"
|
|
68527
|
+
});
|
|
68528
|
+
}
|
|
68529
|
+
});
|
|
68530
|
+
|
|
68531
|
+
// src/commands/videos/ingest.ts
|
|
68532
|
+
import { mkdtemp as mkdtemp4, rm as rm10, stat as stat11 } from "fs/promises";
|
|
68533
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
68534
|
+
import path48 from "path";
|
|
68535
|
+
import { defineCommand as defineCommand238 } from "citty";
|
|
68536
|
+
|
|
68537
|
+
// src/lib/streamUpload.ts
|
|
68538
|
+
import { createHash as createHash2 } from "crypto";
|
|
68539
|
+
import { createReadStream } from "fs";
|
|
68540
|
+
import { Readable } from "stream";
|
|
68541
|
+
import { pipeline } from "stream/promises";
|
|
68542
|
+
async function hashFile(filePath) {
|
|
68543
|
+
const hash = createHash2("sha256");
|
|
68544
|
+
await pipeline(createReadStream(filePath), hash);
|
|
68545
|
+
return hash.digest("hex");
|
|
68546
|
+
}
|
|
68547
|
+
async function putFileStreamed(args5) {
|
|
68548
|
+
const body = Readable.toWeb(createReadStream(args5.filePath));
|
|
68549
|
+
return await fetch(args5.putUrl, {
|
|
68550
|
+
method: "PUT",
|
|
68551
|
+
body,
|
|
68552
|
+
headers: {
|
|
68553
|
+
"Content-Type": args5.contentType,
|
|
68554
|
+
"Content-Length": String(args5.sizeBytes)
|
|
68555
|
+
},
|
|
68556
|
+
duplex: "half"
|
|
68557
|
+
});
|
|
68558
|
+
}
|
|
68559
|
+
|
|
68191
68560
|
// src/commands/videos/ingest.ts
|
|
68192
68561
|
registerSchema({
|
|
68193
68562
|
command: "videos.ingest",
|
|
@@ -68216,7 +68585,7 @@ registerSchema({
|
|
|
68216
68585
|
"dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
|
|
68217
68586
|
}
|
|
68218
68587
|
});
|
|
68219
|
-
var ingestCommand2 =
|
|
68588
|
+
var ingestCommand2 = defineCommand238({
|
|
68220
68589
|
meta: {
|
|
68221
68590
|
name: "ingest",
|
|
68222
68591
|
description: "Add a video to the library from a URL. A direct file URL is handed straight to Baker, which fetches it. A page URL (YouTube, TikTok, Vimeo, Instagram) is downloaded here first, then uploaded \u2014 and a direct URL that Baker cannot fetch falls back to that same path automatically.\n\nExample: baker videos ingest https://www.youtube.com/watch?v=abc123"
|
|
@@ -68402,7 +68771,7 @@ function ingestUrl(args5) {
|
|
|
68402
68771
|
}
|
|
68403
68772
|
async function downloadThenIngest(args5, country) {
|
|
68404
68773
|
const vimeoCookie = captureVimeoCookie();
|
|
68405
|
-
const workDir = await
|
|
68774
|
+
const workDir = await mkdtemp4(path48.join(tmpdir5(), "videos-ingest-"));
|
|
68406
68775
|
try {
|
|
68407
68776
|
const probe = await probeYtDlp({ url: args5.url, country, vimeoCookie, cookieDir: workDir });
|
|
68408
68777
|
if (isAudioOnly(probe.info)) {
|
|
@@ -68459,7 +68828,7 @@ async function downloadThenIngest(args5, country) {
|
|
|
68459
68828
|
...reducedQuality ? { reducedQuality: true } : {}
|
|
68460
68829
|
};
|
|
68461
68830
|
} finally {
|
|
68462
|
-
await
|
|
68831
|
+
await rm10(workDir, { recursive: true, force: true }).catch(() => {
|
|
68463
68832
|
});
|
|
68464
68833
|
}
|
|
68465
68834
|
}
|
|
@@ -68478,7 +68847,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
|
|
|
68478
68847
|
}
|
|
68479
68848
|
|
|
68480
68849
|
// src/commands/videos/search.ts
|
|
68481
|
-
import { defineCommand as
|
|
68850
|
+
import { defineCommand as defineCommand239 } from "citty";
|
|
68482
68851
|
registerSchema({
|
|
68483
68852
|
command: "videos.search",
|
|
68484
68853
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -68488,7 +68857,7 @@ registerSchema({
|
|
|
68488
68857
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
68489
68858
|
}
|
|
68490
68859
|
});
|
|
68491
|
-
var searchCommand4 =
|
|
68860
|
+
var searchCommand4 = defineCommand239({
|
|
68492
68861
|
meta: {
|
|
68493
68862
|
name: "search",
|
|
68494
68863
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -68540,7 +68909,7 @@ var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
|
68540
68909
|
// src/commands/videos/upload.ts
|
|
68541
68910
|
import { readFile as readFile33, stat as stat12 } from "fs/promises";
|
|
68542
68911
|
import { basename as basename3, extname as extname4 } from "path";
|
|
68543
|
-
import { defineCommand as
|
|
68912
|
+
import { defineCommand as defineCommand240 } from "citty";
|
|
68544
68913
|
var MIME_MAP = {
|
|
68545
68914
|
".mp4": "video/mp4",
|
|
68546
68915
|
".mov": "video/quicktime",
|
|
@@ -68582,7 +68951,7 @@ function detectContentType(filePath) {
|
|
|
68582
68951
|
function isRemoteUrl3(value) {
|
|
68583
68952
|
return /^https?:\/\//i.test(value);
|
|
68584
68953
|
}
|
|
68585
|
-
var uploadCommand2 =
|
|
68954
|
+
var uploadCommand2 = defineCommand240({
|
|
68586
68955
|
meta: {
|
|
68587
68956
|
name: "upload",
|
|
68588
68957
|
description: "Upload a video to Baker \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: auto-detects content type and uploads via Mux direct upload.\nRemote: hands off to `videos ingest` (direct fetch, or download-then-upload for a YouTube/TikTok/Vimeo page).\n\nExamples:\n baker videos upload ./demo.mp4\n baker videos upload https://www.youtube.com/watch?v=abc123"
|
|
@@ -68666,10 +69035,10 @@ var uploadCommand2 = defineCommand233({
|
|
|
68666
69035
|
});
|
|
68667
69036
|
|
|
68668
69037
|
// src/commands/videos/index.ts
|
|
68669
|
-
var videosCommand =
|
|
69038
|
+
var videosCommand = defineCommand241({
|
|
68670
69039
|
meta: {
|
|
68671
69040
|
name: "videos",
|
|
68672
|
-
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, describe, delete, tags.
|
|
69041
|
+
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, fetch, describe, delete, tags.
|
|
68673
69042
|
|
|
68674
69043
|
Examples:
|
|
68675
69044
|
baker videos search "product demo" --limit 5
|
|
@@ -68677,6 +69046,7 @@ Examples:
|
|
|
68677
69046
|
baker videos get <video-id>
|
|
68678
69047
|
baker videos upload ./demo.mp4
|
|
68679
69048
|
baker videos ingest https://www.youtube.com/watch?v=abc123
|
|
69049
|
+
baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips
|
|
68680
69050
|
baker videos describe <video-id> --description "Customer testimonial, 30s"
|
|
68681
69051
|
baker videos delete <video-id> --dry-run
|
|
68682
69052
|
baker videos tags
|
|
@@ -68688,6 +69058,7 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
68688
69058
|
search: searchCommand4,
|
|
68689
69059
|
upload: uploadCommand2,
|
|
68690
69060
|
ingest: ingestCommand2,
|
|
69061
|
+
fetch: fetchCommand2,
|
|
68691
69062
|
describe: describeCommand2,
|
|
68692
69063
|
delete: deleteCommand4,
|
|
68693
69064
|
tags: tagsCommand6
|
|
@@ -68695,10 +69066,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
68695
69066
|
});
|
|
68696
69067
|
|
|
68697
69068
|
// src/commands/winning-ads/index.ts
|
|
68698
|
-
import { defineCommand as
|
|
69069
|
+
import { defineCommand as defineCommand254 } from "citty";
|
|
68699
69070
|
|
|
68700
69071
|
// src/commands/winning-ads/advertisers.ts
|
|
68701
|
-
import { defineCommand as
|
|
69072
|
+
import { defineCommand as defineCommand242 } from "citty";
|
|
68702
69073
|
|
|
68703
69074
|
// src/commands/winning-ads/shared.ts
|
|
68704
69075
|
function splitList3(value) {
|
|
@@ -68707,7 +69078,7 @@ function splitList3(value) {
|
|
|
68707
69078
|
}
|
|
68708
69079
|
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
68709
69080
|
}
|
|
68710
|
-
function
|
|
69081
|
+
function reportError3(err) {
|
|
68711
69082
|
if (err instanceof ApiError) {
|
|
68712
69083
|
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68713
69084
|
process.exit(1);
|
|
@@ -68751,7 +69122,7 @@ function advertiserNormalizer(record, full) {
|
|
|
68751
69122
|
last_synced_at: record.last_synced_at ?? null
|
|
68752
69123
|
};
|
|
68753
69124
|
}
|
|
68754
|
-
var advertisersCommand2 =
|
|
69125
|
+
var advertisersCommand2 = defineCommand242({
|
|
68755
69126
|
meta: {
|
|
68756
69127
|
name: "advertisers",
|
|
68757
69128
|
description: 'List corpus advertisers by name or domain. Find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id / winners. Example: baker winning-ads advertisers "Deel" --output md'
|
|
@@ -68803,13 +69174,13 @@ var advertisersCommand2 = defineCommand235({
|
|
|
68803
69174
|
advertiserNormalizer
|
|
68804
69175
|
);
|
|
68805
69176
|
} catch (err) {
|
|
68806
|
-
|
|
69177
|
+
reportError3(err);
|
|
68807
69178
|
}
|
|
68808
69179
|
}
|
|
68809
69180
|
});
|
|
68810
69181
|
|
|
68811
69182
|
// src/commands/winning-ads/brief.ts
|
|
68812
|
-
import { defineCommand as
|
|
69183
|
+
import { defineCommand as defineCommand243 } from "citty";
|
|
68813
69184
|
registerSchema({
|
|
68814
69185
|
command: "winning-ads.brief",
|
|
68815
69186
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -68855,7 +69226,7 @@ function parseDna(raw) {
|
|
|
68855
69226
|
}
|
|
68856
69227
|
return parsed;
|
|
68857
69228
|
}
|
|
68858
|
-
var briefCommand =
|
|
69229
|
+
var briefCommand = defineCommand243({
|
|
68859
69230
|
meta: {
|
|
68860
69231
|
name: "brief",
|
|
68861
69232
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -68885,13 +69256,13 @@ var briefCommand = defineCommand236({
|
|
|
68885
69256
|
const data = await apiPost("/api/ad-library/brief", body);
|
|
68886
69257
|
writeJson({ ok: true, data });
|
|
68887
69258
|
} catch (err) {
|
|
68888
|
-
|
|
69259
|
+
reportError3(err);
|
|
68889
69260
|
}
|
|
68890
69261
|
}
|
|
68891
69262
|
});
|
|
68892
69263
|
|
|
68893
69264
|
// src/commands/winning-ads/content.ts
|
|
68894
|
-
import { defineCommand as
|
|
69265
|
+
import { defineCommand as defineCommand244 } from "citty";
|
|
68895
69266
|
registerSchema({
|
|
68896
69267
|
command: "winning-ads.content",
|
|
68897
69268
|
description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Add --full for speech, pacing, and soundtrack detail. Video ads carry the transcript/on-screen text; static ads carry only the copy.",
|
|
@@ -68904,7 +69275,7 @@ registerSchema({
|
|
|
68904
69275
|
}
|
|
68905
69276
|
}
|
|
68906
69277
|
});
|
|
68907
|
-
var contentCommand =
|
|
69278
|
+
var contentCommand = defineCommand244({
|
|
68908
69279
|
meta: {
|
|
68909
69280
|
name: "content",
|
|
68910
69281
|
description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
@@ -68947,13 +69318,13 @@ var contentCommand = defineCommand237({
|
|
|
68947
69318
|
adContentNormalizer
|
|
68948
69319
|
);
|
|
68949
69320
|
} catch (err) {
|
|
68950
|
-
|
|
69321
|
+
reportError3(err);
|
|
68951
69322
|
}
|
|
68952
69323
|
}
|
|
68953
69324
|
});
|
|
68954
69325
|
|
|
68955
69326
|
// src/commands/winning-ads/feed.ts
|
|
68956
|
-
import { defineCommand as
|
|
69327
|
+
import { defineCommand as defineCommand245 } from "citty";
|
|
68957
69328
|
function buildFeedParams(input) {
|
|
68958
69329
|
const params = {};
|
|
68959
69330
|
const advertiser = splitList3(input.advertiser);
|
|
@@ -69005,7 +69376,7 @@ registerSchema({
|
|
|
69005
69376
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
69006
69377
|
}
|
|
69007
69378
|
});
|
|
69008
|
-
var feedCommand2 =
|
|
69379
|
+
var feedCommand2 = defineCommand245({
|
|
69009
69380
|
meta: {
|
|
69010
69381
|
name: "feed",
|
|
69011
69382
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -69084,13 +69455,13 @@ var feedCommand2 = defineCommand238({
|
|
|
69084
69455
|
`);
|
|
69085
69456
|
}
|
|
69086
69457
|
} catch (err) {
|
|
69087
|
-
|
|
69458
|
+
reportError3(err);
|
|
69088
69459
|
}
|
|
69089
69460
|
}
|
|
69090
69461
|
});
|
|
69091
69462
|
|
|
69092
69463
|
// src/commands/winning-ads/follow.ts
|
|
69093
|
-
import { defineCommand as
|
|
69464
|
+
import { defineCommand as defineCommand246 } from "citty";
|
|
69094
69465
|
var PLATFORMS = adLibraryPlatformSchema.options;
|
|
69095
69466
|
registerSchema({
|
|
69096
69467
|
command: "winning-ads.follow",
|
|
@@ -69105,7 +69476,7 @@ registerSchema({
|
|
|
69105
69476
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
69106
69477
|
}
|
|
69107
69478
|
});
|
|
69108
|
-
var followCommand =
|
|
69479
|
+
var followCommand = defineCommand246({
|
|
69109
69480
|
meta: {
|
|
69110
69481
|
name: "follow",
|
|
69111
69482
|
description: 'Follow a brand to track ALL its ads \u2014 every platform and country. --platform is how we read your input, not a limit. A domain tracks every platform we can resolve. Example: baker winning-ads follow "deel.com" --platform meta'
|
|
@@ -69146,13 +69517,13 @@ var followCommand = defineCommand239({
|
|
|
69146
69517
|
}
|
|
69147
69518
|
writeJson({ ok: true, data, hints: hints2 });
|
|
69148
69519
|
} catch (err) {
|
|
69149
|
-
|
|
69520
|
+
reportError3(err);
|
|
69150
69521
|
}
|
|
69151
69522
|
}
|
|
69152
69523
|
});
|
|
69153
69524
|
|
|
69154
69525
|
// src/commands/winning-ads/follow-competitors.ts
|
|
69155
|
-
import { defineCommand as
|
|
69526
|
+
import { defineCommand as defineCommand247 } from "citty";
|
|
69156
69527
|
var PLATFORMS2 = adLibraryPlatformSchema.options;
|
|
69157
69528
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
69158
69529
|
function buildFollowBatchBody(input) {
|
|
@@ -69185,7 +69556,7 @@ registerSchema({
|
|
|
69185
69556
|
}
|
|
69186
69557
|
}
|
|
69187
69558
|
});
|
|
69188
|
-
var followCompetitorsCommand =
|
|
69559
|
+
var followCompetitorsCommand = defineCommand247({
|
|
69189
69560
|
meta: {
|
|
69190
69561
|
name: "follow-competitors",
|
|
69191
69562
|
description: 'Follow many brands at once by domain \u2014 add every competitor in one call. Example: baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"'
|
|
@@ -69254,13 +69625,13 @@ var followCompetitorsCommand = defineCommand240({
|
|
|
69254
69625
|
}
|
|
69255
69626
|
writeJson({ ok: true, data, hints: hints2.length > 0 ? hints2 : void 0 });
|
|
69256
69627
|
} catch (err) {
|
|
69257
|
-
|
|
69628
|
+
reportError3(err);
|
|
69258
69629
|
}
|
|
69259
69630
|
}
|
|
69260
69631
|
});
|
|
69261
69632
|
|
|
69262
69633
|
// src/commands/winning-ads/following.ts
|
|
69263
|
-
import { defineCommand as
|
|
69634
|
+
import { defineCommand as defineCommand248 } from "citty";
|
|
69264
69635
|
registerSchema({
|
|
69265
69636
|
command: "winning-ads.following",
|
|
69266
69637
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts. A brand still adding has counts that are a lie in progress; one with `discovery_failed` has counts that are short because we couldn't finish looking, which is not the same as it running no ads.",
|
|
@@ -69314,7 +69685,7 @@ function followingNormalizer(record, full) {
|
|
|
69314
69685
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
69315
69686
|
};
|
|
69316
69687
|
}
|
|
69317
|
-
var followingCommand =
|
|
69688
|
+
var followingCommand = defineCommand248({
|
|
69318
69689
|
meta: {
|
|
69319
69690
|
name: "following",
|
|
69320
69691
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. A brand's counts are only final once it is ready. Example: baker winning-ads following --output md"
|
|
@@ -69344,13 +69715,13 @@ var followingCommand = defineCommand241({
|
|
|
69344
69715
|
followingNormalizer
|
|
69345
69716
|
);
|
|
69346
69717
|
} catch (err) {
|
|
69347
|
-
|
|
69718
|
+
reportError3(err);
|
|
69348
69719
|
}
|
|
69349
69720
|
}
|
|
69350
69721
|
});
|
|
69351
69722
|
|
|
69352
69723
|
// src/commands/winning-ads/patterns.ts
|
|
69353
|
-
import { defineCommand as
|
|
69724
|
+
import { defineCommand as defineCommand249 } from "citty";
|
|
69354
69725
|
registerSchema({
|
|
69355
69726
|
command: "winning-ads.patterns",
|
|
69356
69727
|
description: "Mine what separates two cohorts of ads: pass a comma-list of winning ad ids (--winners) and a comma-list of weaker ad ids (--duds). Returns the discriminating DNA fields.",
|
|
@@ -69389,7 +69760,7 @@ function discriminatorRow(record) {
|
|
|
69389
69760
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
69390
69761
|
};
|
|
69391
69762
|
}
|
|
69392
|
-
var patternsCommand =
|
|
69763
|
+
var patternsCommand = defineCommand249({
|
|
69393
69764
|
meta: {
|
|
69394
69765
|
name: "patterns",
|
|
69395
69766
|
description: "Discover what separates winning ads from weak ones. Example: baker winning-ads patterns --winners a_1,a_2,a_3 --duds a_9,a_8 --output md"
|
|
@@ -69439,13 +69810,13 @@ var patternsCommand = defineCommand242({
|
|
|
69439
69810
|
(record) => discriminatorRow(record)
|
|
69440
69811
|
);
|
|
69441
69812
|
} catch (err) {
|
|
69442
|
-
|
|
69813
|
+
reportError3(err);
|
|
69443
69814
|
}
|
|
69444
69815
|
}
|
|
69445
69816
|
});
|
|
69446
69817
|
|
|
69447
69818
|
// src/commands/winning-ads/search.ts
|
|
69448
|
-
import { defineCommand as
|
|
69819
|
+
import { defineCommand as defineCommand250 } from "citty";
|
|
69449
69820
|
registerSchema({
|
|
69450
69821
|
command: "winning-ads.search",
|
|
69451
69822
|
description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
|
|
@@ -69581,9 +69952,9 @@ function reportSearchError(err) {
|
|
|
69581
69952
|
writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
|
|
69582
69953
|
process.exit(1);
|
|
69583
69954
|
}
|
|
69584
|
-
|
|
69955
|
+
reportError3(err);
|
|
69585
69956
|
}
|
|
69586
|
-
var searchCommand5 =
|
|
69957
|
+
var searchCommand5 = defineCommand250({
|
|
69587
69958
|
meta: {
|
|
69588
69959
|
name: "search",
|
|
69589
69960
|
description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
|
|
@@ -69703,7 +70074,7 @@ var searchCommand5 = defineCommand243({
|
|
|
69703
70074
|
});
|
|
69704
70075
|
|
|
69705
70076
|
// src/commands/winning-ads/seeds.ts
|
|
69706
|
-
import { defineCommand as
|
|
70077
|
+
import { defineCommand as defineCommand251 } from "citty";
|
|
69707
70078
|
function leanRow(r) {
|
|
69708
70079
|
return {
|
|
69709
70080
|
key: r.key,
|
|
@@ -69731,7 +70102,7 @@ function makeSeedCommand(opts) {
|
|
|
69731
70102
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
69732
70103
|
}
|
|
69733
70104
|
});
|
|
69734
|
-
return
|
|
70105
|
+
return defineCommand251({
|
|
69735
70106
|
meta: { name: opts.name, description: opts.description },
|
|
69736
70107
|
args: {
|
|
69737
70108
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -69758,7 +70129,7 @@ function makeSeedCommand(opts) {
|
|
|
69758
70129
|
}
|
|
69759
70130
|
writeOutput({ ok: true, data: projected }, output);
|
|
69760
70131
|
} catch (err) {
|
|
69761
|
-
|
|
70132
|
+
reportError3(err);
|
|
69762
70133
|
}
|
|
69763
70134
|
}
|
|
69764
70135
|
});
|
|
@@ -69780,7 +70151,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
69780
70151
|
});
|
|
69781
70152
|
|
|
69782
70153
|
// src/commands/winning-ads/unfollow.ts
|
|
69783
|
-
import { defineCommand as
|
|
70154
|
+
import { defineCommand as defineCommand252 } from "citty";
|
|
69784
70155
|
registerSchema({
|
|
69785
70156
|
command: "winning-ads.unfollow",
|
|
69786
70157
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -69788,7 +70159,7 @@ registerSchema({
|
|
|
69788
70159
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
69789
70160
|
}
|
|
69790
70161
|
});
|
|
69791
|
-
var unfollowCommand =
|
|
70162
|
+
var unfollowCommand = defineCommand252({
|
|
69792
70163
|
meta: {
|
|
69793
70164
|
name: "unfollow",
|
|
69794
70165
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -69803,13 +70174,13 @@ var unfollowCommand = defineCommand245({
|
|
|
69803
70174
|
});
|
|
69804
70175
|
writeJson({ ok: true, data });
|
|
69805
70176
|
} catch (err) {
|
|
69806
|
-
|
|
70177
|
+
reportError3(err);
|
|
69807
70178
|
}
|
|
69808
70179
|
}
|
|
69809
70180
|
});
|
|
69810
70181
|
|
|
69811
70182
|
// src/commands/winning-ads/winners.ts
|
|
69812
|
-
import { defineCommand as
|
|
70183
|
+
import { defineCommand as defineCommand253 } from "citty";
|
|
69813
70184
|
registerSchema({
|
|
69814
70185
|
command: "winning-ads.winners",
|
|
69815
70186
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -69819,7 +70190,7 @@ registerSchema({
|
|
|
69819
70190
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
|
|
69820
70191
|
}
|
|
69821
70192
|
});
|
|
69822
|
-
var winnersCommand =
|
|
70193
|
+
var winnersCommand = defineCommand253({
|
|
69823
70194
|
meta: {
|
|
69824
70195
|
name: "winners",
|
|
69825
70196
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -69863,13 +70234,13 @@ var winnersCommand = defineCommand246({
|
|
|
69863
70234
|
winningAdNormalizer
|
|
69864
70235
|
);
|
|
69865
70236
|
} catch (err) {
|
|
69866
|
-
|
|
70237
|
+
reportError3(err);
|
|
69867
70238
|
}
|
|
69868
70239
|
}
|
|
69869
70240
|
});
|
|
69870
70241
|
|
|
69871
70242
|
// src/commands/winning-ads/index.ts
|
|
69872
|
-
var winningAdsCommand =
|
|
70243
|
+
var winningAdsCommand = defineCommand254({
|
|
69873
70244
|
meta: {
|
|
69874
70245
|
name: "winning-ads",
|
|
69875
70246
|
description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce, and manage the brands your library tracks. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
|
|
@@ -69941,7 +70312,7 @@ function getCliVersion() {
|
|
|
69941
70312
|
}
|
|
69942
70313
|
|
|
69943
70314
|
// src/cli.ts
|
|
69944
|
-
var main =
|
|
70315
|
+
var main = defineCommand255({
|
|
69945
70316
|
meta: {
|
|
69946
70317
|
name: "baker",
|
|
69947
70318
|
version: getCliVersion(),
|
|
@@ -69981,6 +70352,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
69981
70352
|
history: historyCommand2,
|
|
69982
70353
|
hubspot: hubspotCommand,
|
|
69983
70354
|
"winning-ads": winningAdsCommand,
|
|
70355
|
+
"media-sources": mediaSourcesCommand,
|
|
69984
70356
|
mcp: mcpCommand,
|
|
69985
70357
|
schema: schemaCommand2
|
|
69986
70358
|
}
|