@koda-sl/baker-cli 0.382.0 → 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 +42 -8
- package/dist/{chunk-FGHMWBUD.js → chunk-ZW6DHSDG.js} +11 -5
- package/dist/chunk-ZW6DHSDG.js.map +1 -0
- package/dist/cli.js +912 -548
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-FGHMWBUD.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 = {
|
|
@@ -975,9 +975,6 @@ var OBJECTIVE_CAMPAIGN_TYPES = {
|
|
|
975
975
|
ENGAGEMENT: ["SPONSORED_UPDATES", "DYNAMIC"]
|
|
976
976
|
};
|
|
977
977
|
var STAGEABLE_CREATE_STATUSES = ["DRAFT", "ACTIVE", "PAUSED"];
|
|
978
|
-
var CAMPAIGN_GROUP_CREATE_STATUSES = ["DRAFT", "ACTIVE"];
|
|
979
|
-
var CAMPAIGN_GROUP_STATUSES = ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT"];
|
|
980
|
-
var POLITICAL_INTENTS = ["NOT_DECLARED", "NOT_POLITICAL", "POLITICAL"];
|
|
981
978
|
var CREATIVE_INTENDED_STATUSES = ["ACTIVE", "PAUSED", "DRAFT"];
|
|
982
979
|
var CTA_TYPES = [
|
|
983
980
|
"APPLY",
|
|
@@ -1108,26 +1105,17 @@ var entityStatusSchema = z3.enum(["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "D
|
|
|
1108
1105
|
function currencyMinimums(currencyCode) {
|
|
1109
1106
|
return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;
|
|
1110
1107
|
}
|
|
1111
|
-
var
|
|
1108
|
+
var campaignGroupCreateSchema = z3.object({
|
|
1112
1109
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax),
|
|
1113
1110
|
runSchedule: runScheduleSchema,
|
|
1114
1111
|
totalBudget: moneySchema.optional(),
|
|
1115
|
-
status:
|
|
1116
|
-
});
|
|
1117
|
-
var campaignGroupCreateSchema = campaignGroupFieldsSchema.superRefine((p, ctx) => {
|
|
1118
|
-
if (p.totalBudget && !p.runSchedule.end) {
|
|
1119
|
-
ctx.addIssue({
|
|
1120
|
-
code: "custom",
|
|
1121
|
-
path: ["runSchedule", "end"],
|
|
1122
|
-
message: "a group with totalBudget needs runSchedule.end"
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1112
|
+
status: stageableStatusSchema.default("DRAFT")
|
|
1125
1113
|
});
|
|
1126
1114
|
var campaignGroupUpdateSchema = z3.object({
|
|
1127
1115
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax).optional(),
|
|
1128
1116
|
runSchedule: runScheduleSchema.optional(),
|
|
1129
1117
|
totalBudget: moneySchema.optional(),
|
|
1130
|
-
status:
|
|
1118
|
+
status: entityStatusSchema.optional()
|
|
1131
1119
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
1132
1120
|
var campaignFields = {
|
|
1133
1121
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaign.nameMax),
|
|
@@ -1146,7 +1134,6 @@ var campaignFields = {
|
|
|
1146
1134
|
connectedTelevisionOnly: z3.boolean().default(false),
|
|
1147
1135
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1148
1136
|
associatedEntity: z3.string().regex(ORGANIZATION_URN_REGEX).optional(),
|
|
1149
|
-
politicalIntent: z3.enum(POLITICAL_INTENTS).default("NOT_DECLARED"),
|
|
1150
1137
|
status: stageableStatusSchema.default("DRAFT")
|
|
1151
1138
|
};
|
|
1152
1139
|
function validateCampaignBudgets(p, ctx, { requireBudget }) {
|
|
@@ -1204,7 +1191,6 @@ var campaignUpdateSchema = z3.object({
|
|
|
1204
1191
|
offsiteDeliveryEnabled: z3.boolean().optional(),
|
|
1205
1192
|
connectedTelevisionOnly: z3.boolean().optional(),
|
|
1206
1193
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1207
|
-
politicalIntent: z3.enum(POLITICAL_INTENTS).optional(),
|
|
1208
1194
|
status: entityStatusSchema.optional(),
|
|
1209
1195
|
// Create-only on LinkedIn — a live campaign can't change these in place.
|
|
1210
1196
|
// Accepted here only so `draft amend` can carry them into a staged CREATE
|
|
@@ -1830,17 +1816,6 @@ var linkedinDraftOpInputSchema = z3.discriminatedUnion("kind", [
|
|
|
1830
1816
|
updateOp("leadForm.update", leadFormUpdateSchema)
|
|
1831
1817
|
]);
|
|
1832
1818
|
|
|
1833
|
-
// ../api/src/ads-linkedin/search-statuses.ts
|
|
1834
|
-
var LINKEDIN_SEARCH_STATUSES = {
|
|
1835
|
-
campaignGroups: ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"],
|
|
1836
|
-
campaigns: ["ACTIVE", "PAUSED", "ARCHIVED", "COMPLETED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"],
|
|
1837
|
-
creatives: ["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT", "PENDING_DELETION", "REMOVED"]
|
|
1838
|
-
};
|
|
1839
|
-
function unsupportedLinkedinSearchStatuses(level, statuses) {
|
|
1840
|
-
const accepted = LINKEDIN_SEARCH_STATUSES[level];
|
|
1841
|
-
return statuses.filter((status) => !accepted.includes(status));
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
1819
|
// ../api/src/ads-linkedin/wire.ts
|
|
1845
1820
|
import { z as z7 } from "zod";
|
|
1846
1821
|
|
|
@@ -4559,6 +4534,9 @@ var chatChangeTypeSchema = z13.enum([
|
|
|
4559
4534
|
"image",
|
|
4560
4535
|
"video",
|
|
4561
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",
|
|
4562
4540
|
// A landing page saved to the reference library, keyed on the page.
|
|
4563
4541
|
"landing-reference",
|
|
4564
4542
|
// One Studio batch — the takes of one brief, as a set. See convex/lib/validators.ts.
|
|
@@ -6423,6 +6401,10 @@ var imageSourceSchema = z20.enum([
|
|
|
6423
6401
|
"google_testimonial",
|
|
6424
6402
|
"trustpilot_testimonial",
|
|
6425
6403
|
"instagram",
|
|
6404
|
+
"tiktok",
|
|
6405
|
+
"linkedin",
|
|
6406
|
+
"facebook",
|
|
6407
|
+
"google_drive",
|
|
6426
6408
|
"pexels",
|
|
6427
6409
|
"pixabay",
|
|
6428
6410
|
// Retired stock provider — kept so existing library rows stay filterable.
|
|
@@ -8233,7 +8215,9 @@ var videoSourceSchema = z30.enum([
|
|
|
8233
8215
|
"bluesky",
|
|
8234
8216
|
"dailymotion",
|
|
8235
8217
|
"facebook",
|
|
8218
|
+
"google_drive",
|
|
8236
8219
|
"instagram",
|
|
8220
|
+
"linkedin",
|
|
8237
8221
|
"loom",
|
|
8238
8222
|
"newgrounds",
|
|
8239
8223
|
"ok",
|
|
@@ -12127,24 +12111,6 @@ function adCopyHints(payload) {
|
|
|
12127
12111
|
return tells.slice(0, MAX_HINTS).map(hintFor);
|
|
12128
12112
|
}
|
|
12129
12113
|
|
|
12130
|
-
// src/commands/ads/hints.ts
|
|
12131
|
-
function backendHints(envelope) {
|
|
12132
|
-
const hints2 = envelope.hints;
|
|
12133
|
-
return Array.isArray(hints2) ? hints2.filter((hint) => typeof hint === "string") : [];
|
|
12134
|
-
}
|
|
12135
|
-
function withHints(envelope, extra) {
|
|
12136
|
-
const hints2 = [...backendHints(envelope), ...extra];
|
|
12137
|
-
return hints2.length > 0 ? { ...envelope, hints: hints2 } : envelope;
|
|
12138
|
-
}
|
|
12139
|
-
function hintLines(envelope) {
|
|
12140
|
-
return backendHints(envelope).map((hint) => `
|
|
12141
|
-
> ${hint}`).join("");
|
|
12142
|
-
}
|
|
12143
|
-
function splitHints(response) {
|
|
12144
|
-
const { hints: hints2, ...data } = response;
|
|
12145
|
-
return { data, hints: hints2 ?? [] };
|
|
12146
|
-
}
|
|
12147
|
-
|
|
12148
12114
|
// src/commands/ads/google/copy-list-usage.ts
|
|
12149
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"'`;
|
|
12150
12116
|
var COPY_LIST_FLAG = {
|
|
@@ -12152,9 +12118,9 @@ var COPY_LIST_FLAG = {
|
|
|
12152
12118
|
descriptions: "--descriptions",
|
|
12153
12119
|
longHeadlines: "--long-headlines"
|
|
12154
12120
|
};
|
|
12155
|
-
function valueAt(root,
|
|
12121
|
+
function valueAt(root, path49) {
|
|
12156
12122
|
let node = root;
|
|
12157
|
-
for (const key of
|
|
12123
|
+
for (const key of path49) {
|
|
12158
12124
|
if (node === null || typeof node !== "object") return void 0;
|
|
12159
12125
|
node = node[key];
|
|
12160
12126
|
}
|
|
@@ -12387,11 +12353,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
12387
12353
|
function rawTextEntries(value, rawArgs) {
|
|
12388
12354
|
return repeatedValues(rawArgs, "text", value).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
12389
12355
|
}
|
|
12390
|
-
function rawFileEntries(
|
|
12391
|
-
if (typeof
|
|
12356
|
+
function rawFileEntries(path49) {
|
|
12357
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12392
12358
|
return [];
|
|
12393
12359
|
}
|
|
12394
|
-
return readFileSync2(
|
|
12360
|
+
return readFileSync2(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12395
12361
|
}
|
|
12396
12362
|
function keywordEntries(args5, rawArgs) {
|
|
12397
12363
|
const defaultMatch = typeof args5["match-type"] === "string" ? args5["match-type"].toUpperCase() : void 0;
|
|
@@ -12414,14 +12380,14 @@ function keywordEntries(args5, rawArgs) {
|
|
|
12414
12380
|
}
|
|
12415
12381
|
return entries;
|
|
12416
12382
|
}
|
|
12417
|
-
function loadJsonFileArg(
|
|
12418
|
-
if (typeof
|
|
12383
|
+
function loadJsonFileArg(path49) {
|
|
12384
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12419
12385
|
return {};
|
|
12420
12386
|
}
|
|
12421
|
-
const inline =
|
|
12422
|
-
const source = inline ? "inline JSON" :
|
|
12387
|
+
const inline = path49.trimStart().startsWith("{");
|
|
12388
|
+
const source = inline ? "inline JSON" : path49;
|
|
12423
12389
|
try {
|
|
12424
|
-
const parsed = JSON.parse(inline ?
|
|
12390
|
+
const parsed = JSON.parse(inline ? path49 : readFileSync2(path49, "utf8"));
|
|
12425
12391
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12426
12392
|
failWriteValidation(`${source} must contain a JSON object`);
|
|
12427
12393
|
}
|
|
@@ -12509,7 +12475,7 @@ async function stageGoogleOp(raw, hints2) {
|
|
|
12509
12475
|
const chatId = requireChatId();
|
|
12510
12476
|
const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
|
|
12511
12477
|
const allHints = [...noopHints(response.data), ...hints2 ?? [], ...adCopyHints(preflight.data)];
|
|
12512
|
-
writeJsonEnvelope(
|
|
12478
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
12513
12479
|
} catch (err) {
|
|
12514
12480
|
handleGoogleError(err);
|
|
12515
12481
|
}
|
|
@@ -12547,7 +12513,7 @@ async function stageGoogleOps(rawOps, hints2) {
|
|
|
12547
12513
|
const chatId = requireChatId();
|
|
12548
12514
|
const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
|
|
12549
12515
|
const allHints = [...skippedHints(response.data.skipped ?? [], ops.length), ...hints2 ?? [], ...adCopyHints(ops)];
|
|
12550
|
-
writeJsonEnvelope(
|
|
12516
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
12551
12517
|
} catch (err) {
|
|
12552
12518
|
handleGoogleError(err);
|
|
12553
12519
|
}
|
|
@@ -12558,10 +12524,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
12558
12524
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
12559
12525
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
12560
12526
|
}
|
|
12561
|
-
async function draftAction(
|
|
12527
|
+
async function draftAction(path49, body, chat) {
|
|
12562
12528
|
try {
|
|
12563
12529
|
const chatId = resolveChatId(chat);
|
|
12564
|
-
const response = await apiPost(
|
|
12530
|
+
const response = await apiPost(path49, { chatId, ...body });
|
|
12565
12531
|
writeJsonEnvelope(response);
|
|
12566
12532
|
} catch (err) {
|
|
12567
12533
|
handleGoogleError(err);
|
|
@@ -12575,7 +12541,7 @@ async function draftListAction(json, chat) {
|
|
|
12575
12541
|
writeJsonEnvelope(response);
|
|
12576
12542
|
return;
|
|
12577
12543
|
}
|
|
12578
|
-
process.stdout.write(`${renderDraftStatus(response.data)}
|
|
12544
|
+
process.stdout.write(`${renderDraftStatus(response.data)}
|
|
12579
12545
|
`);
|
|
12580
12546
|
} catch (err) {
|
|
12581
12547
|
handleGoogleError(err);
|
|
@@ -14979,14 +14945,14 @@ function mappingRowProblem(row) {
|
|
|
14979
14945
|
|
|
14980
14946
|
// ../api/src/event-sources/template.ts
|
|
14981
14947
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
14982
|
-
function mentionOf(
|
|
14983
|
-
return `{{${
|
|
14948
|
+
function mentionOf(path49) {
|
|
14949
|
+
return `{{${path49}}}`;
|
|
14984
14950
|
}
|
|
14985
14951
|
function templateMentions(template) {
|
|
14986
14952
|
const seen = [];
|
|
14987
14953
|
for (const match of template.matchAll(MENTION)) {
|
|
14988
|
-
const
|
|
14989
|
-
if (
|
|
14954
|
+
const path49 = (match[1] ?? "").trim();
|
|
14955
|
+
if (path49 !== "" && !seen.includes(path49)) seen.push(path49);
|
|
14990
14956
|
}
|
|
14991
14957
|
return seen;
|
|
14992
14958
|
}
|
|
@@ -18341,17 +18307,17 @@ function ignoredColumnHints(columns) {
|
|
|
18341
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.`
|
|
18342
18308
|
];
|
|
18343
18309
|
}
|
|
18344
|
-
function readRowsFile(
|
|
18345
|
-
const inline =
|
|
18310
|
+
function readRowsFile(path49) {
|
|
18311
|
+
const inline = path49.trimStart().startsWith("[") || path49.trimStart().startsWith("{");
|
|
18346
18312
|
let text2;
|
|
18347
18313
|
try {
|
|
18348
|
-
text2 = inline ?
|
|
18314
|
+
text2 = inline ? path49 : readFileSync4(path49, "utf8");
|
|
18349
18315
|
} catch (err) {
|
|
18350
|
-
failWriteValidation(`could not read ${
|
|
18316
|
+
failWriteValidation(`could not read ${path49}: ${err instanceof Error ? err.message : String(err)}`);
|
|
18351
18317
|
}
|
|
18352
18318
|
const parsed = parseConversionRowsText(text2);
|
|
18353
18319
|
if (!parsed.ok) {
|
|
18354
|
-
failWriteValidation(`${inline ? "the conversions passed inline" :
|
|
18320
|
+
failWriteValidation(`${inline ? "the conversions passed inline" : path49}: ${parsed.error}`);
|
|
18355
18321
|
}
|
|
18356
18322
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
18357
18323
|
}
|
|
@@ -20109,6 +20075,10 @@ Full guide: __tooling__/docs/tools/baker/ads-google.md`
|
|
|
20109
20075
|
// src/commands/ads/linkedin/index.ts
|
|
20110
20076
|
import { defineCommand as defineCommand53 } from "citty";
|
|
20111
20077
|
|
|
20078
|
+
// src/commands/ads/linkedin/write-shared.ts
|
|
20079
|
+
import { createHash } from "crypto";
|
|
20080
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
20081
|
+
|
|
20112
20082
|
// src/commands/ads/linkedin/shared.ts
|
|
20113
20083
|
var DAY_MS2 = 864e5;
|
|
20114
20084
|
function handleLinkedinError(err) {
|
|
@@ -20201,48 +20171,18 @@ function daysAgoIso2(days) {
|
|
|
20201
20171
|
function csvOrJson2(args5) {
|
|
20202
20172
|
return args5.output ?? "json";
|
|
20203
20173
|
}
|
|
20204
|
-
function
|
|
20205
|
-
return `CSV of statuses (${LINKEDIN_SEARCH_STATUSES[level].join(",")})`;
|
|
20206
|
-
}
|
|
20207
|
-
function statusFilterError(level, statuses) {
|
|
20208
|
-
const unsupported = unsupportedLinkedinSearchStatuses(level, statuses);
|
|
20209
|
-
if (unsupported.length === 0) {
|
|
20210
|
-
return null;
|
|
20211
|
-
}
|
|
20212
|
-
const accepted = LINKEDIN_SEARCH_STATUSES[level].join(",");
|
|
20213
|
-
return {
|
|
20214
|
-
ok: false,
|
|
20215
|
-
error: {
|
|
20216
|
-
code: "INVALID_STATUS",
|
|
20217
|
-
message: `LinkedIn does not accept status ${unsupported.join(", ")} for this listing.`,
|
|
20218
|
-
fix: {
|
|
20219
|
-
action: "retry_with_flag",
|
|
20220
|
-
explanation: `Re-run with --statuses from ${accepted}, or --all-statuses to drop the filter.`
|
|
20221
|
-
},
|
|
20222
|
-
retryable: false
|
|
20223
|
-
}
|
|
20224
|
-
};
|
|
20225
|
-
}
|
|
20226
|
-
function resolveStatusFilter(args5, level) {
|
|
20174
|
+
function resolveStatusFilter(args5) {
|
|
20227
20175
|
if (args5["all-statuses"]) {
|
|
20228
20176
|
return void 0;
|
|
20229
20177
|
}
|
|
20230
20178
|
const explicit = args5.statuses;
|
|
20231
|
-
if (
|
|
20232
|
-
return
|
|
20233
|
-
}
|
|
20234
|
-
const statuses = explicit.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
20235
|
-
const error = statusFilterError(level, statuses);
|
|
20236
|
-
if (error) {
|
|
20237
|
-
writeAdsJson(error);
|
|
20238
|
-
process.exit(1);
|
|
20179
|
+
if (explicit) {
|
|
20180
|
+
return explicit.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
20239
20181
|
}
|
|
20240
|
-
return
|
|
20182
|
+
return ["ACTIVE"];
|
|
20241
20183
|
}
|
|
20242
20184
|
|
|
20243
20185
|
// src/commands/ads/linkedin/write-shared.ts
|
|
20244
|
-
import { createHash } from "crypto";
|
|
20245
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
20246
20186
|
var TOTAL_BUDGET_HELP = "Lifetime budget \u2014 on something already running it must exceed spend to date, or LinkedIn rejects it";
|
|
20247
20187
|
function bareAccountId(args5) {
|
|
20248
20188
|
const raw = resolveAccountIdArg2(args5);
|
|
@@ -20252,19 +20192,19 @@ function failWriteValidation2(message) {
|
|
|
20252
20192
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
20253
20193
|
process.exit(1);
|
|
20254
20194
|
}
|
|
20255
|
-
function loadJsonFileArg2(
|
|
20256
|
-
if (typeof
|
|
20195
|
+
function loadJsonFileArg2(path49) {
|
|
20196
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20257
20197
|
return {};
|
|
20258
20198
|
}
|
|
20259
20199
|
try {
|
|
20260
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20200
|
+
const parsed = JSON.parse(readFileSync5(path49, "utf8"));
|
|
20261
20201
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
20262
|
-
failWriteValidation2(`${
|
|
20202
|
+
failWriteValidation2(`${path49} must contain a JSON object`);
|
|
20263
20203
|
}
|
|
20264
20204
|
return parsed;
|
|
20265
20205
|
} catch (err) {
|
|
20266
20206
|
if (err instanceof SyntaxError) {
|
|
20267
|
-
failWriteValidation2(`${
|
|
20207
|
+
failWriteValidation2(`${path49} is not valid JSON: ${err.message}`);
|
|
20268
20208
|
}
|
|
20269
20209
|
throw err;
|
|
20270
20210
|
}
|
|
@@ -20349,15 +20289,15 @@ function parseLocaleFlag(value) {
|
|
|
20349
20289
|
}
|
|
20350
20290
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
20351
20291
|
}
|
|
20352
|
-
function loadTargetingFileArg(
|
|
20353
|
-
if (typeof
|
|
20292
|
+
function loadTargetingFileArg(path49) {
|
|
20293
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20354
20294
|
return void 0;
|
|
20355
20295
|
}
|
|
20356
|
-
const parsed = loadJsonFileArg2(
|
|
20296
|
+
const parsed = loadJsonFileArg2(path49);
|
|
20357
20297
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
20358
20298
|
if (!criteria.include) {
|
|
20359
20299
|
failWriteValidation2(
|
|
20360
|
-
`${
|
|
20300
|
+
`${path49} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
20361
20301
|
);
|
|
20362
20302
|
}
|
|
20363
20303
|
return criteria;
|
|
@@ -20392,14 +20332,14 @@ function parseCsvLine(line) {
|
|
|
20392
20332
|
cells.push(current);
|
|
20393
20333
|
return cells.map((cell3) => cell3.trim());
|
|
20394
20334
|
}
|
|
20395
|
-
function parseListFileArg(
|
|
20396
|
-
if (typeof
|
|
20335
|
+
function parseListFileArg(path49, maxRows) {
|
|
20336
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20397
20337
|
return void 0;
|
|
20398
20338
|
}
|
|
20399
|
-
const raw = readFileSync5(
|
|
20339
|
+
const raw = readFileSync5(path49, "utf8");
|
|
20400
20340
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
20401
20341
|
if (lines.length < 2) {
|
|
20402
|
-
failWriteValidation2(`${
|
|
20342
|
+
failWriteValidation2(`${path49} needs a header row and at least one data row`);
|
|
20403
20343
|
}
|
|
20404
20344
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
20405
20345
|
const rows = [];
|
|
@@ -20418,7 +20358,7 @@ function parseListFileArg(path48, maxRows) {
|
|
|
20418
20358
|
}
|
|
20419
20359
|
}
|
|
20420
20360
|
if (rows.length > maxRows) {
|
|
20421
|
-
failWriteValidation2(`${
|
|
20361
|
+
failWriteValidation2(`${path49} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
20422
20362
|
}
|
|
20423
20363
|
return { columns, rows };
|
|
20424
20364
|
}
|
|
@@ -20450,7 +20390,7 @@ async function stageOp(raw, hints2) {
|
|
|
20450
20390
|
op: preflight.data
|
|
20451
20391
|
});
|
|
20452
20392
|
const allHints = [...batchNudge(response.data), ...hints2 ?? [], ...adCopyHints(preflight.data)];
|
|
20453
|
-
writeJsonEnvelope(
|
|
20393
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
20454
20394
|
} catch (err) {
|
|
20455
20395
|
handleLinkedinError(err);
|
|
20456
20396
|
}
|
|
@@ -20477,7 +20417,7 @@ async function stageLinkedinOps(rawOps, hints2) {
|
|
|
20477
20417
|
const chatId = requireChatId();
|
|
20478
20418
|
const response = await apiPost("/api/ads/linkedin/draft/stage-batch", { chatId, ops });
|
|
20479
20419
|
const allHints = [...hints2 ?? [], ...adCopyHints(ops)];
|
|
20480
|
-
writeJsonEnvelope(
|
|
20420
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
20481
20421
|
} catch (err) {
|
|
20482
20422
|
handleLinkedinError(err);
|
|
20483
20423
|
}
|
|
@@ -20514,11 +20454,11 @@ function readPositionals(args5) {
|
|
|
20514
20454
|
function splitIdList(raw) {
|
|
20515
20455
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
20516
20456
|
}
|
|
20517
|
-
function idsFileEntries(
|
|
20518
|
-
if (typeof
|
|
20457
|
+
function idsFileEntries(path49) {
|
|
20458
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20519
20459
|
return [];
|
|
20520
20460
|
}
|
|
20521
|
-
return readFileSync5(
|
|
20461
|
+
return readFileSync5(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
20522
20462
|
}
|
|
20523
20463
|
function requireTargets(args5, entity) {
|
|
20524
20464
|
const positionals = readPositionals(args5);
|
|
@@ -20569,7 +20509,7 @@ registerSchema({
|
|
|
20569
20509
|
"account-id": { type: "string", description: "Account ID", required: false },
|
|
20570
20510
|
"account-urn": { type: "string", description: "Alias for --account-id", required: false },
|
|
20571
20511
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20572
|
-
statuses: { type: "string", description:
|
|
20512
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20573
20513
|
limit: { type: "string", description: "Max rows (default 500)", required: false },
|
|
20574
20514
|
"no-cache": NO_CACHE_ARG,
|
|
20575
20515
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20583,7 +20523,7 @@ registerSchema({
|
|
|
20583
20523
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20584
20524
|
"campaign-group-id": { type: "string", description: "Filter by campaign group", required: false },
|
|
20585
20525
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20586
|
-
statuses: { type: "string", description:
|
|
20526
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20587
20527
|
limit: { type: "string", description: "Max rows", required: false },
|
|
20588
20528
|
"no-cache": NO_CACHE_ARG,
|
|
20589
20529
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20597,7 +20537,7 @@ registerSchema({
|
|
|
20597
20537
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20598
20538
|
"campaign-id": { type: "string", description: "Filter by campaign", required: false },
|
|
20599
20539
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20600
|
-
statuses: { type: "string", description:
|
|
20540
|
+
statuses: { type: "string", description: "CSV of statuses", required: false },
|
|
20601
20541
|
fields: {
|
|
20602
20542
|
type: "string",
|
|
20603
20543
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage",
|
|
@@ -20870,11 +20810,7 @@ registerSchema({
|
|
|
20870
20810
|
description: "3-letter currency code (defaults to the ad account currency)",
|
|
20871
20811
|
required: false
|
|
20872
20812
|
},
|
|
20873
|
-
status: {
|
|
20874
|
-
type: "string",
|
|
20875
|
-
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED",
|
|
20876
|
-
required: false
|
|
20877
|
-
},
|
|
20813
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
|
|
20878
20814
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20879
20815
|
}
|
|
20880
20816
|
});
|
|
@@ -20932,16 +20868,7 @@ registerSchema({
|
|
|
20932
20868
|
ctv: { type: "string", description: "Connected TV on|off (default off)", required: false },
|
|
20933
20869
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20934
20870
|
"associated-entity": { type: "string", description: "Organization URN", required: false },
|
|
20935
|
-
"
|
|
20936
|
-
type: "string",
|
|
20937
|
-
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",
|
|
20938
|
-
required: false
|
|
20939
|
-
},
|
|
20940
|
-
status: {
|
|
20941
|
-
type: "string",
|
|
20942
|
-
description: "DRAFT|ACTIVE|PAUSED (default DRAFT) \u2014 PAUSED needs a group that is not DRAFT",
|
|
20943
|
-
required: false
|
|
20944
|
-
},
|
|
20871
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
|
|
20945
20872
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20946
20873
|
}
|
|
20947
20874
|
});
|
|
@@ -20969,11 +20896,6 @@ registerSchema({
|
|
|
20969
20896
|
lan: { type: "string", description: "on|off", required: false },
|
|
20970
20897
|
ctv: { type: "string", description: "on|off", required: false },
|
|
20971
20898
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20972
|
-
"political-intent": {
|
|
20973
|
-
type: "string",
|
|
20974
|
-
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",
|
|
20975
|
-
required: false
|
|
20976
|
-
},
|
|
20977
20899
|
status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED", required: false },
|
|
20978
20900
|
file: { type: "string", description: "JSON file with fields to change", required: false }
|
|
20979
20901
|
}
|
|
@@ -21369,8 +21291,7 @@ var campaignGroupsCreateCommand = defineCommand33({
|
|
|
21369
21291
|
meta: {
|
|
21370
21292
|
name: "create",
|
|
21371
21293
|
description: `Stage a new campaign group. ${STAGED_NOTE}
|
|
21372
|
-
|
|
21373
|
-
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`
|
|
21374
21295
|
},
|
|
21375
21296
|
args: {
|
|
21376
21297
|
...accountArgs,
|
|
@@ -21379,10 +21300,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
|
|
|
21379
21300
|
end: { type: "string", description: "Run schedule end" },
|
|
21380
21301
|
"total-budget": { type: "string", description: TOTAL_BUDGET_HELP },
|
|
21381
21302
|
currency: { type: "string", description: "3-letter currency code (defaults to the ad account currency)" },
|
|
21382
|
-
status: {
|
|
21383
|
-
type: "string",
|
|
21384
|
-
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED; pause it once it exists"
|
|
21385
|
-
},
|
|
21303
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)" },
|
|
21386
21304
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21387
21305
|
},
|
|
21388
21306
|
run: async ({ args: args5 }) => {
|
|
@@ -21448,11 +21366,9 @@ function campaignPayloadFromFlags(args5) {
|
|
|
21448
21366
|
connectedTelevisionOnly: parseOnOffFlag(args5.ctv, "--ctv"),
|
|
21449
21367
|
creativeSelection: args5["creative-selection"] ? String(args5["creative-selection"]).toUpperCase() : void 0,
|
|
21450
21368
|
associatedEntity: args5["associated-entity"],
|
|
21451
|
-
politicalIntent: args5["political-intent"] ? String(args5["political-intent"]).toUpperCase() : void 0,
|
|
21452
21369
|
status: args5.status ? String(args5.status).toUpperCase() : void 0
|
|
21453
21370
|
};
|
|
21454
21371
|
}
|
|
21455
|
-
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."`;
|
|
21456
21372
|
var campaignFlagArgs = {
|
|
21457
21373
|
...accountArgs,
|
|
21458
21374
|
name: { type: "string", description: "Campaign name (\u2264255 chars)" },
|
|
@@ -21473,8 +21389,7 @@ var campaignFlagArgs = {
|
|
|
21473
21389
|
ctv: { type: "string", description: "Connected TV on|off" },
|
|
21474
21390
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN" },
|
|
21475
21391
|
"associated-entity": { type: "string", description: "Organization URN" },
|
|
21476
|
-
|
|
21477
|
-
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED \u2014 PAUSED needs a group that is not DRAFT" },
|
|
21392
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED" },
|
|
21478
21393
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21479
21394
|
};
|
|
21480
21395
|
var campaignsCreateCommand = defineCommand33({
|
|
@@ -22991,7 +22906,7 @@ var listArgs = {
|
|
|
22991
22906
|
"account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
|
|
22992
22907
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
22993
22908
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
22994
|
-
statuses: { type: "string", description:
|
|
22909
|
+
statuses: { type: "string", description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)" },
|
|
22995
22910
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
22996
22911
|
"no-cache": NO_CACHE_ARG,
|
|
22997
22912
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -23006,7 +22921,7 @@ var campaignGroupsListCommand = defineCommand40({
|
|
|
23006
22921
|
const accountId = resolveAccountIdArg2(args5);
|
|
23007
22922
|
try {
|
|
23008
22923
|
const params = { "account-id": accountId };
|
|
23009
|
-
const statuses = resolveStatusFilter(args5
|
|
22924
|
+
const statuses = resolveStatusFilter(args5);
|
|
23010
22925
|
if (statuses) params.statuses = statuses.join(",");
|
|
23011
22926
|
if (args5.limit) params.limit = String(args5.limit);
|
|
23012
22927
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
@@ -23057,7 +22972,7 @@ var listArgs2 = {
|
|
|
23057
22972
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
23058
22973
|
"campaign-group-id": { type: "string", description: "Filter by campaign group" },
|
|
23059
22974
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
23060
|
-
statuses: { type: "string", description:
|
|
22975
|
+
statuses: { type: "string", description: "CSV of statuses" },
|
|
23061
22976
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
23062
22977
|
"no-cache": NO_CACHE_ARG,
|
|
23063
22978
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -23072,7 +22987,7 @@ var campaignsListCommand = defineCommand41({
|
|
|
23072
22987
|
const accountId = resolveAccountIdArg2(args5);
|
|
23073
22988
|
try {
|
|
23074
22989
|
const params = { "account-id": accountId };
|
|
23075
|
-
const statuses = resolveStatusFilter(args5
|
|
22990
|
+
const statuses = resolveStatusFilter(args5);
|
|
23076
22991
|
if (statuses) params.statuses = statuses.join(",");
|
|
23077
22992
|
if (args5["campaign-group-id"]) params["campaign-group-id"] = String(args5["campaign-group-id"]);
|
|
23078
22993
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -23305,9 +23220,9 @@ import { defineCommand as defineCommand44 } from "citty";
|
|
|
23305
23220
|
function asRecord(value) {
|
|
23306
23221
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
23307
23222
|
}
|
|
23308
|
-
function readPath2(row,
|
|
23223
|
+
function readPath2(row, path49) {
|
|
23309
23224
|
let current = row;
|
|
23310
|
-
for (const segment of
|
|
23225
|
+
for (const segment of path49.split(".")) {
|
|
23311
23226
|
const record = asRecord(current);
|
|
23312
23227
|
if (!record) return void 0;
|
|
23313
23228
|
current = record[segment];
|
|
@@ -23317,10 +23232,10 @@ function readPath2(row, path48) {
|
|
|
23317
23232
|
function projectFields(rows, paths) {
|
|
23318
23233
|
return rows.map((row) => {
|
|
23319
23234
|
const projected = {};
|
|
23320
|
-
for (const
|
|
23321
|
-
const value = readPath2(row,
|
|
23235
|
+
for (const path49 of paths) {
|
|
23236
|
+
const value = readPath2(row, path49);
|
|
23322
23237
|
if (value !== void 0) {
|
|
23323
|
-
projected[
|
|
23238
|
+
projected[path49] = value;
|
|
23324
23239
|
}
|
|
23325
23240
|
}
|
|
23326
23241
|
return projected;
|
|
@@ -23333,16 +23248,16 @@ function shapeListRows(rows, args5, compact4) {
|
|
|
23333
23248
|
const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
|
|
23334
23249
|
if (paths.length > 0) {
|
|
23335
23250
|
const projected = projectFields(raw, paths).map((row, i) => {
|
|
23336
|
-
const missing = paths.filter((
|
|
23251
|
+
const missing = paths.filter((path49) => row[path49] === void 0);
|
|
23337
23252
|
const source = rows[i];
|
|
23338
23253
|
if (missing.length === 0 || source === void 0) return row;
|
|
23339
23254
|
const compactRow3 = compact4.row(source);
|
|
23340
|
-
for (const
|
|
23341
|
-
if (compactRow3[
|
|
23255
|
+
for (const path49 of missing) {
|
|
23256
|
+
if (compactRow3[path49] !== void 0) row[path49] = compactRow3[path49];
|
|
23342
23257
|
}
|
|
23343
23258
|
return row;
|
|
23344
23259
|
});
|
|
23345
|
-
const unmatched = paths.filter((
|
|
23260
|
+
const unmatched = paths.filter((path49) => projected.every((row) => row[path49] === void 0));
|
|
23346
23261
|
if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
|
|
23347
23262
|
const carried = /* @__PURE__ */ new Set([...compact4.columns, ...raw.flatMap((row) => Object.keys(row))]);
|
|
23348
23263
|
return {
|
|
@@ -23422,7 +23337,7 @@ var listArgs3 = {
|
|
|
23422
23337
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
23423
23338
|
"campaign-id": { type: "string", description: "Filter by campaign ID" },
|
|
23424
23339
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
23425
|
-
statuses: { type: "string", description:
|
|
23340
|
+
statuses: { type: "string", description: "CSV of intended statuses (ACTIVE,PAUSED,DRAFT,ARCHIVED)" },
|
|
23426
23341
|
fields: {
|
|
23427
23342
|
type: "string",
|
|
23428
23343
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage"
|
|
@@ -23442,7 +23357,7 @@ var creativesListCommand = defineCommand44({
|
|
|
23442
23357
|
const accountId = resolveAccountIdArg2(args5);
|
|
23443
23358
|
try {
|
|
23444
23359
|
const params = { "account-id": accountId };
|
|
23445
|
-
const statuses = resolveStatusFilter(args5
|
|
23360
|
+
const statuses = resolveStatusFilter(args5);
|
|
23446
23361
|
if (statuses) params.statuses = statuses.join(",");
|
|
23447
23362
|
if (args5["campaign-id"]) params["campaign-id"] = String(args5["campaign-id"]);
|
|
23448
23363
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -23749,7 +23664,7 @@ async function listDraft(json, chat) {
|
|
|
23749
23664
|
writeJsonEnvelope(response);
|
|
23750
23665
|
return;
|
|
23751
23666
|
}
|
|
23752
|
-
process.stdout.write(`${renderDraftStatus2(response.data)}
|
|
23667
|
+
process.stdout.write(`${renderDraftStatus2(response.data)}
|
|
23753
23668
|
`);
|
|
23754
23669
|
} catch (err) {
|
|
23755
23670
|
handleLinkedinError(err);
|
|
@@ -24712,54 +24627,54 @@ function buildCustomConversionRule(input) {
|
|
|
24712
24627
|
function customConversionRuleRefusal(rule) {
|
|
24713
24628
|
return ruleNodeRefusal(rule, "rule");
|
|
24714
24629
|
}
|
|
24715
|
-
function branchRefusal(key, value,
|
|
24630
|
+
function branchRefusal(key, value, path49) {
|
|
24716
24631
|
if (!Array.isArray(value) || value.length === 0) {
|
|
24717
|
-
return `${
|
|
24632
|
+
return `${path49}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
24718
24633
|
}
|
|
24719
24634
|
for (const [index, child] of value.entries()) {
|
|
24720
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
24635
|
+
const refusal = ruleNodeRefusal(child, `${path49}.${key}[${index}]`);
|
|
24721
24636
|
if (refusal) {
|
|
24722
24637
|
return refusal;
|
|
24723
24638
|
}
|
|
24724
24639
|
}
|
|
24725
24640
|
return void 0;
|
|
24726
24641
|
}
|
|
24727
|
-
function conditionRefusal(key, value,
|
|
24728
|
-
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);
|
|
24729
24644
|
}
|
|
24730
|
-
function ruleNodeRefusal(node,
|
|
24645
|
+
function ruleNodeRefusal(node, path49) {
|
|
24731
24646
|
if (!isRecord2(node)) {
|
|
24732
|
-
return `${
|
|
24647
|
+
return `${path49} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
24733
24648
|
}
|
|
24734
24649
|
const entries = Object.entries(node);
|
|
24735
24650
|
if (entries.length === 0) {
|
|
24736
|
-
return `${
|
|
24651
|
+
return `${path49} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
24737
24652
|
}
|
|
24738
24653
|
if (entries.length > 1) {
|
|
24739
|
-
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]}`;
|
|
24740
24655
|
}
|
|
24741
24656
|
for (const [key, value] of entries) {
|
|
24742
|
-
const refusal = conditionRefusal(key, value,
|
|
24657
|
+
const refusal = conditionRefusal(key, value, path49);
|
|
24743
24658
|
if (refusal) {
|
|
24744
24659
|
return refusal;
|
|
24745
24660
|
}
|
|
24746
24661
|
}
|
|
24747
24662
|
return void 0;
|
|
24748
24663
|
}
|
|
24749
|
-
function leafRefusal(field, condition,
|
|
24664
|
+
function leafRefusal(field, condition, path49) {
|
|
24750
24665
|
if (!isRecord2(condition)) {
|
|
24751
|
-
return `${
|
|
24666
|
+
return `${path49}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
24752
24667
|
}
|
|
24753
24668
|
const tests = Object.entries(condition);
|
|
24754
24669
|
if (tests.length === 0) {
|
|
24755
|
-
return `${
|
|
24670
|
+
return `${path49}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
24756
24671
|
}
|
|
24757
24672
|
if (tests.length > 1) {
|
|
24758
|
-
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]}`;
|
|
24759
24674
|
}
|
|
24760
24675
|
for (const [operator] of tests) {
|
|
24761
24676
|
if (!RULE_OPERATORS[operator]) {
|
|
24762
|
-
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)`;
|
|
24763
24678
|
}
|
|
24764
24679
|
}
|
|
24765
24680
|
return void 0;
|
|
@@ -25475,11 +25390,11 @@ var updateStatusSchema = z37.enum(UPDATE_STATUSES);
|
|
|
25475
25390
|
function currencyMinimums2(currencyCode) {
|
|
25476
25391
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
25477
25392
|
}
|
|
25478
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
25393
|
+
function validateDailyBudgetFloor(money, ctx, path49) {
|
|
25479
25394
|
if (money?.currencyCode) {
|
|
25480
25395
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
25481
25396
|
if (Number(money.amount) < min) {
|
|
25482
|
-
ctx.addIssue({ code: "custom", path:
|
|
25397
|
+
ctx.addIssue({ code: "custom", path: path49, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
25483
25398
|
}
|
|
25484
25399
|
}
|
|
25485
25400
|
}
|
|
@@ -26351,19 +26266,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
26351
26266
|
);
|
|
26352
26267
|
}
|
|
26353
26268
|
}
|
|
26354
|
-
function loadJsonFileArg3(
|
|
26355
|
-
if (typeof
|
|
26269
|
+
function loadJsonFileArg3(path49) {
|
|
26270
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
26356
26271
|
return {};
|
|
26357
26272
|
}
|
|
26358
26273
|
try {
|
|
26359
|
-
const parsed = JSON.parse(readFileSync9(
|
|
26274
|
+
const parsed = JSON.parse(readFileSync9(path49, "utf8"));
|
|
26360
26275
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
26361
|
-
failWriteValidation3(`${
|
|
26276
|
+
failWriteValidation3(`${path49} must contain a JSON object`);
|
|
26362
26277
|
}
|
|
26363
26278
|
return parsed;
|
|
26364
26279
|
} catch (err) {
|
|
26365
26280
|
if (err instanceof SyntaxError) {
|
|
26366
|
-
failWriteValidation3(`${
|
|
26281
|
+
failWriteValidation3(`${path49} is not valid JSON: ${err.message}`);
|
|
26367
26282
|
}
|
|
26368
26283
|
throw err;
|
|
26369
26284
|
}
|
|
@@ -26454,7 +26369,7 @@ async function stageOp2(raw) {
|
|
|
26454
26369
|
const chatId = requireChatId();
|
|
26455
26370
|
const response = await apiPost("/api/ads/meta/draft/stage", { chatId, op: preflight.data });
|
|
26456
26371
|
const copyHints = adCopyHints(preflight.data);
|
|
26457
|
-
writeJsonEnvelope(
|
|
26372
|
+
writeJsonEnvelope(copyHints.length > 0 ? { ...response, hints: copyHints } : response);
|
|
26458
26373
|
} catch (err) {
|
|
26459
26374
|
handleMetaError(err);
|
|
26460
26375
|
}
|
|
@@ -27727,7 +27642,7 @@ async function listDraft2(json, chat) {
|
|
|
27727
27642
|
writeJsonEnvelope(response);
|
|
27728
27643
|
return;
|
|
27729
27644
|
}
|
|
27730
|
-
process.stdout.write(`${renderDraftStatus3(response.data)}
|
|
27645
|
+
process.stdout.write(`${renderDraftStatus3(response.data)}
|
|
27731
27646
|
`);
|
|
27732
27647
|
} catch (err) {
|
|
27733
27648
|
handleMetaError(err);
|
|
@@ -32059,12 +31974,12 @@ function flowExists(slug) {
|
|
|
32059
31974
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
32060
31975
|
}
|
|
32061
31976
|
function readFlowTree(slug) {
|
|
32062
|
-
const
|
|
32063
|
-
if (!existsSync3(
|
|
31977
|
+
const path49 = join2(flowsDir(), slug, "_data.json");
|
|
31978
|
+
if (!existsSync3(path49)) {
|
|
32064
31979
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
32065
31980
|
}
|
|
32066
31981
|
try {
|
|
32067
|
-
return JSON.parse(readFileSync11(
|
|
31982
|
+
return JSON.parse(readFileSync11(path49, "utf-8"));
|
|
32068
31983
|
} catch (error) {
|
|
32069
31984
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
32070
31985
|
}
|
|
@@ -33024,12 +32939,12 @@ function readPeopleFile(args5) {
|
|
|
33024
32939
|
}
|
|
33025
32940
|
function unreadablePeopleFile(args5) {
|
|
33026
32941
|
if (!args5["people-file"]) return void 0;
|
|
33027
|
-
const
|
|
32942
|
+
const path49 = String(args5["people-file"]);
|
|
33028
32943
|
try {
|
|
33029
|
-
readFileSync12(
|
|
32944
|
+
readFileSync12(path49, "utf8");
|
|
33030
32945
|
return void 0;
|
|
33031
32946
|
} catch {
|
|
33032
|
-
return `Couldn't read --people-file ${
|
|
32947
|
+
return `Couldn't read --people-file ${path49}. Check the path, or pass the people inline with --person.`;
|
|
33033
32948
|
}
|
|
33034
32949
|
}
|
|
33035
32950
|
function peopleLimitError(args5) {
|
|
@@ -34001,11 +33916,11 @@ function parseFieldArgs(argv) {
|
|
|
34001
33916
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
34002
33917
|
const eq = pair.indexOf("=");
|
|
34003
33918
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
34004
|
-
const
|
|
33919
|
+
const path49 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
34005
33920
|
const problem = mappingRowProblem(field);
|
|
34006
33921
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
34007
|
-
if (
|
|
34008
|
-
mapping[field] =
|
|
33922
|
+
if (path49 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
33923
|
+
mapping[field] = path49;
|
|
34009
33924
|
}
|
|
34010
33925
|
return mapping;
|
|
34011
33926
|
}
|
|
@@ -35607,11 +35522,11 @@ function unwrap(response) {
|
|
|
35607
35522
|
}
|
|
35608
35523
|
return response.data;
|
|
35609
35524
|
}
|
|
35610
|
-
async function readAvatars(
|
|
35611
|
-
return unwrap(await apiGet(
|
|
35525
|
+
async function readAvatars(path49, params) {
|
|
35526
|
+
return unwrap(await apiGet(path49, params));
|
|
35612
35527
|
}
|
|
35613
|
-
async function writeAvatars(
|
|
35614
|
-
return unwrap(await apiPost(
|
|
35528
|
+
async function writeAvatars(path49, body) {
|
|
35529
|
+
return unwrap(await apiPost(path49, body));
|
|
35615
35530
|
}
|
|
35616
35531
|
|
|
35617
35532
|
// src/commands/avatars/create.ts
|
|
@@ -36520,12 +36435,12 @@ function missingFontFiles(urls, available) {
|
|
|
36520
36435
|
function planFontAdoption(sources, families) {
|
|
36521
36436
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
36522
36437
|
const byFamily = /* @__PURE__ */ new Map();
|
|
36523
|
-
for (const { path:
|
|
36524
|
-
const dir = posix.dirname(
|
|
36438
|
+
for (const { path: path49, source } of sources) {
|
|
36439
|
+
const dir = posix.dirname(path49);
|
|
36525
36440
|
for (const face of declaredFontFaces(source)) {
|
|
36526
36441
|
if (!wanted.has(face.family)) continue;
|
|
36527
36442
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
36528
|
-
perFile.set(
|
|
36443
|
+
perFile.set(path49, [...perFile.get(path49) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
36529
36444
|
byFamily.set(face.family, perFile);
|
|
36530
36445
|
}
|
|
36531
36446
|
}
|
|
@@ -40790,18 +40705,10 @@ function dropUncastVoices(nodes) {
|
|
|
40790
40705
|
if (node && node.type === "voice_select" && !referenced.has(node.id)) nodes.splice(i, 1);
|
|
40791
40706
|
}
|
|
40792
40707
|
}
|
|
40793
|
-
function
|
|
40794
|
-
if (requested !== "reuse") return void 0;
|
|
40795
|
-
const showsPeople = (blueprint.global?.cast ?? []).length > 0 || elements.some((e) => e.type.toLowerCase() === "person");
|
|
40796
|
-
if (!showsPeople) return void 0;
|
|
40797
|
-
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.";
|
|
40798
|
-
}
|
|
40799
|
-
function scaffoldVideoCanvas(input, elementsInput, requested) {
|
|
40708
|
+
function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
40800
40709
|
const blueprint = VideoBlueprint.parse(input);
|
|
40801
40710
|
injectHookPhysicality(blueprint);
|
|
40802
40711
|
const elements = RecurringElements.parse(elementsInput);
|
|
40803
|
-
const reuseRefused = framesReuseRefusal(blueprint, elements, requested.frames);
|
|
40804
|
-
const opts = reuseRefused ? { ...requested, frames: "generate" } : requested;
|
|
40805
40712
|
const clock = spineClockFor(blueprint);
|
|
40806
40713
|
const nodes = [];
|
|
40807
40714
|
emitBlueprintIngests(opts, nodes);
|
|
@@ -40904,7 +40811,6 @@ function scaffoldVideoCanvas(input, elementsInput, requested) {
|
|
|
40904
40811
|
}
|
|
40905
40812
|
const todo = {
|
|
40906
40813
|
...buildVideoTodo(videoReport(input, elementsInput), overlays.length, floating.length, opts, blueprint),
|
|
40907
|
-
...reuseRefused ? { frames_reuse_refused: reuseRefused } : {},
|
|
40908
40814
|
...aspectRemapTodo(resolveAspect(blueprint.source?.aspect_ratio, opts.aspect, genAspectsFor(opts.videoModel))),
|
|
40909
40815
|
model_constraints: buildModelConstraints()
|
|
40910
40816
|
};
|
|
@@ -45831,12 +45737,6 @@ function videoDefinitionDescription(blueprint) {
|
|
|
45831
45737
|
const product = g.branding?.product;
|
|
45832
45738
|
return typeof product === "string" && product.trim() ? product.trim() : void 0;
|
|
45833
45739
|
}
|
|
45834
|
-
function framesModeReport(canvas, requested) {
|
|
45835
|
-
const todo = canvas.metadata?.todo;
|
|
45836
|
-
const mode = typeof todo?.frames_mode === "string" ? todo.frames_mode : requested;
|
|
45837
|
-
const refused = typeof todo?.frames_reuse_refused === "string" ? todo.frames_reuse_refused : void 0;
|
|
45838
|
-
return { frames_mode: mode, ...refused ? { frames_reuse_refused: refused } : {} };
|
|
45839
|
-
}
|
|
45840
45740
|
async function materializeReferenceVideo(fileArg2) {
|
|
45841
45741
|
if (!/^https?:\/\//i.test(fileArg2)) return path26.resolve(fileArg2);
|
|
45842
45742
|
let bytes;
|
|
@@ -45994,10 +45894,7 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
45994
45894
|
type: "string",
|
|
45995
45895
|
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
45996
45896
|
},
|
|
45997
|
-
frames: {
|
|
45998
|
-
type: "string",
|
|
45999
|
-
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.`
|
|
46000
|
-
},
|
|
45897
|
+
frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
|
|
46001
45898
|
ambient: {
|
|
46002
45899
|
type: "boolean",
|
|
46003
45900
|
description: "Give silent b-roll scenes native diegetic ambient mixed deep under the music bed (off by default)"
|
|
@@ -46200,7 +46097,6 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
46200
46097
|
error: { code: "validation", issues: validation.issues },
|
|
46201
46098
|
canvas_path: outPath,
|
|
46202
46099
|
prompt_path: blueprintPath,
|
|
46203
|
-
...framesModeReport(canvas, frames),
|
|
46204
46100
|
note: "The canvas WAS written despite the blocking issue(s) \u2014 fix them in place, then `baker canvas validate` before running.",
|
|
46205
46101
|
...uncastHint
|
|
46206
46102
|
},
|
|
@@ -46252,7 +46148,7 @@ var scaffoldVideoCommand = defineCommand116({
|
|
|
46252
46148
|
composition_dir: compositionDest,
|
|
46253
46149
|
output: canvas.output,
|
|
46254
46150
|
...uncastHint,
|
|
46255
|
-
|
|
46151
|
+
frames_mode: frames,
|
|
46256
46152
|
models: {
|
|
46257
46153
|
deconstruct: deconstructModel,
|
|
46258
46154
|
select: selectModel,
|
|
@@ -49370,10 +49266,10 @@ function parseValueExpression(raw) {
|
|
|
49370
49266
|
return parts.map(parsePart);
|
|
49371
49267
|
}
|
|
49372
49268
|
function trackingFieldIds() {
|
|
49373
|
-
const
|
|
49374
|
-
if (!existsSync6(
|
|
49269
|
+
const path49 = join4(flowsDir(), "..", "tracking.ts");
|
|
49270
|
+
if (!existsSync6(path49)) return null;
|
|
49375
49271
|
try {
|
|
49376
|
-
const source = readFileSync15(
|
|
49272
|
+
const source = readFileSync15(path49, "utf-8");
|
|
49377
49273
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
49378
49274
|
if (!block2) return null;
|
|
49379
49275
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -49947,13 +49843,13 @@ function specsFromFile(parsed) {
|
|
|
49947
49843
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
49948
49844
|
});
|
|
49949
49845
|
}
|
|
49950
|
-
function readSpecFile(
|
|
49846
|
+
function readSpecFile(path49) {
|
|
49951
49847
|
let raw;
|
|
49952
49848
|
try {
|
|
49953
|
-
raw =
|
|
49849
|
+
raw = path49 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path49, "utf-8");
|
|
49954
49850
|
} catch (error) {
|
|
49955
49851
|
refuse(
|
|
49956
|
-
`Could not read ${
|
|
49852
|
+
`Could not read ${path49 === "-" ? "the mapping from stdin" : `"${path49}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
49957
49853
|
);
|
|
49958
49854
|
}
|
|
49959
49855
|
let parsed;
|
|
@@ -49961,7 +49857,7 @@ function readSpecFile(path48) {
|
|
|
49961
49857
|
parsed = JSON.parse(raw);
|
|
49962
49858
|
} catch (error) {
|
|
49963
49859
|
refuse(
|
|
49964
|
-
`${
|
|
49860
|
+
`${path49 === "-" ? "stdin" : `"${path49}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
49965
49861
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
49966
49862
|
);
|
|
49967
49863
|
}
|
|
@@ -50260,21 +50156,21 @@ var ARRAY_FIELDS = [
|
|
|
50260
50156
|
"tagIds"
|
|
50261
50157
|
];
|
|
50262
50158
|
var ARRAY_OWNERS = ["", "body"];
|
|
50263
|
-
function dropUnsetOptionals(sideEffect,
|
|
50159
|
+
function dropUnsetOptionals(sideEffect, path49) {
|
|
50264
50160
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
50265
50161
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
50266
50162
|
delete sideEffect[key];
|
|
50267
|
-
return [{ path:
|
|
50163
|
+
return [{ path: path49, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
50268
50164
|
});
|
|
50269
50165
|
}
|
|
50270
|
-
function fillNulledArrays(target2, prefix,
|
|
50166
|
+
function fillNulledArrays(target2, prefix, path49) {
|
|
50271
50167
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
50272
50168
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
50273
50169
|
target2[key] = [];
|
|
50274
|
-
return [{ path:
|
|
50170
|
+
return [{ path: path49, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
50275
50171
|
});
|
|
50276
50172
|
}
|
|
50277
|
-
function tidyEmailRecipients(sideEffect,
|
|
50173
|
+
function tidyEmailRecipients(sideEffect, path49) {
|
|
50278
50174
|
if (sideEffect.type !== "email") return [];
|
|
50279
50175
|
const config = sideEffect.encryptedConfig;
|
|
50280
50176
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -50285,7 +50181,7 @@ function tidyEmailRecipients(sideEffect, path48) {
|
|
|
50285
50181
|
const tidied = to.join(", ");
|
|
50286
50182
|
if (tidied === raw) return [];
|
|
50287
50183
|
config.email = tidied;
|
|
50288
|
-
return [{ path:
|
|
50184
|
+
return [{ path: path49, change: "tidied the recipient list's spacing and separators" }];
|
|
50289
50185
|
}
|
|
50290
50186
|
function sideEffectsOf(node) {
|
|
50291
50187
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -50294,13 +50190,13 @@ function sideEffectsOf(node) {
|
|
|
50294
50190
|
);
|
|
50295
50191
|
}
|
|
50296
50192
|
function normalizeSideEffect(sideEffect, where) {
|
|
50297
|
-
const
|
|
50193
|
+
const path49 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
50298
50194
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
50299
50195
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
50300
50196
|
if (!target2 || typeof target2 !== "object") return [];
|
|
50301
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
50197
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path49);
|
|
50302
50198
|
});
|
|
50303
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
50199
|
+
return [...dropUnsetOptionals(sideEffect, path49), ...arrays, ...tidyEmailRecipients(sideEffect, path49)];
|
|
50304
50200
|
}
|
|
50305
50201
|
function normalizeFlowTree(tree) {
|
|
50306
50202
|
const changes = [];
|
|
@@ -51662,11 +51558,11 @@ var WARNING_HINT = "Read the warnings above before telling the user this is read
|
|
|
51662
51558
|
async function stageOp3(op) {
|
|
51663
51559
|
const chatId = requireChatId();
|
|
51664
51560
|
try {
|
|
51665
|
-
const
|
|
51561
|
+
const data = await apiPost("/api/ga4/draft/stage", { chatId, op });
|
|
51666
51562
|
writeJsonEnvelope({
|
|
51667
51563
|
ok: true,
|
|
51668
51564
|
data,
|
|
51669
|
-
hints: [...
|
|
51565
|
+
hints: [...STAGE_HINTS, ...data.warnings.length > 0 ? [WARNING_HINT] : []]
|
|
51670
51566
|
});
|
|
51671
51567
|
} catch (err) {
|
|
51672
51568
|
handleError5(err);
|
|
@@ -51680,23 +51576,21 @@ async function stageOps(ops) {
|
|
|
51680
51576
|
}
|
|
51681
51577
|
const chatId = requireChatId();
|
|
51682
51578
|
try {
|
|
51683
|
-
const {
|
|
51684
|
-
await apiPost("/api/ga4/draft/stage-batch", { chatId, ops })
|
|
51685
|
-
);
|
|
51579
|
+
const data = await apiPost("/api/ga4/draft/stage-batch", { chatId, ops });
|
|
51686
51580
|
writeJsonEnvelope({
|
|
51687
51581
|
ok: true,
|
|
51688
51582
|
data,
|
|
51689
|
-
hints: [...
|
|
51583
|
+
hints: [...STAGE_HINTS, ...data.ops.some((op) => op.warnings.length > 0) ? [WARNING_HINT] : []]
|
|
51690
51584
|
});
|
|
51691
51585
|
} catch (err) {
|
|
51692
51586
|
handleError5(err);
|
|
51693
51587
|
}
|
|
51694
51588
|
}
|
|
51695
|
-
async function draftAction2(
|
|
51589
|
+
async function draftAction2(path49, body, chat) {
|
|
51696
51590
|
const chatId = resolveChatId(chat);
|
|
51697
51591
|
try {
|
|
51698
|
-
const
|
|
51699
|
-
writeJsonEnvelope({ ok: true, data
|
|
51592
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
51593
|
+
writeJsonEnvelope({ ok: true, data });
|
|
51700
51594
|
return data;
|
|
51701
51595
|
} catch (err) {
|
|
51702
51596
|
handleError5(err);
|
|
@@ -51728,13 +51622,12 @@ function renderDraft(response) {
|
|
|
51728
51622
|
async function draftList(json, chat) {
|
|
51729
51623
|
const chatId = resolveChatId(chat);
|
|
51730
51624
|
try {
|
|
51731
|
-
const
|
|
51732
|
-
const { data, hints: hints2 } = splitHints(response);
|
|
51625
|
+
const data = await apiPost("/api/ga4/draft", { chatId });
|
|
51733
51626
|
if (json) {
|
|
51734
|
-
writeJsonEnvelope({ ok: true, data
|
|
51627
|
+
writeJsonEnvelope({ ok: true, data });
|
|
51735
51628
|
return;
|
|
51736
51629
|
}
|
|
51737
|
-
process.stdout.write(`${renderDraft(data)}
|
|
51630
|
+
process.stdout.write(`${renderDraft(data)}
|
|
51738
51631
|
`);
|
|
51739
51632
|
} catch (err) {
|
|
51740
51633
|
handleError5(err);
|
|
@@ -54225,9 +54118,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
54225
54118
|
}
|
|
54226
54119
|
return readFile28(pathOrUrl);
|
|
54227
54120
|
}
|
|
54228
|
-
async function isDirectory(
|
|
54121
|
+
async function isDirectory(path49) {
|
|
54229
54122
|
try {
|
|
54230
|
-
const s = await stat7(
|
|
54123
|
+
const s = await stat7(path49);
|
|
54231
54124
|
return s.isDirectory();
|
|
54232
54125
|
} catch {
|
|
54233
54126
|
return false;
|
|
@@ -54655,13 +54548,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
54655
54548
|
}
|
|
54656
54549
|
function disambiguate(paths) {
|
|
54657
54550
|
const taken = /* @__PURE__ */ new Set();
|
|
54658
|
-
return paths.map((
|
|
54659
|
-
if (!taken.has(
|
|
54660
|
-
taken.add(
|
|
54661
|
-
return
|
|
54551
|
+
return paths.map((path49) => {
|
|
54552
|
+
if (!taken.has(path49)) {
|
|
54553
|
+
taken.add(path49);
|
|
54554
|
+
return path49;
|
|
54662
54555
|
}
|
|
54663
|
-
const ext = extname3(
|
|
54664
|
-
const stem =
|
|
54556
|
+
const ext = extname3(path49);
|
|
54557
|
+
const stem = path49.slice(0, path49.length - ext.length);
|
|
54665
54558
|
let n = 2;
|
|
54666
54559
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
54667
54560
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -54787,10 +54680,10 @@ async function runDownloads(plan) {
|
|
|
54787
54680
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
54788
54681
|
const downloaded = [];
|
|
54789
54682
|
for (const [index, item] of fetched.entries()) {
|
|
54790
|
-
const
|
|
54683
|
+
const path49 = paths[index] ?? item.path;
|
|
54791
54684
|
try {
|
|
54792
|
-
await atomicWrite(
|
|
54793
|
-
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 });
|
|
54794
54687
|
} catch (err) {
|
|
54795
54688
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
54796
54689
|
}
|
|
@@ -62977,11 +62870,365 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
|
62977
62870
|
}
|
|
62978
62871
|
});
|
|
62979
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
|
+
|
|
62980
63227
|
// src/commands/research/index.ts
|
|
62981
|
-
import { defineCommand as
|
|
63228
|
+
import { defineCommand as defineCommand202 } from "citty";
|
|
62982
63229
|
|
|
62983
63230
|
// src/commands/research/advertisers.ts
|
|
62984
|
-
import { defineCommand as
|
|
63231
|
+
import { defineCommand as defineCommand190 } from "citty";
|
|
62985
63232
|
|
|
62986
63233
|
// src/commands/research/hints.ts
|
|
62987
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.';
|
|
@@ -63183,7 +63430,7 @@ var FIELDS3 = {
|
|
|
63183
63430
|
etv: "Estimated traffic value (USD)",
|
|
63184
63431
|
visibility: "SERP visibility score (0-1)"
|
|
63185
63432
|
};
|
|
63186
|
-
var advertisersCommand =
|
|
63433
|
+
var advertisersCommand = defineCommand190({
|
|
63187
63434
|
meta: {
|
|
63188
63435
|
name: "advertisers",
|
|
63189
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).
|
|
@@ -63239,7 +63486,7 @@ Examples:
|
|
|
63239
63486
|
});
|
|
63240
63487
|
|
|
63241
63488
|
// src/commands/research/autocomplete.ts
|
|
63242
|
-
import { defineCommand as
|
|
63489
|
+
import { defineCommand as defineCommand191 } from "citty";
|
|
63243
63490
|
registerSchema({
|
|
63244
63491
|
command: "research.autocomplete",
|
|
63245
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).",
|
|
@@ -63262,7 +63509,7 @@ registerSchema({
|
|
|
63262
63509
|
var FIELDS4 = {
|
|
63263
63510
|
suggestion: "Autocomplete suggestion from Google"
|
|
63264
63511
|
};
|
|
63265
|
-
var autocompleteCommand =
|
|
63512
|
+
var autocompleteCommand = defineCommand191({
|
|
63266
63513
|
meta: {
|
|
63267
63514
|
name: "autocomplete",
|
|
63268
63515
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -63317,7 +63564,7 @@ Examples:
|
|
|
63317
63564
|
});
|
|
63318
63565
|
|
|
63319
63566
|
// src/commands/research/countries.ts
|
|
63320
|
-
import { defineCommand as
|
|
63567
|
+
import { defineCommand as defineCommand192 } from "citty";
|
|
63321
63568
|
registerSchema({
|
|
63322
63569
|
command: "research.countries",
|
|
63323
63570
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -63374,7 +63621,7 @@ var FIELDS5 = {
|
|
|
63374
63621
|
code: "Country code to pass as --location",
|
|
63375
63622
|
name: "Country name"
|
|
63376
63623
|
};
|
|
63377
|
-
var countriesCommand =
|
|
63624
|
+
var countriesCommand = defineCommand192({
|
|
63378
63625
|
meta: {
|
|
63379
63626
|
name: "countries",
|
|
63380
63627
|
description: "List all supported country codes for --location flag."
|
|
@@ -63385,7 +63632,7 @@ var countriesCommand = defineCommand186({
|
|
|
63385
63632
|
});
|
|
63386
63633
|
|
|
63387
63634
|
// src/commands/research/fetch.ts
|
|
63388
|
-
import { defineCommand as
|
|
63635
|
+
import { defineCommand as defineCommand193 } from "citty";
|
|
63389
63636
|
var CONTENT_PREVIEW_CHARS = 2e4;
|
|
63390
63637
|
var TIMEOUT_MS = 18e4;
|
|
63391
63638
|
registerSchema({
|
|
@@ -63458,7 +63705,7 @@ function fetchFix(code) {
|
|
|
63458
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."
|
|
63459
63706
|
};
|
|
63460
63707
|
}
|
|
63461
|
-
var fetchCommand =
|
|
63708
|
+
var fetchCommand = defineCommand193({
|
|
63462
63709
|
meta: {
|
|
63463
63710
|
name: "fetch",
|
|
63464
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.
|
|
@@ -63535,7 +63782,7 @@ Examples:
|
|
|
63535
63782
|
});
|
|
63536
63783
|
|
|
63537
63784
|
// src/commands/research/intent.ts
|
|
63538
|
-
import { defineCommand as
|
|
63785
|
+
import { defineCommand as defineCommand194 } from "citty";
|
|
63539
63786
|
registerSchema({
|
|
63540
63787
|
command: "research.intent",
|
|
63541
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.",
|
|
@@ -63558,7 +63805,7 @@ var FIELDS7 = {
|
|
|
63558
63805
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
63559
63806
|
probability: "Confidence score 0.0-1.0"
|
|
63560
63807
|
};
|
|
63561
|
-
var intentCommand =
|
|
63808
|
+
var intentCommand = defineCommand194({
|
|
63562
63809
|
meta: {
|
|
63563
63810
|
name: "intent",
|
|
63564
63811
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -63606,7 +63853,7 @@ Examples:
|
|
|
63606
63853
|
});
|
|
63607
63854
|
|
|
63608
63855
|
// src/commands/research/keyword-gap.ts
|
|
63609
|
-
import { defineCommand as
|
|
63856
|
+
import { defineCommand as defineCommand195 } from "citty";
|
|
63610
63857
|
registerSchema({
|
|
63611
63858
|
command: "research.keyword-gap",
|
|
63612
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.",
|
|
@@ -63635,7 +63882,7 @@ var FIELDS8 = {
|
|
|
63635
63882
|
cpc: "Cost per click USD",
|
|
63636
63883
|
their_position: "Competitor's ranking position"
|
|
63637
63884
|
};
|
|
63638
|
-
var keywordGapCommand =
|
|
63885
|
+
var keywordGapCommand = defineCommand195({
|
|
63639
63886
|
meta: {
|
|
63640
63887
|
name: "keyword-gap",
|
|
63641
63888
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -63710,7 +63957,7 @@ Examples:
|
|
|
63710
63957
|
});
|
|
63711
63958
|
|
|
63712
63959
|
// src/commands/research/keyword-metrics.ts
|
|
63713
|
-
import { defineCommand as
|
|
63960
|
+
import { defineCommand as defineCommand196 } from "citty";
|
|
63714
63961
|
|
|
63715
63962
|
// src/commands/research/keyword-metrics-rows.ts
|
|
63716
63963
|
var KEYWORD_METRICS_SOURCE = "keyword_planner_estimate_via_dataforseo";
|
|
@@ -63790,7 +64037,7 @@ registerSchema({
|
|
|
63790
64037
|
"no-cache": { type: "boolean", description: "Skip server cache, hit API directly", required: false }
|
|
63791
64038
|
}
|
|
63792
64039
|
});
|
|
63793
|
-
var keywordMetricsCommand =
|
|
64040
|
+
var keywordMetricsCommand = defineCommand196({
|
|
63794
64041
|
meta: {
|
|
63795
64042
|
name: "keyword-metrics",
|
|
63796
64043
|
description: `Volume, CPC and competition for keywords you name. No domain required.
|
|
@@ -63872,7 +64119,7 @@ Examples:
|
|
|
63872
64119
|
});
|
|
63873
64120
|
|
|
63874
64121
|
// src/commands/research/keywords-for-site.ts
|
|
63875
|
-
import { defineCommand as
|
|
64122
|
+
import { defineCommand as defineCommand197 } from "citty";
|
|
63876
64123
|
registerSchema({
|
|
63877
64124
|
command: "research.keywords-for-site",
|
|
63878
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.",
|
|
@@ -63905,7 +64152,7 @@ var FIELDS9 = {
|
|
|
63905
64152
|
competition: "LOW, MEDIUM, or HIGH",
|
|
63906
64153
|
competition_index: "Competition score 0-100"
|
|
63907
64154
|
};
|
|
63908
|
-
var keywordsForSiteCommand =
|
|
64155
|
+
var keywordsForSiteCommand = defineCommand197({
|
|
63909
64156
|
meta: {
|
|
63910
64157
|
name: "keywords-for-site",
|
|
63911
64158
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -63967,7 +64214,7 @@ Examples:
|
|
|
63967
64214
|
});
|
|
63968
64215
|
|
|
63969
64216
|
// src/commands/research/languages.ts
|
|
63970
|
-
import { defineCommand as
|
|
64217
|
+
import { defineCommand as defineCommand198 } from "citty";
|
|
63971
64218
|
registerSchema({
|
|
63972
64219
|
command: "research.languages",
|
|
63973
64220
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -63997,7 +64244,7 @@ var FIELDS10 = {
|
|
|
63997
64244
|
code: "Language code to pass as --language",
|
|
63998
64245
|
name: "Language name (also accepted by --language)"
|
|
63999
64246
|
};
|
|
64000
|
-
var languagesCommand2 =
|
|
64247
|
+
var languagesCommand2 = defineCommand198({
|
|
64001
64248
|
meta: {
|
|
64002
64249
|
name: "languages",
|
|
64003
64250
|
description: "List all supported language codes for --language flag."
|
|
@@ -64008,7 +64255,7 @@ var languagesCommand2 = defineCommand192({
|
|
|
64008
64255
|
});
|
|
64009
64256
|
|
|
64010
64257
|
// src/commands/research/lighthouse.ts
|
|
64011
|
-
import { defineCommand as
|
|
64258
|
+
import { defineCommand as defineCommand199 } from "citty";
|
|
64012
64259
|
registerSchema({
|
|
64013
64260
|
command: "research.lighthouse",
|
|
64014
64261
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -64027,7 +64274,7 @@ var FIELDS11 = {
|
|
|
64027
64274
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
64028
64275
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
64029
64276
|
};
|
|
64030
|
-
var lighthouseCommand =
|
|
64277
|
+
var lighthouseCommand = defineCommand199({
|
|
64031
64278
|
meta: {
|
|
64032
64279
|
name: "lighthouse",
|
|
64033
64280
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -64065,7 +64312,7 @@ Examples:
|
|
|
64065
64312
|
});
|
|
64066
64313
|
|
|
64067
64314
|
// src/commands/research/relevant-pages.ts
|
|
64068
|
-
import { defineCommand as
|
|
64315
|
+
import { defineCommand as defineCommand200 } from "citty";
|
|
64069
64316
|
registerSchema({
|
|
64070
64317
|
command: "research.relevant-pages",
|
|
64071
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).",
|
|
@@ -64091,7 +64338,7 @@ var FIELDS12 = {
|
|
|
64091
64338
|
keywords: "Total organic keywords the page ranks for",
|
|
64092
64339
|
top_10: "Keywords in positions 1-10"
|
|
64093
64340
|
};
|
|
64094
|
-
var relevantPagesCommand =
|
|
64341
|
+
var relevantPagesCommand = defineCommand200({
|
|
64095
64342
|
meta: {
|
|
64096
64343
|
name: "relevant-pages",
|
|
64097
64344
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -64138,7 +64385,7 @@ Examples:
|
|
|
64138
64385
|
});
|
|
64139
64386
|
|
|
64140
64387
|
// src/commands/research/web.ts
|
|
64141
|
-
import { defineCommand as
|
|
64388
|
+
import { defineCommand as defineCommand201 } from "citty";
|
|
64142
64389
|
registerSchema({
|
|
64143
64390
|
command: "research.web",
|
|
64144
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).",
|
|
@@ -64189,7 +64436,7 @@ async function runDeepResearch(question) {
|
|
|
64189
64436
|
}
|
|
64190
64437
|
throw new Error("Deep research timed out");
|
|
64191
64438
|
}
|
|
64192
|
-
var webCommand =
|
|
64439
|
+
var webCommand = defineCommand201({
|
|
64193
64440
|
meta: {
|
|
64194
64441
|
name: "web",
|
|
64195
64442
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -64251,7 +64498,7 @@ Examples:
|
|
|
64251
64498
|
});
|
|
64252
64499
|
|
|
64253
64500
|
// src/commands/research/index.ts
|
|
64254
|
-
var researchCommand =
|
|
64501
|
+
var researchCommand = defineCommand202({
|
|
64255
64502
|
meta: {
|
|
64256
64503
|
name: "research",
|
|
64257
64504
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -64298,10 +64545,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
|
|
|
64298
64545
|
});
|
|
64299
64546
|
|
|
64300
64547
|
// src/commands/scheduled-agents/index.ts
|
|
64301
|
-
import { defineCommand as
|
|
64548
|
+
import { defineCommand as defineCommand213 } from "citty";
|
|
64302
64549
|
|
|
64303
64550
|
// src/commands/scheduled-agents/create.ts
|
|
64304
|
-
import { defineCommand as
|
|
64551
|
+
import { defineCommand as defineCommand203 } from "citty";
|
|
64305
64552
|
|
|
64306
64553
|
// src/commands/scheduled-agents/shared.ts
|
|
64307
64554
|
var TEMP_SCHEDULED_AGENT_PREFIX = "temp_agent_";
|
|
@@ -64668,7 +64915,7 @@ registerSchema({
|
|
|
64668
64915
|
}
|
|
64669
64916
|
}
|
|
64670
64917
|
});
|
|
64671
|
-
var createCommand3 =
|
|
64918
|
+
var createCommand3 = defineCommand203({
|
|
64672
64919
|
meta: {
|
|
64673
64920
|
name: "create",
|
|
64674
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'
|
|
@@ -64725,7 +64972,7 @@ var createCommand3 = defineCommand197({
|
|
|
64725
64972
|
});
|
|
64726
64973
|
|
|
64727
64974
|
// src/commands/scheduled-agents/delete.ts
|
|
64728
|
-
import { defineCommand as
|
|
64975
|
+
import { defineCommand as defineCommand204 } from "citty";
|
|
64729
64976
|
registerSchema({
|
|
64730
64977
|
command: "scheduled-agents.delete",
|
|
64731
64978
|
description: "Stage deletion of a published scheduled agent, or cancel one this chat staged (temp_agent_*).",
|
|
@@ -64733,7 +64980,7 @@ registerSchema({
|
|
|
64733
64980
|
id: { type: "string", description: "Published scheduled agent ID or temp_agent_* draft ID", required: true }
|
|
64734
64981
|
}
|
|
64735
64982
|
});
|
|
64736
|
-
var deleteCommand3 =
|
|
64983
|
+
var deleteCommand3 = defineCommand204({
|
|
64737
64984
|
meta: {
|
|
64738
64985
|
name: "delete",
|
|
64739
64986
|
description: "Stage a scheduled agent deletion. Example: baker scheduled-agents delete <id-or-temp_agent_id>"
|
|
@@ -64762,7 +65009,7 @@ var deleteCommand3 = defineCommand198({
|
|
|
64762
65009
|
});
|
|
64763
65010
|
|
|
64764
65011
|
// src/commands/scheduled-agents/get.ts
|
|
64765
|
-
import { defineCommand as
|
|
65012
|
+
import { defineCommand as defineCommand205 } from "citty";
|
|
64766
65013
|
registerSchema({
|
|
64767
65014
|
command: "scheduled-agents.get",
|
|
64768
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.",
|
|
@@ -64771,7 +65018,7 @@ registerSchema({
|
|
|
64771
65018
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
64772
65019
|
}
|
|
64773
65020
|
});
|
|
64774
|
-
var getCommand4 =
|
|
65021
|
+
var getCommand4 = defineCommand205({
|
|
64775
65022
|
meta: {
|
|
64776
65023
|
name: "get",
|
|
64777
65024
|
description: "Get a scheduled agent. Example: baker scheduled-agents get <id-or-temp_agent_id>"
|
|
@@ -64810,7 +65057,7 @@ var getCommand4 = defineCommand199({
|
|
|
64810
65057
|
});
|
|
64811
65058
|
|
|
64812
65059
|
// src/commands/scheduled-agents/list.ts
|
|
64813
|
-
import { defineCommand as
|
|
65060
|
+
import { defineCommand as defineCommand206 } from "citty";
|
|
64814
65061
|
var FULL_DESCRIPTION = "Return every item and staged change as stored, briefs included (tens of KB). Prefer `get <id>` for one item.";
|
|
64815
65062
|
registerSchema({
|
|
64816
65063
|
command: "scheduled-agents.list",
|
|
@@ -64820,7 +65067,7 @@ registerSchema({
|
|
|
64820
65067
|
full: { type: "boolean", description: FULL_DESCRIPTION, required: false }
|
|
64821
65068
|
}
|
|
64822
65069
|
});
|
|
64823
|
-
var
|
|
65070
|
+
var listCommand18 = defineCommand206({
|
|
64824
65071
|
meta: {
|
|
64825
65072
|
name: "list",
|
|
64826
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."
|
|
@@ -64846,7 +65093,7 @@ var listCommand17 = defineCommand200({
|
|
|
64846
65093
|
});
|
|
64847
65094
|
|
|
64848
65095
|
// src/commands/scheduled-agents/run.ts
|
|
64849
|
-
import { defineCommand as
|
|
65096
|
+
import { defineCommand as defineCommand207 } from "citty";
|
|
64850
65097
|
registerSchema({
|
|
64851
65098
|
command: "scheduled-agents.run",
|
|
64852
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.",
|
|
@@ -64854,7 +65101,7 @@ registerSchema({
|
|
|
64854
65101
|
id: { type: "string", description: "Published scheduled agent ID", required: true }
|
|
64855
65102
|
}
|
|
64856
65103
|
});
|
|
64857
|
-
var runCommand2 =
|
|
65104
|
+
var runCommand2 = defineCommand207({
|
|
64858
65105
|
meta: {
|
|
64859
65106
|
name: "run",
|
|
64860
65107
|
description: "Run a published scheduled agent now. Example: baker scheduled-agents run <id>"
|
|
@@ -64886,7 +65133,7 @@ var runCommand2 = defineCommand201({
|
|
|
64886
65133
|
});
|
|
64887
65134
|
|
|
64888
65135
|
// src/commands/scheduled-agents/targets.ts
|
|
64889
|
-
import { defineCommand as
|
|
65136
|
+
import { defineCommand as defineCommand208 } from "citty";
|
|
64890
65137
|
var ARGS2 = {
|
|
64891
65138
|
trigger: {
|
|
64892
65139
|
type: "string",
|
|
@@ -64920,7 +65167,7 @@ registerSchema({
|
|
|
64920
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.",
|
|
64921
65168
|
args: ARGS2
|
|
64922
65169
|
});
|
|
64923
|
-
var targetsCommand =
|
|
65170
|
+
var targetsCommand = defineCommand208({
|
|
64924
65171
|
meta: {
|
|
64925
65172
|
name: "targets",
|
|
64926
65173
|
description: `What a trigger can be pointed at \u2014 so "when a Task is picked up" becomes "when THIS Task is picked up".
|
|
@@ -64963,7 +65210,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
64963
65210
|
// src/commands/scheduled-agents/templates.ts
|
|
64964
65211
|
import { readFile as readFile32 } from "fs/promises";
|
|
64965
65212
|
import path46 from "path";
|
|
64966
|
-
import { defineCommand as
|
|
65213
|
+
import { defineCommand as defineCommand209 } from "citty";
|
|
64967
65214
|
registerSchema({
|
|
64968
65215
|
command: "scheduled-agents.templates",
|
|
64969
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.",
|
|
@@ -65018,7 +65265,7 @@ registerSchema({
|
|
|
65018
65265
|
}
|
|
65019
65266
|
}
|
|
65020
65267
|
});
|
|
65021
|
-
var templatesCommand =
|
|
65268
|
+
var templatesCommand = defineCommand209({
|
|
65022
65269
|
meta: {
|
|
65023
65270
|
name: "templates",
|
|
65024
65271
|
description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
|
|
@@ -65114,7 +65361,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65114
65361
|
});
|
|
65115
65362
|
|
|
65116
65363
|
// src/commands/scheduled-agents/triggers.ts
|
|
65117
|
-
import { defineCommand as
|
|
65364
|
+
import { defineCommand as defineCommand210 } from "citty";
|
|
65118
65365
|
var ARGS3 = {
|
|
65119
65366
|
trigger: {
|
|
65120
65367
|
type: "string",
|
|
@@ -65200,7 +65447,7 @@ function shapeTriggerCatalog(response, filter) {
|
|
|
65200
65447
|
}
|
|
65201
65448
|
return { ok: true, data: { groups, reacting: catalog.reacting } };
|
|
65202
65449
|
}
|
|
65203
|
-
var triggersCommand2 =
|
|
65450
|
+
var triggersCommand2 = defineCommand210({
|
|
65204
65451
|
meta: {
|
|
65205
65452
|
name: "triggers",
|
|
65206
65453
|
description: `Everything that can start a scheduled agent.
|
|
@@ -65230,7 +65477,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65230
65477
|
});
|
|
65231
65478
|
|
|
65232
65479
|
// src/commands/scheduled-agents/unstage.ts
|
|
65233
|
-
import { defineCommand as
|
|
65480
|
+
import { defineCommand as defineCommand211 } from "citty";
|
|
65234
65481
|
registerSchema({
|
|
65235
65482
|
command: "scheduled-agents.unstage",
|
|
65236
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.",
|
|
@@ -65256,7 +65503,7 @@ function unstageBody(args5, chatId) {
|
|
|
65256
65503
|
}
|
|
65257
65504
|
return { chatId, ref: args5.ref, index };
|
|
65258
65505
|
}
|
|
65259
|
-
var unstageCommand =
|
|
65506
|
+
var unstageCommand = defineCommand211({
|
|
65260
65507
|
meta: {
|
|
65261
65508
|
name: "unstage",
|
|
65262
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"
|
|
@@ -65287,7 +65534,7 @@ var unstageCommand = defineCommand205({
|
|
|
65287
65534
|
});
|
|
65288
65535
|
|
|
65289
65536
|
// src/commands/scheduled-agents/update.ts
|
|
65290
|
-
import { defineCommand as
|
|
65537
|
+
import { defineCommand as defineCommand212 } from "citty";
|
|
65291
65538
|
registerSchema({
|
|
65292
65539
|
command: "scheduled-agents.update",
|
|
65293
65540
|
description: "Stage an update to a published scheduled agent, or to one this chat staged (temp_agent_*).",
|
|
@@ -65314,7 +65561,7 @@ registerSchema({
|
|
|
65314
65561
|
enabled: { type: "string", description: "Replacement enabled state", required: false, enum: ["true", "false"] }
|
|
65315
65562
|
}
|
|
65316
65563
|
});
|
|
65317
|
-
var updateCommand4 =
|
|
65564
|
+
var updateCommand4 = defineCommand212({
|
|
65318
65565
|
meta: {
|
|
65319
65566
|
name: "update",
|
|
65320
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"
|
|
@@ -65385,7 +65632,7 @@ var updateCommand4 = defineCommand206({
|
|
|
65385
65632
|
});
|
|
65386
65633
|
|
|
65387
65634
|
// src/commands/scheduled-agents/index.ts
|
|
65388
|
-
var scheduledAgentsCommand =
|
|
65635
|
+
var scheduledAgentsCommand = defineCommand213({
|
|
65389
65636
|
meta: {
|
|
65390
65637
|
name: "scheduled-agents",
|
|
65391
65638
|
description: `Manage Scheduled agents. Subcommands: list, get, triggers, targets, create, update, delete, unstage, run, templates.
|
|
@@ -65414,7 +65661,7 @@ Examples:
|
|
|
65414
65661
|
Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
65415
65662
|
},
|
|
65416
65663
|
subCommands: {
|
|
65417
|
-
list:
|
|
65664
|
+
list: listCommand18,
|
|
65418
65665
|
get: getCommand4,
|
|
65419
65666
|
triggers: triggersCommand2,
|
|
65420
65667
|
targets: targetsCommand,
|
|
@@ -65428,14 +65675,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65428
65675
|
});
|
|
65429
65676
|
|
|
65430
65677
|
// src/commands/schema.ts
|
|
65431
|
-
import { defineCommand as
|
|
65678
|
+
import { defineCommand as defineCommand214 } from "citty";
|
|
65432
65679
|
function narrowToFamily(commandName, available) {
|
|
65433
65680
|
const segments = commandName.split(".");
|
|
65434
65681
|
const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
|
|
65435
65682
|
const siblings = available.filter((name) => name.startsWith(prefix));
|
|
65436
65683
|
return siblings.length > 0 ? siblings : available;
|
|
65437
65684
|
}
|
|
65438
|
-
var schemaCommand2 =
|
|
65685
|
+
var schemaCommand2 = defineCommand214({
|
|
65439
65686
|
meta: {
|
|
65440
65687
|
name: "schema",
|
|
65441
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)"
|
|
@@ -65480,10 +65727,10 @@ var schemaCommand2 = defineCommand208({
|
|
|
65480
65727
|
});
|
|
65481
65728
|
|
|
65482
65729
|
// src/commands/studio/index.ts
|
|
65483
|
-
import { defineCommand as
|
|
65730
|
+
import { defineCommand as defineCommand223 } from "citty";
|
|
65484
65731
|
|
|
65485
65732
|
// src/commands/studio/animate.ts
|
|
65486
|
-
import { defineCommand as
|
|
65733
|
+
import { defineCommand as defineCommand215 } from "citty";
|
|
65487
65734
|
|
|
65488
65735
|
// src/commands/studio/spokenPace.ts
|
|
65489
65736
|
var WORDS_PER_SECOND3 = SPOKEN_WORDS_PER_SECOND;
|
|
@@ -65709,7 +65956,7 @@ function parseImageRefs(spec) {
|
|
|
65709
65956
|
}
|
|
65710
65957
|
var defaultDeps = {
|
|
65711
65958
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
65712
|
-
upload: (
|
|
65959
|
+
upload: (path49) => uploadLocalImage({ file: path49, contentType: detectImageContentType(path49), source: "uploaded" })
|
|
65713
65960
|
};
|
|
65714
65961
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
65715
65962
|
const refs = parseImageRefs(spec);
|
|
@@ -65729,10 +65976,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
65729
65976
|
}
|
|
65730
65977
|
return { imageIds, added };
|
|
65731
65978
|
}
|
|
65732
|
-
function uploadFailure(
|
|
65979
|
+
function uploadFailure(path49) {
|
|
65733
65980
|
return (error) => {
|
|
65734
65981
|
if (error instanceof ApiError) throw error;
|
|
65735
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
65982
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path49}" as an image.`);
|
|
65736
65983
|
};
|
|
65737
65984
|
}
|
|
65738
65985
|
|
|
@@ -65996,7 +66243,7 @@ async function adByHandHintFor(body) {
|
|
|
65996
66243
|
return null;
|
|
65997
66244
|
}
|
|
65998
66245
|
}
|
|
65999
|
-
var animateCommand =
|
|
66246
|
+
var animateCommand = defineCommand215({
|
|
66000
66247
|
meta: {
|
|
66001
66248
|
name: "animate",
|
|
66002
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"
|
|
@@ -66121,7 +66368,7 @@ var animateCommand = defineCommand209({
|
|
|
66121
66368
|
});
|
|
66122
66369
|
|
|
66123
66370
|
// src/commands/studio/generate.ts
|
|
66124
|
-
import { defineCommand as
|
|
66371
|
+
import { defineCommand as defineCommand216 } from "citty";
|
|
66125
66372
|
var MODEL_LIST2 = IMAGE_MODEL_IDS;
|
|
66126
66373
|
var DEFAULT_MAX_WAIT_MS2 = 24e4;
|
|
66127
66374
|
registerSchema({
|
|
@@ -66257,7 +66504,7 @@ function buildGenerateBody(args5, prompt) {
|
|
|
66257
66504
|
}
|
|
66258
66505
|
return body;
|
|
66259
66506
|
}
|
|
66260
|
-
var generateCommand =
|
|
66507
|
+
var generateCommand = defineCommand216({
|
|
66261
66508
|
meta: {
|
|
66262
66509
|
name: "generate",
|
|
66263
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]]'"
|
|
@@ -66340,7 +66587,7 @@ var generateCommand = defineCommand210({
|
|
|
66340
66587
|
});
|
|
66341
66588
|
|
|
66342
66589
|
// src/commands/studio/get.ts
|
|
66343
|
-
import { defineCommand as
|
|
66590
|
+
import { defineCommand as defineCommand217 } from "citty";
|
|
66344
66591
|
registerSchema({
|
|
66345
66592
|
command: "studio.get",
|
|
66346
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.",
|
|
@@ -66349,7 +66596,7 @@ registerSchema({
|
|
|
66349
66596
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66350
66597
|
}
|
|
66351
66598
|
});
|
|
66352
|
-
var getCommand5 =
|
|
66599
|
+
var getCommand5 = defineCommand217({
|
|
66353
66600
|
meta: {
|
|
66354
66601
|
name: "get",
|
|
66355
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"
|
|
@@ -66378,7 +66625,7 @@ var getCommand5 = defineCommand211({
|
|
|
66378
66625
|
});
|
|
66379
66626
|
|
|
66380
66627
|
// src/commands/studio/improve.ts
|
|
66381
|
-
import { defineCommand as
|
|
66628
|
+
import { defineCommand as defineCommand218 } from "citty";
|
|
66382
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.";
|
|
66383
66630
|
registerSchema({
|
|
66384
66631
|
command: "studio.improve",
|
|
@@ -66403,7 +66650,7 @@ registerSchema({
|
|
|
66403
66650
|
}
|
|
66404
66651
|
}
|
|
66405
66652
|
});
|
|
66406
|
-
var improveCommand =
|
|
66653
|
+
var improveCommand = defineCommand218({
|
|
66407
66654
|
meta: {
|
|
66408
66655
|
name: "improve",
|
|
66409
66656
|
description: `${DESCRIPTION2}
|
|
@@ -66447,7 +66694,7 @@ Examples:
|
|
|
66447
66694
|
});
|
|
66448
66695
|
|
|
66449
66696
|
// src/commands/studio/keep.ts
|
|
66450
|
-
import { defineCommand as
|
|
66697
|
+
import { defineCommand as defineCommand219 } from "citty";
|
|
66451
66698
|
registerSchema({
|
|
66452
66699
|
command: "studio.keep",
|
|
66453
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.",
|
|
@@ -66457,7 +66704,7 @@ registerSchema({
|
|
|
66457
66704
|
undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
|
|
66458
66705
|
}
|
|
66459
66706
|
});
|
|
66460
|
-
var keepCommand =
|
|
66707
|
+
var keepCommand = defineCommand219({
|
|
66461
66708
|
meta: {
|
|
66462
66709
|
name: "keep",
|
|
66463
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"
|
|
@@ -66508,7 +66755,7 @@ var keepCommand = defineCommand213({
|
|
|
66508
66755
|
});
|
|
66509
66756
|
|
|
66510
66757
|
// src/commands/studio/list.ts
|
|
66511
|
-
import { defineCommand as
|
|
66758
|
+
import { defineCommand as defineCommand220 } from "citty";
|
|
66512
66759
|
registerSchema({
|
|
66513
66760
|
command: "studio.list",
|
|
66514
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.",
|
|
@@ -66519,7 +66766,7 @@ registerSchema({
|
|
|
66519
66766
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66520
66767
|
}
|
|
66521
66768
|
});
|
|
66522
|
-
var
|
|
66769
|
+
var listCommand19 = defineCommand220({
|
|
66523
66770
|
meta: {
|
|
66524
66771
|
name: "list",
|
|
66525
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"
|
|
@@ -66553,7 +66800,7 @@ var listCommand18 = defineCommand214({
|
|
|
66553
66800
|
});
|
|
66554
66801
|
|
|
66555
66802
|
// src/commands/studio/models.ts
|
|
66556
|
-
import { defineCommand as
|
|
66803
|
+
import { defineCommand as defineCommand221 } from "citty";
|
|
66557
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.";
|
|
66558
66805
|
registerSchema({
|
|
66559
66806
|
command: "studio.models",
|
|
@@ -66640,7 +66887,7 @@ function buildModelCards(kind, model) {
|
|
|
66640
66887
|
const selected = model ? ids.filter((id) => id === model) : ids;
|
|
66641
66888
|
return selected.map((id) => build(id));
|
|
66642
66889
|
}
|
|
66643
|
-
var modelsCommand =
|
|
66890
|
+
var modelsCommand = defineCommand221({
|
|
66644
66891
|
meta: {
|
|
66645
66892
|
name: "models",
|
|
66646
66893
|
description: `${DESCRIPTION3}
|
|
@@ -66687,13 +66934,13 @@ Examples:
|
|
|
66687
66934
|
});
|
|
66688
66935
|
|
|
66689
66936
|
// src/commands/studio/skills.ts
|
|
66690
|
-
import { defineCommand as
|
|
66937
|
+
import { defineCommand as defineCommand222 } from "citty";
|
|
66691
66938
|
registerSchema({
|
|
66692
66939
|
command: "studio.skills",
|
|
66693
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.",
|
|
66694
66941
|
args: {}
|
|
66695
66942
|
});
|
|
66696
|
-
var skillsCommand =
|
|
66943
|
+
var skillsCommand = defineCommand222({
|
|
66697
66944
|
meta: {
|
|
66698
66945
|
name: "skills",
|
|
66699
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"
|
|
@@ -66717,7 +66964,7 @@ var skillsCommand = defineCommand216({
|
|
|
66717
66964
|
});
|
|
66718
66965
|
|
|
66719
66966
|
// src/commands/studio/index.ts
|
|
66720
|
-
var studioCommand =
|
|
66967
|
+
var studioCommand = defineCommand223({
|
|
66721
66968
|
meta: {
|
|
66722
66969
|
name: "studio",
|
|
66723
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.
|
|
@@ -66751,7 +66998,7 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
66751
66998
|
generate: generateCommand,
|
|
66752
66999
|
animate: animateCommand,
|
|
66753
67000
|
get: getCommand5,
|
|
66754
|
-
list:
|
|
67001
|
+
list: listCommand19,
|
|
66755
67002
|
keep: keepCommand,
|
|
66756
67003
|
models: modelsCommand,
|
|
66757
67004
|
skills: skillsCommand,
|
|
@@ -66760,10 +67007,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
66760
67007
|
});
|
|
66761
67008
|
|
|
66762
67009
|
// src/commands/tag-manager/index.ts
|
|
66763
|
-
import { defineCommand as
|
|
67010
|
+
import { defineCommand as defineCommand227 } from "citty";
|
|
66764
67011
|
|
|
66765
67012
|
// src/commands/tag-manager/draft.ts
|
|
66766
|
-
import { defineCommand as
|
|
67013
|
+
import { defineCommand as defineCommand224 } from "citty";
|
|
66767
67014
|
|
|
66768
67015
|
// src/commands/tag-manager/shared.ts
|
|
66769
67016
|
import { readFileSync as readFileSync21 } from "fs";
|
|
@@ -66824,19 +67071,17 @@ var STAGE_HINTS2 = [
|
|
|
66824
67071
|
async function stageOp4(op) {
|
|
66825
67072
|
const chatId = requireChatId();
|
|
66826
67073
|
try {
|
|
66827
|
-
const {
|
|
66828
|
-
|
|
66829
|
-
);
|
|
66830
|
-
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 });
|
|
66831
67076
|
} catch (err) {
|
|
66832
67077
|
handleError8(err);
|
|
66833
67078
|
}
|
|
66834
67079
|
}
|
|
66835
|
-
async function draftAction3(
|
|
67080
|
+
async function draftAction3(path49, body, chat) {
|
|
66836
67081
|
const chatId = resolveChatId(chat);
|
|
66837
67082
|
try {
|
|
66838
|
-
const
|
|
66839
|
-
writeJsonEnvelope({ ok: true, data
|
|
67083
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
67084
|
+
writeJsonEnvelope({ ok: true, data });
|
|
66840
67085
|
return data;
|
|
66841
67086
|
} catch (err) {
|
|
66842
67087
|
handleError8(err);
|
|
@@ -66867,13 +67112,12 @@ function renderDraft2(response) {
|
|
|
66867
67112
|
async function draftList2(json, chat) {
|
|
66868
67113
|
const chatId = resolveChatId(chat);
|
|
66869
67114
|
try {
|
|
66870
|
-
const
|
|
66871
|
-
const { data, hints: hints2 } = splitHints(response);
|
|
67115
|
+
const data = await apiPost("/api/tag-manager/draft", { chatId });
|
|
66872
67116
|
if (json) {
|
|
66873
|
-
writeJsonEnvelope({ ok: true, data
|
|
67117
|
+
writeJsonEnvelope({ ok: true, data });
|
|
66874
67118
|
return;
|
|
66875
67119
|
}
|
|
66876
|
-
process.stdout.write(`${renderDraft2(data)}
|
|
67120
|
+
process.stdout.write(`${renderDraft2(data)}
|
|
66877
67121
|
`);
|
|
66878
67122
|
} catch (err) {
|
|
66879
67123
|
handleError8(err);
|
|
@@ -66889,13 +67133,13 @@ registerSchema({
|
|
|
66889
67133
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
66890
67134
|
}
|
|
66891
67135
|
});
|
|
66892
|
-
var draftCommand5 =
|
|
67136
|
+
var draftCommand5 = defineCommand224({
|
|
66893
67137
|
meta: {
|
|
66894
67138
|
name: "draft",
|
|
66895
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."
|
|
66896
67140
|
},
|
|
66897
67141
|
subCommands: {
|
|
66898
|
-
list:
|
|
67142
|
+
list: defineCommand224({
|
|
66899
67143
|
meta: {
|
|
66900
67144
|
name: "list",
|
|
66901
67145
|
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
@@ -66908,7 +67152,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66908
67152
|
await draftList2(args5.json === true, args5.chat);
|
|
66909
67153
|
}
|
|
66910
67154
|
}),
|
|
66911
|
-
show:
|
|
67155
|
+
show: defineCommand224({
|
|
66912
67156
|
meta: {
|
|
66913
67157
|
name: "show",
|
|
66914
67158
|
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
@@ -66925,7 +67169,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66925
67169
|
);
|
|
66926
67170
|
}
|
|
66927
67171
|
}),
|
|
66928
|
-
amend:
|
|
67172
|
+
amend: defineCommand224({
|
|
66929
67173
|
meta: {
|
|
66930
67174
|
name: "amend",
|
|
66931
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."
|
|
@@ -66942,7 +67186,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66942
67186
|
});
|
|
66943
67187
|
}
|
|
66944
67188
|
}),
|
|
66945
|
-
remove:
|
|
67189
|
+
remove: defineCommand224({
|
|
66946
67190
|
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
66947
67191
|
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
66948
67192
|
run: async ({ args: args5 }) => {
|
|
@@ -66951,7 +67195,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66951
67195
|
});
|
|
66952
67196
|
}
|
|
66953
67197
|
}),
|
|
66954
|
-
clear:
|
|
67198
|
+
clear: defineCommand224({
|
|
66955
67199
|
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
66956
67200
|
run: async () => {
|
|
66957
67201
|
await draftAction3("/api/tag-manager/draft/clear", {});
|
|
@@ -66961,7 +67205,7 @@ var draftCommand5 = defineCommand218({
|
|
|
66961
67205
|
});
|
|
66962
67206
|
|
|
66963
67207
|
// src/commands/tag-manager/read.ts
|
|
66964
|
-
import { defineCommand as
|
|
67208
|
+
import { defineCommand as defineCommand225 } from "citty";
|
|
66965
67209
|
registerSchema({
|
|
66966
67210
|
command: "tagManager.containers",
|
|
66967
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.",
|
|
@@ -67002,7 +67246,7 @@ function containersHints(containers) {
|
|
|
67002
67246
|
}))
|
|
67003
67247
|
});
|
|
67004
67248
|
}
|
|
67005
|
-
var containersCommand =
|
|
67249
|
+
var containersCommand = defineCommand225({
|
|
67006
67250
|
meta: {
|
|
67007
67251
|
name: "containers",
|
|
67008
67252
|
description: `List Tag Manager containers reachable by this company's connection.
|
|
@@ -67019,7 +67263,7 @@ Start here:
|
|
|
67019
67263
|
}
|
|
67020
67264
|
}
|
|
67021
67265
|
});
|
|
67022
|
-
var readCommand =
|
|
67266
|
+
var readCommand = defineCommand225({
|
|
67023
67267
|
meta: {
|
|
67024
67268
|
name: "read",
|
|
67025
67269
|
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
@@ -67061,7 +67305,7 @@ Examples:
|
|
|
67061
67305
|
});
|
|
67062
67306
|
|
|
67063
67307
|
// src/commands/tag-manager/write-commands.ts
|
|
67064
|
-
import { defineCommand as
|
|
67308
|
+
import { defineCommand as defineCommand226 } from "citty";
|
|
67065
67309
|
var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
|
|
67066
67310
|
var ENTITIES = [
|
|
67067
67311
|
{
|
|
@@ -67117,10 +67361,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
|
|
|
67117
67361
|
});
|
|
67118
67362
|
}
|
|
67119
67363
|
function entityCommand(entity, noun, example) {
|
|
67120
|
-
return
|
|
67364
|
+
return defineCommand226({
|
|
67121
67365
|
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
67122
67366
|
subCommands: {
|
|
67123
|
-
create:
|
|
67367
|
+
create: defineCommand226({
|
|
67124
67368
|
meta: {
|
|
67125
67369
|
name: "create",
|
|
67126
67370
|
description: `Stage a new ${noun}
|
|
@@ -67142,7 +67386,7 @@ Examples:
|
|
|
67142
67386
|
});
|
|
67143
67387
|
}
|
|
67144
67388
|
}),
|
|
67145
|
-
update:
|
|
67389
|
+
update: defineCommand226({
|
|
67146
67390
|
meta: {
|
|
67147
67391
|
name: "update",
|
|
67148
67392
|
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
@@ -67162,7 +67406,7 @@ Examples:
|
|
|
67162
67406
|
});
|
|
67163
67407
|
}
|
|
67164
67408
|
}),
|
|
67165
|
-
delete:
|
|
67409
|
+
delete: defineCommand226({
|
|
67166
67410
|
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
67167
67411
|
args: {
|
|
67168
67412
|
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
@@ -67203,7 +67447,7 @@ function builtinTypes(args5) {
|
|
|
67203
67447
|
}
|
|
67204
67448
|
return raw.split(",").map((entry) => entry.trim());
|
|
67205
67449
|
}
|
|
67206
|
-
var builtinCommand =
|
|
67450
|
+
var builtinCommand = defineCommand226({
|
|
67207
67451
|
meta: {
|
|
67208
67452
|
name: "builtin",
|
|
67209
67453
|
description: `Enable or disable built-in variables
|
|
@@ -67213,7 +67457,7 @@ Examples:
|
|
|
67213
67457
|
baker tag-manager builtin disable --types formId`
|
|
67214
67458
|
},
|
|
67215
67459
|
subCommands: {
|
|
67216
|
-
enable:
|
|
67460
|
+
enable: defineCommand226({
|
|
67217
67461
|
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
67218
67462
|
args: {
|
|
67219
67463
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67227,7 +67471,7 @@ Examples:
|
|
|
67227
67471
|
});
|
|
67228
67472
|
}
|
|
67229
67473
|
}),
|
|
67230
|
-
disable:
|
|
67474
|
+
disable: defineCommand226({
|
|
67231
67475
|
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
67232
67476
|
args: {
|
|
67233
67477
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67245,7 +67489,7 @@ Examples:
|
|
|
67245
67489
|
});
|
|
67246
67490
|
|
|
67247
67491
|
// src/commands/tag-manager/index.ts
|
|
67248
|
-
var tagManagerCommand =
|
|
67492
|
+
var tagManagerCommand = defineCommand227({
|
|
67249
67493
|
meta: {
|
|
67250
67494
|
name: "tag-manager",
|
|
67251
67495
|
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
@@ -67282,7 +67526,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
|
67282
67526
|
});
|
|
67283
67527
|
|
|
67284
67528
|
// src/commands/tags/index.ts
|
|
67285
|
-
import { defineCommand as
|
|
67529
|
+
import { defineCommand as defineCommand228 } from "citty";
|
|
67286
67530
|
|
|
67287
67531
|
// src/commands/tags/shared.ts
|
|
67288
67532
|
function failApi3(err) {
|
|
@@ -67362,7 +67606,7 @@ async function listTags(json) {
|
|
|
67362
67606
|
var listArgs12 = {
|
|
67363
67607
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
|
|
67364
67608
|
};
|
|
67365
|
-
var
|
|
67609
|
+
var listCommand20 = defineCommand228({
|
|
67366
67610
|
meta: {
|
|
67367
67611
|
name: "list",
|
|
67368
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"
|
|
@@ -67381,7 +67625,7 @@ async function listDraft4(chat) {
|
|
|
67381
67625
|
failApi3(err);
|
|
67382
67626
|
}
|
|
67383
67627
|
}
|
|
67384
|
-
var draftCommand6 =
|
|
67628
|
+
var draftCommand6 = defineCommand228({
|
|
67385
67629
|
meta: {
|
|
67386
67630
|
name: "draft",
|
|
67387
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."
|
|
@@ -67391,7 +67635,7 @@ var draftCommand6 = defineCommand222({
|
|
|
67391
67635
|
await listDraft4(args5.chat);
|
|
67392
67636
|
}
|
|
67393
67637
|
});
|
|
67394
|
-
var tagsCommand4 =
|
|
67638
|
+
var tagsCommand4 = defineCommand228({
|
|
67395
67639
|
meta: {
|
|
67396
67640
|
name: "tags",
|
|
67397
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.
|
|
@@ -67408,7 +67652,7 @@ Examples:
|
|
|
67408
67652
|
Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
67409
67653
|
},
|
|
67410
67654
|
subCommands: {
|
|
67411
|
-
list:
|
|
67655
|
+
list: listCommand20,
|
|
67412
67656
|
draft: draftCommand6
|
|
67413
67657
|
},
|
|
67414
67658
|
// Bare `baker tags` lists the effective tags. `args` stays so citty knows this
|
|
@@ -67420,10 +67664,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
67420
67664
|
});
|
|
67421
67665
|
|
|
67422
67666
|
// src/commands/testimonials/index.ts
|
|
67423
|
-
import { defineCommand as
|
|
67667
|
+
import { defineCommand as defineCommand232 } from "citty";
|
|
67424
67668
|
|
|
67425
67669
|
// src/commands/testimonials/get.ts
|
|
67426
|
-
import { defineCommand as
|
|
67670
|
+
import { defineCommand as defineCommand229 } from "citty";
|
|
67427
67671
|
registerSchema({
|
|
67428
67672
|
command: "testimonials.get",
|
|
67429
67673
|
description: "Get a single testimonial by ID",
|
|
@@ -67431,7 +67675,7 @@ registerSchema({
|
|
|
67431
67675
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
67432
67676
|
}
|
|
67433
67677
|
});
|
|
67434
|
-
var getCommand6 =
|
|
67678
|
+
var getCommand6 = defineCommand229({
|
|
67435
67679
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
67436
67680
|
args: {
|
|
67437
67681
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -67468,7 +67712,7 @@ var getCommand6 = defineCommand223({
|
|
|
67468
67712
|
});
|
|
67469
67713
|
|
|
67470
67714
|
// src/commands/testimonials/list.ts
|
|
67471
|
-
import { defineCommand as
|
|
67715
|
+
import { defineCommand as defineCommand230 } from "citty";
|
|
67472
67716
|
|
|
67473
67717
|
// src/commands/testimonials/emptyCorpusHints.ts
|
|
67474
67718
|
function resolveEmptyReason({
|
|
@@ -67625,7 +67869,7 @@ function buildListParams(args5) {
|
|
|
67625
67869
|
}
|
|
67626
67870
|
return params;
|
|
67627
67871
|
}
|
|
67628
|
-
var
|
|
67872
|
+
var listCommand21 = defineCommand230({
|
|
67629
67873
|
meta: {
|
|
67630
67874
|
name: "list",
|
|
67631
67875
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -67685,7 +67929,7 @@ var listCommand20 = defineCommand224({
|
|
|
67685
67929
|
});
|
|
67686
67930
|
|
|
67687
67931
|
// src/commands/testimonials/search.ts
|
|
67688
|
-
import { defineCommand as
|
|
67932
|
+
import { defineCommand as defineCommand231 } from "citty";
|
|
67689
67933
|
var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
|
|
67690
67934
|
function languageBiasHint(results, requestedLanguage) {
|
|
67691
67935
|
if (requestedLanguage) {
|
|
@@ -67764,7 +68008,7 @@ function buildSearchRequest(query, args5) {
|
|
|
67764
68008
|
}
|
|
67765
68009
|
return body;
|
|
67766
68010
|
}
|
|
67767
|
-
var searchCommand3 =
|
|
68011
|
+
var searchCommand3 = defineCommand231({
|
|
67768
68012
|
meta: {
|
|
67769
68013
|
name: "search",
|
|
67770
68014
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -67828,7 +68072,7 @@ var searchCommand3 = defineCommand225({
|
|
|
67828
68072
|
var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
67829
68073
|
|
|
67830
68074
|
// src/commands/testimonials/index.ts
|
|
67831
|
-
var testimonialsCommand =
|
|
68075
|
+
var testimonialsCommand = defineCommand232({
|
|
67832
68076
|
meta: {
|
|
67833
68077
|
name: "testimonials",
|
|
67834
68078
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -67844,16 +68088,16 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
67844
68088
|
subCommands: {
|
|
67845
68089
|
get: getCommand6,
|
|
67846
68090
|
search: searchCommand3,
|
|
67847
|
-
list:
|
|
68091
|
+
list: listCommand21,
|
|
67848
68092
|
tags: tagsCommand5
|
|
67849
68093
|
}
|
|
67850
68094
|
});
|
|
67851
68095
|
|
|
67852
68096
|
// src/commands/videos/index.ts
|
|
67853
|
-
import { defineCommand as
|
|
68097
|
+
import { defineCommand as defineCommand241 } from "citty";
|
|
67854
68098
|
|
|
67855
68099
|
// src/commands/videos/delete.ts
|
|
67856
|
-
import { defineCommand as
|
|
68100
|
+
import { defineCommand as defineCommand233 } from "citty";
|
|
67857
68101
|
registerSchema({
|
|
67858
68102
|
command: "videos.delete",
|
|
67859
68103
|
description: "Delete a video by ID",
|
|
@@ -67867,7 +68111,7 @@ registerSchema({
|
|
|
67867
68111
|
}
|
|
67868
68112
|
}
|
|
67869
68113
|
});
|
|
67870
|
-
var deleteCommand4 =
|
|
68114
|
+
var deleteCommand4 = defineCommand233({
|
|
67871
68115
|
meta: {
|
|
67872
68116
|
name: "delete",
|
|
67873
68117
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -67908,7 +68152,7 @@ var deleteCommand4 = defineCommand227({
|
|
|
67908
68152
|
});
|
|
67909
68153
|
|
|
67910
68154
|
// src/commands/videos/describe.ts
|
|
67911
|
-
import { defineCommand as
|
|
68155
|
+
import { defineCommand as defineCommand234 } from "citty";
|
|
67912
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.";
|
|
67913
68157
|
registerSchema({
|
|
67914
68158
|
command: "videos.describe",
|
|
@@ -67925,7 +68169,7 @@ registerSchema({
|
|
|
67925
68169
|
full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
|
|
67926
68170
|
}
|
|
67927
68171
|
});
|
|
67928
|
-
var describeCommand2 =
|
|
68172
|
+
var describeCommand2 = defineCommand234({
|
|
67929
68173
|
meta: {
|
|
67930
68174
|
name: "describe",
|
|
67931
68175
|
description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
|
|
@@ -67982,108 +68226,12 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
67982
68226
|
}
|
|
67983
68227
|
});
|
|
67984
68228
|
|
|
67985
|
-
// src/commands/videos/
|
|
67986
|
-
import {
|
|
67987
|
-
|
|
67988
|
-
command: "videos.get",
|
|
67989
|
-
description: "Get a single video by ID",
|
|
67990
|
-
args: {
|
|
67991
|
-
id: { type: "string", description: "Video ID", required: true }
|
|
67992
|
-
}
|
|
67993
|
-
});
|
|
67994
|
-
var getCommand7 = defineCommand229({
|
|
67995
|
-
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
67996
|
-
args: {
|
|
67997
|
-
id: { type: "positional", description: "Video ID", required: false },
|
|
67998
|
-
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
67999
|
-
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
68000
|
-
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
68001
|
-
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
68002
|
-
},
|
|
68003
|
-
run: async ({ args: args5 }) => {
|
|
68004
|
-
try {
|
|
68005
|
-
const id = args5.id || args5["video-id"];
|
|
68006
|
-
if (!id) {
|
|
68007
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
68008
|
-
process.exit(1);
|
|
68009
|
-
}
|
|
68010
|
-
validateConvexId(id);
|
|
68011
|
-
const data = await apiGet("/api/videos/get", { id });
|
|
68012
|
-
writeOutput(
|
|
68013
|
-
{ ok: true, data },
|
|
68014
|
-
args5.output || "json",
|
|
68015
|
-
args5.fields ? args5.fields.split(",") : void 0,
|
|
68016
|
-
args5.full,
|
|
68017
|
-
videoNormalizer
|
|
68018
|
-
);
|
|
68019
|
-
} catch (err) {
|
|
68020
|
-
if (err instanceof ApiError) {
|
|
68021
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68022
|
-
process.exit(1);
|
|
68023
|
-
}
|
|
68024
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
68025
|
-
process.exit(1);
|
|
68026
|
-
}
|
|
68027
|
-
}
|
|
68028
|
-
});
|
|
68029
|
-
|
|
68030
|
-
// src/commands/videos/group.ts
|
|
68031
|
-
import { defineCommand as defineCommand230 } from "citty";
|
|
68032
|
-
registerSchema({
|
|
68033
|
-
command: "videos.group",
|
|
68034
|
-
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
68035
|
-
args: {
|
|
68036
|
-
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
68037
|
-
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
68038
|
-
}
|
|
68039
|
-
});
|
|
68040
|
-
var groupCommand2 = defineCommand230({
|
|
68041
|
-
meta: {
|
|
68042
|
-
name: "group",
|
|
68043
|
-
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>"
|
|
68044
|
-
},
|
|
68045
|
-
args: {
|
|
68046
|
-
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
68047
|
-
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
68048
|
-
},
|
|
68049
|
-
run: async ({ args: args5 }) => {
|
|
68050
|
-
await runMediaGroupLookup({
|
|
68051
|
-
id: args5.id,
|
|
68052
|
-
groupKey: args5["group-key"],
|
|
68053
|
-
path: "/api/videos/group",
|
|
68054
|
-
idLabel: "a video or image id"
|
|
68055
|
-
});
|
|
68056
|
-
}
|
|
68057
|
-
});
|
|
68058
|
-
|
|
68059
|
-
// src/commands/videos/ingest.ts
|
|
68060
|
-
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";
|
|
68061
68232
|
import { tmpdir as tmpdir4 } from "os";
|
|
68062
68233
|
import path47 from "path";
|
|
68063
|
-
import { defineCommand as
|
|
68064
|
-
|
|
68065
|
-
// src/lib/streamUpload.ts
|
|
68066
|
-
import { createHash as createHash2 } from "crypto";
|
|
68067
|
-
import { createReadStream } from "fs";
|
|
68068
|
-
import { Readable } from "stream";
|
|
68069
|
-
import { pipeline } from "stream/promises";
|
|
68070
|
-
async function hashFile(filePath) {
|
|
68071
|
-
const hash = createHash2("sha256");
|
|
68072
|
-
await pipeline(createReadStream(filePath), hash);
|
|
68073
|
-
return hash.digest("hex");
|
|
68074
|
-
}
|
|
68075
|
-
async function putFileStreamed(args5) {
|
|
68076
|
-
const body = Readable.toWeb(createReadStream(args5.filePath));
|
|
68077
|
-
return await fetch(args5.putUrl, {
|
|
68078
|
-
method: "PUT",
|
|
68079
|
-
body,
|
|
68080
|
-
headers: {
|
|
68081
|
-
"Content-Type": args5.contentType,
|
|
68082
|
-
"Content-Length": String(args5.sizeBytes)
|
|
68083
|
-
},
|
|
68084
|
-
duplex: "half"
|
|
68085
|
-
});
|
|
68086
|
-
}
|
|
68234
|
+
import { defineCommand as defineCommand235 } from "citty";
|
|
68087
68235
|
|
|
68088
68236
|
// src/commands/videos/videoPlatforms.ts
|
|
68089
68237
|
var PLATFORM_DOMAINS = {
|
|
@@ -68092,6 +68240,7 @@ var PLATFORM_DOMAINS = {
|
|
|
68092
68240
|
tiktok: ["tiktok.com"],
|
|
68093
68241
|
twitter: ["twitter.com", "x.com", "vxtwitter.com", "fixvx.com"],
|
|
68094
68242
|
facebook: ["facebook.com", "fb.watch", "fb.com"],
|
|
68243
|
+
linkedin: ["linkedin.com", "lnkd.in"],
|
|
68095
68244
|
reddit: ["reddit.com", "redd.it"],
|
|
68096
68245
|
vimeo: ["vimeo.com"],
|
|
68097
68246
|
dailymotion: ["dailymotion.com", "dai.ly"],
|
|
@@ -68196,6 +68345,218 @@ function safePathname(rawUrl) {
|
|
|
68196
68345
|
}
|
|
68197
68346
|
}
|
|
68198
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
|
+
|
|
68199
68560
|
// src/commands/videos/ingest.ts
|
|
68200
68561
|
registerSchema({
|
|
68201
68562
|
command: "videos.ingest",
|
|
@@ -68224,7 +68585,7 @@ registerSchema({
|
|
|
68224
68585
|
"dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
|
|
68225
68586
|
}
|
|
68226
68587
|
});
|
|
68227
|
-
var ingestCommand2 =
|
|
68588
|
+
var ingestCommand2 = defineCommand238({
|
|
68228
68589
|
meta: {
|
|
68229
68590
|
name: "ingest",
|
|
68230
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"
|
|
@@ -68410,7 +68771,7 @@ function ingestUrl(args5) {
|
|
|
68410
68771
|
}
|
|
68411
68772
|
async function downloadThenIngest(args5, country) {
|
|
68412
68773
|
const vimeoCookie = captureVimeoCookie();
|
|
68413
|
-
const workDir = await
|
|
68774
|
+
const workDir = await mkdtemp4(path48.join(tmpdir5(), "videos-ingest-"));
|
|
68414
68775
|
try {
|
|
68415
68776
|
const probe = await probeYtDlp({ url: args5.url, country, vimeoCookie, cookieDir: workDir });
|
|
68416
68777
|
if (isAudioOnly(probe.info)) {
|
|
@@ -68467,7 +68828,7 @@ async function downloadThenIngest(args5, country) {
|
|
|
68467
68828
|
...reducedQuality ? { reducedQuality: true } : {}
|
|
68468
68829
|
};
|
|
68469
68830
|
} finally {
|
|
68470
|
-
await
|
|
68831
|
+
await rm10(workDir, { recursive: true, force: true }).catch(() => {
|
|
68471
68832
|
});
|
|
68472
68833
|
}
|
|
68473
68834
|
}
|
|
@@ -68486,7 +68847,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
|
|
|
68486
68847
|
}
|
|
68487
68848
|
|
|
68488
68849
|
// src/commands/videos/search.ts
|
|
68489
|
-
import { defineCommand as
|
|
68850
|
+
import { defineCommand as defineCommand239 } from "citty";
|
|
68490
68851
|
registerSchema({
|
|
68491
68852
|
command: "videos.search",
|
|
68492
68853
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -68496,7 +68857,7 @@ registerSchema({
|
|
|
68496
68857
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
68497
68858
|
}
|
|
68498
68859
|
});
|
|
68499
|
-
var searchCommand4 =
|
|
68860
|
+
var searchCommand4 = defineCommand239({
|
|
68500
68861
|
meta: {
|
|
68501
68862
|
name: "search",
|
|
68502
68863
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -68548,7 +68909,7 @@ var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
|
68548
68909
|
// src/commands/videos/upload.ts
|
|
68549
68910
|
import { readFile as readFile33, stat as stat12 } from "fs/promises";
|
|
68550
68911
|
import { basename as basename3, extname as extname4 } from "path";
|
|
68551
|
-
import { defineCommand as
|
|
68912
|
+
import { defineCommand as defineCommand240 } from "citty";
|
|
68552
68913
|
var MIME_MAP = {
|
|
68553
68914
|
".mp4": "video/mp4",
|
|
68554
68915
|
".mov": "video/quicktime",
|
|
@@ -68590,7 +68951,7 @@ function detectContentType(filePath) {
|
|
|
68590
68951
|
function isRemoteUrl3(value) {
|
|
68591
68952
|
return /^https?:\/\//i.test(value);
|
|
68592
68953
|
}
|
|
68593
|
-
var uploadCommand2 =
|
|
68954
|
+
var uploadCommand2 = defineCommand240({
|
|
68594
68955
|
meta: {
|
|
68595
68956
|
name: "upload",
|
|
68596
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"
|
|
@@ -68674,10 +69035,10 @@ var uploadCommand2 = defineCommand233({
|
|
|
68674
69035
|
});
|
|
68675
69036
|
|
|
68676
69037
|
// src/commands/videos/index.ts
|
|
68677
|
-
var videosCommand =
|
|
69038
|
+
var videosCommand = defineCommand241({
|
|
68678
69039
|
meta: {
|
|
68679
69040
|
name: "videos",
|
|
68680
|
-
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.
|
|
68681
69042
|
|
|
68682
69043
|
Examples:
|
|
68683
69044
|
baker videos search "product demo" --limit 5
|
|
@@ -68685,6 +69046,7 @@ Examples:
|
|
|
68685
69046
|
baker videos get <video-id>
|
|
68686
69047
|
baker videos upload ./demo.mp4
|
|
68687
69048
|
baker videos ingest https://www.youtube.com/watch?v=abc123
|
|
69049
|
+
baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips
|
|
68688
69050
|
baker videos describe <video-id> --description "Customer testimonial, 30s"
|
|
68689
69051
|
baker videos delete <video-id> --dry-run
|
|
68690
69052
|
baker videos tags
|
|
@@ -68696,6 +69058,7 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
68696
69058
|
search: searchCommand4,
|
|
68697
69059
|
upload: uploadCommand2,
|
|
68698
69060
|
ingest: ingestCommand2,
|
|
69061
|
+
fetch: fetchCommand2,
|
|
68699
69062
|
describe: describeCommand2,
|
|
68700
69063
|
delete: deleteCommand4,
|
|
68701
69064
|
tags: tagsCommand6
|
|
@@ -68703,10 +69066,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
68703
69066
|
});
|
|
68704
69067
|
|
|
68705
69068
|
// src/commands/winning-ads/index.ts
|
|
68706
|
-
import { defineCommand as
|
|
69069
|
+
import { defineCommand as defineCommand254 } from "citty";
|
|
68707
69070
|
|
|
68708
69071
|
// src/commands/winning-ads/advertisers.ts
|
|
68709
|
-
import { defineCommand as
|
|
69072
|
+
import { defineCommand as defineCommand242 } from "citty";
|
|
68710
69073
|
|
|
68711
69074
|
// src/commands/winning-ads/shared.ts
|
|
68712
69075
|
function splitList3(value) {
|
|
@@ -68715,7 +69078,7 @@ function splitList3(value) {
|
|
|
68715
69078
|
}
|
|
68716
69079
|
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
68717
69080
|
}
|
|
68718
|
-
function
|
|
69081
|
+
function reportError3(err) {
|
|
68719
69082
|
if (err instanceof ApiError) {
|
|
68720
69083
|
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68721
69084
|
process.exit(1);
|
|
@@ -68759,7 +69122,7 @@ function advertiserNormalizer(record, full) {
|
|
|
68759
69122
|
last_synced_at: record.last_synced_at ?? null
|
|
68760
69123
|
};
|
|
68761
69124
|
}
|
|
68762
|
-
var advertisersCommand2 =
|
|
69125
|
+
var advertisersCommand2 = defineCommand242({
|
|
68763
69126
|
meta: {
|
|
68764
69127
|
name: "advertisers",
|
|
68765
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'
|
|
@@ -68811,13 +69174,13 @@ var advertisersCommand2 = defineCommand235({
|
|
|
68811
69174
|
advertiserNormalizer
|
|
68812
69175
|
);
|
|
68813
69176
|
} catch (err) {
|
|
68814
|
-
|
|
69177
|
+
reportError3(err);
|
|
68815
69178
|
}
|
|
68816
69179
|
}
|
|
68817
69180
|
});
|
|
68818
69181
|
|
|
68819
69182
|
// src/commands/winning-ads/brief.ts
|
|
68820
|
-
import { defineCommand as
|
|
69183
|
+
import { defineCommand as defineCommand243 } from "citty";
|
|
68821
69184
|
registerSchema({
|
|
68822
69185
|
command: "winning-ads.brief",
|
|
68823
69186
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -68863,7 +69226,7 @@ function parseDna(raw) {
|
|
|
68863
69226
|
}
|
|
68864
69227
|
return parsed;
|
|
68865
69228
|
}
|
|
68866
|
-
var briefCommand =
|
|
69229
|
+
var briefCommand = defineCommand243({
|
|
68867
69230
|
meta: {
|
|
68868
69231
|
name: "brief",
|
|
68869
69232
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -68893,13 +69256,13 @@ var briefCommand = defineCommand236({
|
|
|
68893
69256
|
const data = await apiPost("/api/ad-library/brief", body);
|
|
68894
69257
|
writeJson({ ok: true, data });
|
|
68895
69258
|
} catch (err) {
|
|
68896
|
-
|
|
69259
|
+
reportError3(err);
|
|
68897
69260
|
}
|
|
68898
69261
|
}
|
|
68899
69262
|
});
|
|
68900
69263
|
|
|
68901
69264
|
// src/commands/winning-ads/content.ts
|
|
68902
|
-
import { defineCommand as
|
|
69265
|
+
import { defineCommand as defineCommand244 } from "citty";
|
|
68903
69266
|
registerSchema({
|
|
68904
69267
|
command: "winning-ads.content",
|
|
68905
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.",
|
|
@@ -68912,7 +69275,7 @@ registerSchema({
|
|
|
68912
69275
|
}
|
|
68913
69276
|
}
|
|
68914
69277
|
});
|
|
68915
|
-
var contentCommand =
|
|
69278
|
+
var contentCommand = defineCommand244({
|
|
68916
69279
|
meta: {
|
|
68917
69280
|
name: "content",
|
|
68918
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"
|
|
@@ -68955,13 +69318,13 @@ var contentCommand = defineCommand237({
|
|
|
68955
69318
|
adContentNormalizer
|
|
68956
69319
|
);
|
|
68957
69320
|
} catch (err) {
|
|
68958
|
-
|
|
69321
|
+
reportError3(err);
|
|
68959
69322
|
}
|
|
68960
69323
|
}
|
|
68961
69324
|
});
|
|
68962
69325
|
|
|
68963
69326
|
// src/commands/winning-ads/feed.ts
|
|
68964
|
-
import { defineCommand as
|
|
69327
|
+
import { defineCommand as defineCommand245 } from "citty";
|
|
68965
69328
|
function buildFeedParams(input) {
|
|
68966
69329
|
const params = {};
|
|
68967
69330
|
const advertiser = splitList3(input.advertiser);
|
|
@@ -69013,7 +69376,7 @@ registerSchema({
|
|
|
69013
69376
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
69014
69377
|
}
|
|
69015
69378
|
});
|
|
69016
|
-
var feedCommand2 =
|
|
69379
|
+
var feedCommand2 = defineCommand245({
|
|
69017
69380
|
meta: {
|
|
69018
69381
|
name: "feed",
|
|
69019
69382
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -69092,13 +69455,13 @@ var feedCommand2 = defineCommand238({
|
|
|
69092
69455
|
`);
|
|
69093
69456
|
}
|
|
69094
69457
|
} catch (err) {
|
|
69095
|
-
|
|
69458
|
+
reportError3(err);
|
|
69096
69459
|
}
|
|
69097
69460
|
}
|
|
69098
69461
|
});
|
|
69099
69462
|
|
|
69100
69463
|
// src/commands/winning-ads/follow.ts
|
|
69101
|
-
import { defineCommand as
|
|
69464
|
+
import { defineCommand as defineCommand246 } from "citty";
|
|
69102
69465
|
var PLATFORMS = adLibraryPlatformSchema.options;
|
|
69103
69466
|
registerSchema({
|
|
69104
69467
|
command: "winning-ads.follow",
|
|
@@ -69113,7 +69476,7 @@ registerSchema({
|
|
|
69113
69476
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
69114
69477
|
}
|
|
69115
69478
|
});
|
|
69116
|
-
var followCommand =
|
|
69479
|
+
var followCommand = defineCommand246({
|
|
69117
69480
|
meta: {
|
|
69118
69481
|
name: "follow",
|
|
69119
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'
|
|
@@ -69154,13 +69517,13 @@ var followCommand = defineCommand239({
|
|
|
69154
69517
|
}
|
|
69155
69518
|
writeJson({ ok: true, data, hints: hints2 });
|
|
69156
69519
|
} catch (err) {
|
|
69157
|
-
|
|
69520
|
+
reportError3(err);
|
|
69158
69521
|
}
|
|
69159
69522
|
}
|
|
69160
69523
|
});
|
|
69161
69524
|
|
|
69162
69525
|
// src/commands/winning-ads/follow-competitors.ts
|
|
69163
|
-
import { defineCommand as
|
|
69526
|
+
import { defineCommand as defineCommand247 } from "citty";
|
|
69164
69527
|
var PLATFORMS2 = adLibraryPlatformSchema.options;
|
|
69165
69528
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
69166
69529
|
function buildFollowBatchBody(input) {
|
|
@@ -69193,7 +69556,7 @@ registerSchema({
|
|
|
69193
69556
|
}
|
|
69194
69557
|
}
|
|
69195
69558
|
});
|
|
69196
|
-
var followCompetitorsCommand =
|
|
69559
|
+
var followCompetitorsCommand = defineCommand247({
|
|
69197
69560
|
meta: {
|
|
69198
69561
|
name: "follow-competitors",
|
|
69199
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"'
|
|
@@ -69262,13 +69625,13 @@ var followCompetitorsCommand = defineCommand240({
|
|
|
69262
69625
|
}
|
|
69263
69626
|
writeJson({ ok: true, data, hints: hints2.length > 0 ? hints2 : void 0 });
|
|
69264
69627
|
} catch (err) {
|
|
69265
|
-
|
|
69628
|
+
reportError3(err);
|
|
69266
69629
|
}
|
|
69267
69630
|
}
|
|
69268
69631
|
});
|
|
69269
69632
|
|
|
69270
69633
|
// src/commands/winning-ads/following.ts
|
|
69271
|
-
import { defineCommand as
|
|
69634
|
+
import { defineCommand as defineCommand248 } from "citty";
|
|
69272
69635
|
registerSchema({
|
|
69273
69636
|
command: "winning-ads.following",
|
|
69274
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.",
|
|
@@ -69322,7 +69685,7 @@ function followingNormalizer(record, full) {
|
|
|
69322
69685
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
69323
69686
|
};
|
|
69324
69687
|
}
|
|
69325
|
-
var followingCommand =
|
|
69688
|
+
var followingCommand = defineCommand248({
|
|
69326
69689
|
meta: {
|
|
69327
69690
|
name: "following",
|
|
69328
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"
|
|
@@ -69352,13 +69715,13 @@ var followingCommand = defineCommand241({
|
|
|
69352
69715
|
followingNormalizer
|
|
69353
69716
|
);
|
|
69354
69717
|
} catch (err) {
|
|
69355
|
-
|
|
69718
|
+
reportError3(err);
|
|
69356
69719
|
}
|
|
69357
69720
|
}
|
|
69358
69721
|
});
|
|
69359
69722
|
|
|
69360
69723
|
// src/commands/winning-ads/patterns.ts
|
|
69361
|
-
import { defineCommand as
|
|
69724
|
+
import { defineCommand as defineCommand249 } from "citty";
|
|
69362
69725
|
registerSchema({
|
|
69363
69726
|
command: "winning-ads.patterns",
|
|
69364
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.",
|
|
@@ -69397,7 +69760,7 @@ function discriminatorRow(record) {
|
|
|
69397
69760
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
69398
69761
|
};
|
|
69399
69762
|
}
|
|
69400
|
-
var patternsCommand =
|
|
69763
|
+
var patternsCommand = defineCommand249({
|
|
69401
69764
|
meta: {
|
|
69402
69765
|
name: "patterns",
|
|
69403
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"
|
|
@@ -69447,13 +69810,13 @@ var patternsCommand = defineCommand242({
|
|
|
69447
69810
|
(record) => discriminatorRow(record)
|
|
69448
69811
|
);
|
|
69449
69812
|
} catch (err) {
|
|
69450
|
-
|
|
69813
|
+
reportError3(err);
|
|
69451
69814
|
}
|
|
69452
69815
|
}
|
|
69453
69816
|
});
|
|
69454
69817
|
|
|
69455
69818
|
// src/commands/winning-ads/search.ts
|
|
69456
|
-
import { defineCommand as
|
|
69819
|
+
import { defineCommand as defineCommand250 } from "citty";
|
|
69457
69820
|
registerSchema({
|
|
69458
69821
|
command: "winning-ads.search",
|
|
69459
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.",
|
|
@@ -69589,9 +69952,9 @@ function reportSearchError(err) {
|
|
|
69589
69952
|
writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
|
|
69590
69953
|
process.exit(1);
|
|
69591
69954
|
}
|
|
69592
|
-
|
|
69955
|
+
reportError3(err);
|
|
69593
69956
|
}
|
|
69594
|
-
var searchCommand5 =
|
|
69957
|
+
var searchCommand5 = defineCommand250({
|
|
69595
69958
|
meta: {
|
|
69596
69959
|
name: "search",
|
|
69597
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"
|
|
@@ -69711,7 +70074,7 @@ var searchCommand5 = defineCommand243({
|
|
|
69711
70074
|
});
|
|
69712
70075
|
|
|
69713
70076
|
// src/commands/winning-ads/seeds.ts
|
|
69714
|
-
import { defineCommand as
|
|
70077
|
+
import { defineCommand as defineCommand251 } from "citty";
|
|
69715
70078
|
function leanRow(r) {
|
|
69716
70079
|
return {
|
|
69717
70080
|
key: r.key,
|
|
@@ -69739,7 +70102,7 @@ function makeSeedCommand(opts) {
|
|
|
69739
70102
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
69740
70103
|
}
|
|
69741
70104
|
});
|
|
69742
|
-
return
|
|
70105
|
+
return defineCommand251({
|
|
69743
70106
|
meta: { name: opts.name, description: opts.description },
|
|
69744
70107
|
args: {
|
|
69745
70108
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -69766,7 +70129,7 @@ function makeSeedCommand(opts) {
|
|
|
69766
70129
|
}
|
|
69767
70130
|
writeOutput({ ok: true, data: projected }, output);
|
|
69768
70131
|
} catch (err) {
|
|
69769
|
-
|
|
70132
|
+
reportError3(err);
|
|
69770
70133
|
}
|
|
69771
70134
|
}
|
|
69772
70135
|
});
|
|
@@ -69788,7 +70151,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
69788
70151
|
});
|
|
69789
70152
|
|
|
69790
70153
|
// src/commands/winning-ads/unfollow.ts
|
|
69791
|
-
import { defineCommand as
|
|
70154
|
+
import { defineCommand as defineCommand252 } from "citty";
|
|
69792
70155
|
registerSchema({
|
|
69793
70156
|
command: "winning-ads.unfollow",
|
|
69794
70157
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -69796,7 +70159,7 @@ registerSchema({
|
|
|
69796
70159
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
69797
70160
|
}
|
|
69798
70161
|
});
|
|
69799
|
-
var unfollowCommand =
|
|
70162
|
+
var unfollowCommand = defineCommand252({
|
|
69800
70163
|
meta: {
|
|
69801
70164
|
name: "unfollow",
|
|
69802
70165
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -69811,13 +70174,13 @@ var unfollowCommand = defineCommand245({
|
|
|
69811
70174
|
});
|
|
69812
70175
|
writeJson({ ok: true, data });
|
|
69813
70176
|
} catch (err) {
|
|
69814
|
-
|
|
70177
|
+
reportError3(err);
|
|
69815
70178
|
}
|
|
69816
70179
|
}
|
|
69817
70180
|
});
|
|
69818
70181
|
|
|
69819
70182
|
// src/commands/winning-ads/winners.ts
|
|
69820
|
-
import { defineCommand as
|
|
70183
|
+
import { defineCommand as defineCommand253 } from "citty";
|
|
69821
70184
|
registerSchema({
|
|
69822
70185
|
command: "winning-ads.winners",
|
|
69823
70186
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -69827,7 +70190,7 @@ registerSchema({
|
|
|
69827
70190
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
|
|
69828
70191
|
}
|
|
69829
70192
|
});
|
|
69830
|
-
var winnersCommand =
|
|
70193
|
+
var winnersCommand = defineCommand253({
|
|
69831
70194
|
meta: {
|
|
69832
70195
|
name: "winners",
|
|
69833
70196
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -69871,13 +70234,13 @@ var winnersCommand = defineCommand246({
|
|
|
69871
70234
|
winningAdNormalizer
|
|
69872
70235
|
);
|
|
69873
70236
|
} catch (err) {
|
|
69874
|
-
|
|
70237
|
+
reportError3(err);
|
|
69875
70238
|
}
|
|
69876
70239
|
}
|
|
69877
70240
|
});
|
|
69878
70241
|
|
|
69879
70242
|
// src/commands/winning-ads/index.ts
|
|
69880
|
-
var winningAdsCommand =
|
|
70243
|
+
var winningAdsCommand = defineCommand254({
|
|
69881
70244
|
meta: {
|
|
69882
70245
|
name: "winning-ads",
|
|
69883
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.
|
|
@@ -69949,7 +70312,7 @@ function getCliVersion() {
|
|
|
69949
70312
|
}
|
|
69950
70313
|
|
|
69951
70314
|
// src/cli.ts
|
|
69952
|
-
var main =
|
|
70315
|
+
var main = defineCommand255({
|
|
69953
70316
|
meta: {
|
|
69954
70317
|
name: "baker",
|
|
69955
70318
|
version: getCliVersion(),
|
|
@@ -69989,6 +70352,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
69989
70352
|
history: historyCommand2,
|
|
69990
70353
|
hubspot: hubspotCommand,
|
|
69991
70354
|
"winning-ads": winningAdsCommand,
|
|
70355
|
+
"media-sources": mediaSourcesCommand,
|
|
69992
70356
|
mcp: mcpCommand,
|
|
69993
70357
|
schema: schemaCommand2
|
|
69994
70358
|
}
|