@koda-sl/baker-cli 0.380.0-dev.824ccf426 → 0.380.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -40
- package/dist/{chunk-HOMVJ2D3.js → chunk-FGHMWBUD.js} +5 -11
- package/dist/chunk-FGHMWBUD.js.map +1 -0
- package/dist/cli.js +480 -864
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-HOMVJ2D3.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-FGHMWBUD.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 defineCommand248, runMain } from "citty";
|
|
147
147
|
|
|
148
148
|
// src/cache-flag.ts
|
|
149
149
|
var NO_CACHE_ARG = {
|
|
@@ -975,6 +975,9 @@ 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"];
|
|
978
981
|
var CREATIVE_INTENDED_STATUSES = ["ACTIVE", "PAUSED", "DRAFT"];
|
|
979
982
|
var CTA_TYPES = [
|
|
980
983
|
"APPLY",
|
|
@@ -1105,17 +1108,26 @@ var entityStatusSchema = z3.enum(["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "D
|
|
|
1105
1108
|
function currencyMinimums(currencyCode) {
|
|
1106
1109
|
return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;
|
|
1107
1110
|
}
|
|
1108
|
-
var
|
|
1111
|
+
var campaignGroupFieldsSchema = z3.object({
|
|
1109
1112
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax),
|
|
1110
1113
|
runSchedule: runScheduleSchema,
|
|
1111
1114
|
totalBudget: moneySchema.optional(),
|
|
1112
|
-
status:
|
|
1115
|
+
status: z3.enum(CAMPAIGN_GROUP_CREATE_STATUSES).default("DRAFT")
|
|
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
|
+
}
|
|
1113
1125
|
});
|
|
1114
1126
|
var campaignGroupUpdateSchema = z3.object({
|
|
1115
1127
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax).optional(),
|
|
1116
1128
|
runSchedule: runScheduleSchema.optional(),
|
|
1117
1129
|
totalBudget: moneySchema.optional(),
|
|
1118
|
-
status:
|
|
1130
|
+
status: z3.enum(CAMPAIGN_GROUP_STATUSES).optional()
|
|
1119
1131
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
1120
1132
|
var campaignFields = {
|
|
1121
1133
|
name: z3.string().min(1).max(LINKEDIN_LIMITS.campaign.nameMax),
|
|
@@ -1134,6 +1146,7 @@ var campaignFields = {
|
|
|
1134
1146
|
connectedTelevisionOnly: z3.boolean().default(false),
|
|
1135
1147
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1136
1148
|
associatedEntity: z3.string().regex(ORGANIZATION_URN_REGEX).optional(),
|
|
1149
|
+
politicalIntent: z3.enum(POLITICAL_INTENTS).default("NOT_DECLARED"),
|
|
1137
1150
|
status: stageableStatusSchema.default("DRAFT")
|
|
1138
1151
|
};
|
|
1139
1152
|
function validateCampaignBudgets(p, ctx, { requireBudget }) {
|
|
@@ -1191,6 +1204,7 @@ var campaignUpdateSchema = z3.object({
|
|
|
1191
1204
|
offsiteDeliveryEnabled: z3.boolean().optional(),
|
|
1192
1205
|
connectedTelevisionOnly: z3.boolean().optional(),
|
|
1193
1206
|
creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
|
|
1207
|
+
politicalIntent: z3.enum(POLITICAL_INTENTS).optional(),
|
|
1194
1208
|
status: entityStatusSchema.optional(),
|
|
1195
1209
|
// Create-only on LinkedIn — a live campaign can't change these in place.
|
|
1196
1210
|
// Accepted here only so `draft amend` can carry them into a staged CREATE
|
|
@@ -1816,6 +1830,17 @@ var linkedinDraftOpInputSchema = z3.discriminatedUnion("kind", [
|
|
|
1816
1830
|
updateOp("leadForm.update", leadFormUpdateSchema)
|
|
1817
1831
|
]);
|
|
1818
1832
|
|
|
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
|
+
|
|
1819
1844
|
// ../api/src/ads-linkedin/wire.ts
|
|
1820
1845
|
import { z as z7 } from "zod";
|
|
1821
1846
|
|
|
@@ -4534,9 +4559,6 @@ var chatChangeTypeSchema = z13.enum([
|
|
|
4534
4559
|
"image",
|
|
4535
4560
|
"video",
|
|
4536
4561
|
"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",
|
|
4540
4562
|
// A landing page saved to the reference library, keyed on the page.
|
|
4541
4563
|
"landing-reference",
|
|
4542
4564
|
// One Studio batch — the takes of one brief, as a set. See convex/lib/validators.ts.
|
|
@@ -6401,10 +6423,6 @@ var imageSourceSchema = z20.enum([
|
|
|
6401
6423
|
"google_testimonial",
|
|
6402
6424
|
"trustpilot_testimonial",
|
|
6403
6425
|
"instagram",
|
|
6404
|
-
"tiktok",
|
|
6405
|
-
"linkedin",
|
|
6406
|
-
"facebook",
|
|
6407
|
-
"google_drive",
|
|
6408
6426
|
"pexels",
|
|
6409
6427
|
"pixabay",
|
|
6410
6428
|
// Retired stock provider — kept so existing library rows stay filterable.
|
|
@@ -8215,9 +8233,7 @@ var videoSourceSchema = z30.enum([
|
|
|
8215
8233
|
"bluesky",
|
|
8216
8234
|
"dailymotion",
|
|
8217
8235
|
"facebook",
|
|
8218
|
-
"google_drive",
|
|
8219
8236
|
"instagram",
|
|
8220
|
-
"linkedin",
|
|
8221
8237
|
"loom",
|
|
8222
8238
|
"newgrounds",
|
|
8223
8239
|
"ok",
|
|
@@ -12118,9 +12134,9 @@ var COPY_LIST_FLAG = {
|
|
|
12118
12134
|
descriptions: "--descriptions",
|
|
12119
12135
|
longHeadlines: "--long-headlines"
|
|
12120
12136
|
};
|
|
12121
|
-
function valueAt(root,
|
|
12137
|
+
function valueAt(root, path48) {
|
|
12122
12138
|
let node = root;
|
|
12123
|
-
for (const key of
|
|
12139
|
+
for (const key of path48) {
|
|
12124
12140
|
if (node === null || typeof node !== "object") return void 0;
|
|
12125
12141
|
node = node[key];
|
|
12126
12142
|
}
|
|
@@ -12353,11 +12369,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
12353
12369
|
function rawTextEntries(value, rawArgs) {
|
|
12354
12370
|
return repeatedValues(rawArgs, "text", value).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
12355
12371
|
}
|
|
12356
|
-
function rawFileEntries(
|
|
12357
|
-
if (typeof
|
|
12372
|
+
function rawFileEntries(path48) {
|
|
12373
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
12358
12374
|
return [];
|
|
12359
12375
|
}
|
|
12360
|
-
return readFileSync2(
|
|
12376
|
+
return readFileSync2(path48, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12361
12377
|
}
|
|
12362
12378
|
function keywordEntries(args5, rawArgs) {
|
|
12363
12379
|
const defaultMatch = typeof args5["match-type"] === "string" ? args5["match-type"].toUpperCase() : void 0;
|
|
@@ -12380,14 +12396,14 @@ function keywordEntries(args5, rawArgs) {
|
|
|
12380
12396
|
}
|
|
12381
12397
|
return entries;
|
|
12382
12398
|
}
|
|
12383
|
-
function loadJsonFileArg(
|
|
12384
|
-
if (typeof
|
|
12399
|
+
function loadJsonFileArg(path48) {
|
|
12400
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
12385
12401
|
return {};
|
|
12386
12402
|
}
|
|
12387
|
-
const inline =
|
|
12388
|
-
const source = inline ? "inline JSON" :
|
|
12403
|
+
const inline = path48.trimStart().startsWith("{");
|
|
12404
|
+
const source = inline ? "inline JSON" : path48;
|
|
12389
12405
|
try {
|
|
12390
|
-
const parsed = JSON.parse(inline ?
|
|
12406
|
+
const parsed = JSON.parse(inline ? path48 : readFileSync2(path48, "utf8"));
|
|
12391
12407
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12392
12408
|
failWriteValidation(`${source} must contain a JSON object`);
|
|
12393
12409
|
}
|
|
@@ -12524,10 +12540,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
12524
12540
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
12525
12541
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
12526
12542
|
}
|
|
12527
|
-
async function draftAction(
|
|
12543
|
+
async function draftAction(path48, body, chat) {
|
|
12528
12544
|
try {
|
|
12529
12545
|
const chatId = resolveChatId(chat);
|
|
12530
|
-
const response = await apiPost(
|
|
12546
|
+
const response = await apiPost(path48, { chatId, ...body });
|
|
12531
12547
|
writeJsonEnvelope(response);
|
|
12532
12548
|
} catch (err) {
|
|
12533
12549
|
handleGoogleError(err);
|
|
@@ -14945,14 +14961,14 @@ function mappingRowProblem(row) {
|
|
|
14945
14961
|
|
|
14946
14962
|
// ../api/src/event-sources/template.ts
|
|
14947
14963
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
14948
|
-
function mentionOf(
|
|
14949
|
-
return `{{${
|
|
14964
|
+
function mentionOf(path48) {
|
|
14965
|
+
return `{{${path48}}}`;
|
|
14950
14966
|
}
|
|
14951
14967
|
function templateMentions(template) {
|
|
14952
14968
|
const seen = [];
|
|
14953
14969
|
for (const match of template.matchAll(MENTION)) {
|
|
14954
|
-
const
|
|
14955
|
-
if (
|
|
14970
|
+
const path48 = (match[1] ?? "").trim();
|
|
14971
|
+
if (path48 !== "" && !seen.includes(path48)) seen.push(path48);
|
|
14956
14972
|
}
|
|
14957
14973
|
return seen;
|
|
14958
14974
|
}
|
|
@@ -18307,17 +18323,17 @@ function ignoredColumnHints(columns) {
|
|
|
18307
18323
|
`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.`
|
|
18308
18324
|
];
|
|
18309
18325
|
}
|
|
18310
|
-
function readRowsFile(
|
|
18311
|
-
const inline =
|
|
18326
|
+
function readRowsFile(path48) {
|
|
18327
|
+
const inline = path48.trimStart().startsWith("[") || path48.trimStart().startsWith("{");
|
|
18312
18328
|
let text2;
|
|
18313
18329
|
try {
|
|
18314
|
-
text2 = inline ?
|
|
18330
|
+
text2 = inline ? path48 : readFileSync4(path48, "utf8");
|
|
18315
18331
|
} catch (err) {
|
|
18316
|
-
failWriteValidation(`could not read ${
|
|
18332
|
+
failWriteValidation(`could not read ${path48}: ${err instanceof Error ? err.message : String(err)}`);
|
|
18317
18333
|
}
|
|
18318
18334
|
const parsed = parseConversionRowsText(text2);
|
|
18319
18335
|
if (!parsed.ok) {
|
|
18320
|
-
failWriteValidation(`${inline ? "the conversions passed inline" :
|
|
18336
|
+
failWriteValidation(`${inline ? "the conversions passed inline" : path48}: ${parsed.error}`);
|
|
18321
18337
|
}
|
|
18322
18338
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
18323
18339
|
}
|
|
@@ -20075,10 +20091,6 @@ Full guide: __tooling__/docs/tools/baker/ads-google.md`
|
|
|
20075
20091
|
// src/commands/ads/linkedin/index.ts
|
|
20076
20092
|
import { defineCommand as defineCommand53 } from "citty";
|
|
20077
20093
|
|
|
20078
|
-
// src/commands/ads/linkedin/write-shared.ts
|
|
20079
|
-
import { createHash } from "crypto";
|
|
20080
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
20081
|
-
|
|
20082
20094
|
// src/commands/ads/linkedin/shared.ts
|
|
20083
20095
|
var DAY_MS2 = 864e5;
|
|
20084
20096
|
function handleLinkedinError(err) {
|
|
@@ -20171,18 +20183,48 @@ function daysAgoIso2(days) {
|
|
|
20171
20183
|
function csvOrJson2(args5) {
|
|
20172
20184
|
return args5.output ?? "json";
|
|
20173
20185
|
}
|
|
20174
|
-
function
|
|
20186
|
+
function statusesArgDescription(level) {
|
|
20187
|
+
return `CSV of statuses (${LINKEDIN_SEARCH_STATUSES[level].join(",")})`;
|
|
20188
|
+
}
|
|
20189
|
+
function statusFilterError(level, statuses) {
|
|
20190
|
+
const unsupported = unsupportedLinkedinSearchStatuses(level, statuses);
|
|
20191
|
+
if (unsupported.length === 0) {
|
|
20192
|
+
return null;
|
|
20193
|
+
}
|
|
20194
|
+
const accepted = LINKEDIN_SEARCH_STATUSES[level].join(",");
|
|
20195
|
+
return {
|
|
20196
|
+
ok: false,
|
|
20197
|
+
error: {
|
|
20198
|
+
code: "INVALID_STATUS",
|
|
20199
|
+
message: `LinkedIn does not accept status ${unsupported.join(", ")} for this listing.`,
|
|
20200
|
+
fix: {
|
|
20201
|
+
action: "retry_with_flag",
|
|
20202
|
+
explanation: `Re-run with --statuses from ${accepted}, or --all-statuses to drop the filter.`
|
|
20203
|
+
},
|
|
20204
|
+
retryable: false
|
|
20205
|
+
}
|
|
20206
|
+
};
|
|
20207
|
+
}
|
|
20208
|
+
function resolveStatusFilter(args5, level) {
|
|
20175
20209
|
if (args5["all-statuses"]) {
|
|
20176
20210
|
return void 0;
|
|
20177
20211
|
}
|
|
20178
20212
|
const explicit = args5.statuses;
|
|
20179
|
-
if (explicit) {
|
|
20180
|
-
return
|
|
20213
|
+
if (!explicit) {
|
|
20214
|
+
return ["ACTIVE"];
|
|
20215
|
+
}
|
|
20216
|
+
const statuses = explicit.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
20217
|
+
const error = statusFilterError(level, statuses);
|
|
20218
|
+
if (error) {
|
|
20219
|
+
writeAdsJson(error);
|
|
20220
|
+
process.exit(1);
|
|
20181
20221
|
}
|
|
20182
|
-
return
|
|
20222
|
+
return statuses;
|
|
20183
20223
|
}
|
|
20184
20224
|
|
|
20185
20225
|
// src/commands/ads/linkedin/write-shared.ts
|
|
20226
|
+
import { createHash } from "crypto";
|
|
20227
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
20186
20228
|
var TOTAL_BUDGET_HELP = "Lifetime budget \u2014 on something already running it must exceed spend to date, or LinkedIn rejects it";
|
|
20187
20229
|
function bareAccountId(args5) {
|
|
20188
20230
|
const raw = resolveAccountIdArg2(args5);
|
|
@@ -20192,19 +20234,19 @@ function failWriteValidation2(message) {
|
|
|
20192
20234
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
20193
20235
|
process.exit(1);
|
|
20194
20236
|
}
|
|
20195
|
-
function loadJsonFileArg2(
|
|
20196
|
-
if (typeof
|
|
20237
|
+
function loadJsonFileArg2(path48) {
|
|
20238
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
20197
20239
|
return {};
|
|
20198
20240
|
}
|
|
20199
20241
|
try {
|
|
20200
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20242
|
+
const parsed = JSON.parse(readFileSync5(path48, "utf8"));
|
|
20201
20243
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
20202
|
-
failWriteValidation2(`${
|
|
20244
|
+
failWriteValidation2(`${path48} must contain a JSON object`);
|
|
20203
20245
|
}
|
|
20204
20246
|
return parsed;
|
|
20205
20247
|
} catch (err) {
|
|
20206
20248
|
if (err instanceof SyntaxError) {
|
|
20207
|
-
failWriteValidation2(`${
|
|
20249
|
+
failWriteValidation2(`${path48} is not valid JSON: ${err.message}`);
|
|
20208
20250
|
}
|
|
20209
20251
|
throw err;
|
|
20210
20252
|
}
|
|
@@ -20289,15 +20331,15 @@ function parseLocaleFlag(value) {
|
|
|
20289
20331
|
}
|
|
20290
20332
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
20291
20333
|
}
|
|
20292
|
-
function loadTargetingFileArg(
|
|
20293
|
-
if (typeof
|
|
20334
|
+
function loadTargetingFileArg(path48) {
|
|
20335
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
20294
20336
|
return void 0;
|
|
20295
20337
|
}
|
|
20296
|
-
const parsed = loadJsonFileArg2(
|
|
20338
|
+
const parsed = loadJsonFileArg2(path48);
|
|
20297
20339
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
20298
20340
|
if (!criteria.include) {
|
|
20299
20341
|
failWriteValidation2(
|
|
20300
|
-
`${
|
|
20342
|
+
`${path48} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
20301
20343
|
);
|
|
20302
20344
|
}
|
|
20303
20345
|
return criteria;
|
|
@@ -20332,14 +20374,14 @@ function parseCsvLine(line) {
|
|
|
20332
20374
|
cells.push(current);
|
|
20333
20375
|
return cells.map((cell3) => cell3.trim());
|
|
20334
20376
|
}
|
|
20335
|
-
function parseListFileArg(
|
|
20336
|
-
if (typeof
|
|
20377
|
+
function parseListFileArg(path48, maxRows) {
|
|
20378
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
20337
20379
|
return void 0;
|
|
20338
20380
|
}
|
|
20339
|
-
const raw = readFileSync5(
|
|
20381
|
+
const raw = readFileSync5(path48, "utf8");
|
|
20340
20382
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
20341
20383
|
if (lines.length < 2) {
|
|
20342
|
-
failWriteValidation2(`${
|
|
20384
|
+
failWriteValidation2(`${path48} needs a header row and at least one data row`);
|
|
20343
20385
|
}
|
|
20344
20386
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
20345
20387
|
const rows = [];
|
|
@@ -20358,7 +20400,7 @@ function parseListFileArg(path49, maxRows) {
|
|
|
20358
20400
|
}
|
|
20359
20401
|
}
|
|
20360
20402
|
if (rows.length > maxRows) {
|
|
20361
|
-
failWriteValidation2(`${
|
|
20403
|
+
failWriteValidation2(`${path48} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
20362
20404
|
}
|
|
20363
20405
|
return { columns, rows };
|
|
20364
20406
|
}
|
|
@@ -20454,11 +20496,11 @@ function readPositionals(args5) {
|
|
|
20454
20496
|
function splitIdList(raw) {
|
|
20455
20497
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
20456
20498
|
}
|
|
20457
|
-
function idsFileEntries(
|
|
20458
|
-
if (typeof
|
|
20499
|
+
function idsFileEntries(path48) {
|
|
20500
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
20459
20501
|
return [];
|
|
20460
20502
|
}
|
|
20461
|
-
return readFileSync5(
|
|
20503
|
+
return readFileSync5(path48, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
20462
20504
|
}
|
|
20463
20505
|
function requireTargets(args5, entity) {
|
|
20464
20506
|
const positionals = readPositionals(args5);
|
|
@@ -20509,7 +20551,7 @@ registerSchema({
|
|
|
20509
20551
|
"account-id": { type: "string", description: "Account ID", required: false },
|
|
20510
20552
|
"account-urn": { type: "string", description: "Alias for --account-id", required: false },
|
|
20511
20553
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20512
|
-
statuses: { type: "string", description: "
|
|
20554
|
+
statuses: { type: "string", description: statusesArgDescription("campaignGroups"), required: false },
|
|
20513
20555
|
limit: { type: "string", description: "Max rows (default 500)", required: false },
|
|
20514
20556
|
"no-cache": NO_CACHE_ARG,
|
|
20515
20557
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20523,7 +20565,7 @@ registerSchema({
|
|
|
20523
20565
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20524
20566
|
"campaign-group-id": { type: "string", description: "Filter by campaign group", required: false },
|
|
20525
20567
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20526
|
-
statuses: { type: "string", description: "
|
|
20568
|
+
statuses: { type: "string", description: statusesArgDescription("campaigns"), required: false },
|
|
20527
20569
|
limit: { type: "string", description: "Max rows", required: false },
|
|
20528
20570
|
"no-cache": NO_CACHE_ARG,
|
|
20529
20571
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -20537,7 +20579,7 @@ registerSchema({
|
|
|
20537
20579
|
"account-urn": { type: "string", description: "Alias", required: false },
|
|
20538
20580
|
"campaign-id": { type: "string", description: "Filter by campaign", required: false },
|
|
20539
20581
|
"all-statuses": { type: "boolean", description: "Drop the ACTIVE filter", required: false },
|
|
20540
|
-
statuses: { type: "string", description: "
|
|
20582
|
+
statuses: { type: "string", description: statusesArgDescription("creatives"), required: false },
|
|
20541
20583
|
fields: {
|
|
20542
20584
|
type: "string",
|
|
20543
20585
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage",
|
|
@@ -20810,7 +20852,11 @@ registerSchema({
|
|
|
20810
20852
|
description: "3-letter currency code (defaults to the ad account currency)",
|
|
20811
20853
|
required: false
|
|
20812
20854
|
},
|
|
20813
|
-
status: {
|
|
20855
|
+
status: {
|
|
20856
|
+
type: "string",
|
|
20857
|
+
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED",
|
|
20858
|
+
required: false
|
|
20859
|
+
},
|
|
20814
20860
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20815
20861
|
}
|
|
20816
20862
|
});
|
|
@@ -20868,7 +20914,16 @@ registerSchema({
|
|
|
20868
20914
|
ctv: { type: "string", description: "Connected TV on|off (default off)", required: false },
|
|
20869
20915
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20870
20916
|
"associated-entity": { type: "string", description: "Organization URN", required: false },
|
|
20871
|
-
|
|
20917
|
+
"political-intent": {
|
|
20918
|
+
type: "string",
|
|
20919
|
+
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",
|
|
20920
|
+
required: false
|
|
20921
|
+
},
|
|
20922
|
+
status: {
|
|
20923
|
+
type: "string",
|
|
20924
|
+
description: "DRAFT|ACTIVE|PAUSED (default DRAFT) \u2014 PAUSED needs a group that is not DRAFT",
|
|
20925
|
+
required: false
|
|
20926
|
+
},
|
|
20872
20927
|
file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
|
|
20873
20928
|
}
|
|
20874
20929
|
});
|
|
@@ -20896,6 +20951,11 @@ registerSchema({
|
|
|
20896
20951
|
lan: { type: "string", description: "on|off", required: false },
|
|
20897
20952
|
ctv: { type: "string", description: "on|off", required: false },
|
|
20898
20953
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
|
|
20954
|
+
"political-intent": {
|
|
20955
|
+
type: "string",
|
|
20956
|
+
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",
|
|
20957
|
+
required: false
|
|
20958
|
+
},
|
|
20899
20959
|
status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED", required: false },
|
|
20900
20960
|
file: { type: "string", description: "JSON file with fields to change", required: false }
|
|
20901
20961
|
}
|
|
@@ -21291,7 +21351,8 @@ var campaignGroupsCreateCommand = defineCommand33({
|
|
|
21291
21351
|
meta: {
|
|
21292
21352
|
name: "create",
|
|
21293
21353
|
description: `Stage a new campaign group. ${STAGED_NOTE}
|
|
21294
|
-
|
|
21354
|
+
A group can't be created PAUSED, and a --total-budget needs an --end.
|
|
21355
|
+
Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-07-10 --end 2026-09-30 --total-budget 5000 --currency EUR`
|
|
21295
21356
|
},
|
|
21296
21357
|
args: {
|
|
21297
21358
|
...accountArgs,
|
|
@@ -21300,7 +21361,10 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
|
|
|
21300
21361
|
end: { type: "string", description: "Run schedule end" },
|
|
21301
21362
|
"total-budget": { type: "string", description: TOTAL_BUDGET_HELP },
|
|
21302
21363
|
currency: { type: "string", description: "3-letter currency code (defaults to the ad account currency)" },
|
|
21303
|
-
status: {
|
|
21364
|
+
status: {
|
|
21365
|
+
type: "string",
|
|
21366
|
+
description: "DRAFT|ACTIVE (default DRAFT) \u2014 LinkedIn refuses a new group created PAUSED; pause it once it exists"
|
|
21367
|
+
},
|
|
21304
21368
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21305
21369
|
},
|
|
21306
21370
|
run: async ({ args: args5 }) => {
|
|
@@ -21366,9 +21430,11 @@ function campaignPayloadFromFlags(args5) {
|
|
|
21366
21430
|
connectedTelevisionOnly: parseOnOffFlag(args5.ctv, "--ctv"),
|
|
21367
21431
|
creativeSelection: args5["creative-selection"] ? String(args5["creative-selection"]).toUpperCase() : void 0,
|
|
21368
21432
|
associatedEntity: args5["associated-entity"],
|
|
21433
|
+
politicalIntent: args5["political-intent"] ? String(args5["political-intent"]).toUpperCase() : void 0,
|
|
21369
21434
|
status: args5.status ? String(args5.status).toUpperCase() : void 0
|
|
21370
21435
|
};
|
|
21371
21436
|
}
|
|
21437
|
+
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."`;
|
|
21372
21438
|
var campaignFlagArgs = {
|
|
21373
21439
|
...accountArgs,
|
|
21374
21440
|
name: { type: "string", description: "Campaign name (\u2264255 chars)" },
|
|
@@ -21389,7 +21455,8 @@ var campaignFlagArgs = {
|
|
|
21389
21455
|
ctv: { type: "string", description: "Connected TV on|off" },
|
|
21390
21456
|
"creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN" },
|
|
21391
21457
|
"associated-entity": { type: "string", description: "Organization URN" },
|
|
21392
|
-
|
|
21458
|
+
"political-intent": { type: "string", description: POLITICAL_INTENT_HELP },
|
|
21459
|
+
status: { type: "string", description: "DRAFT|ACTIVE|PAUSED \u2014 PAUSED needs a group that is not DRAFT" },
|
|
21393
21460
|
file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
|
|
21394
21461
|
};
|
|
21395
21462
|
var campaignsCreateCommand = defineCommand33({
|
|
@@ -22906,7 +22973,7 @@ var listArgs = {
|
|
|
22906
22973
|
"account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
|
|
22907
22974
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
22908
22975
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
22909
|
-
statuses: { type: "string", description: "
|
|
22976
|
+
statuses: { type: "string", description: statusesArgDescription("campaignGroups") },
|
|
22910
22977
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
22911
22978
|
"no-cache": NO_CACHE_ARG,
|
|
22912
22979
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -22921,7 +22988,7 @@ var campaignGroupsListCommand = defineCommand40({
|
|
|
22921
22988
|
const accountId = resolveAccountIdArg2(args5);
|
|
22922
22989
|
try {
|
|
22923
22990
|
const params = { "account-id": accountId };
|
|
22924
|
-
const statuses = resolveStatusFilter(args5);
|
|
22991
|
+
const statuses = resolveStatusFilter(args5, "campaignGroups");
|
|
22925
22992
|
if (statuses) params.statuses = statuses.join(",");
|
|
22926
22993
|
if (args5.limit) params.limit = String(args5.limit);
|
|
22927
22994
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
@@ -22972,7 +23039,7 @@ var listArgs2 = {
|
|
|
22972
23039
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
22973
23040
|
"campaign-group-id": { type: "string", description: "Filter by campaign group" },
|
|
22974
23041
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
22975
|
-
statuses: { type: "string", description: "
|
|
23042
|
+
statuses: { type: "string", description: statusesArgDescription("campaigns") },
|
|
22976
23043
|
limit: { type: "string", description: "Max rows (default: 500)" },
|
|
22977
23044
|
"no-cache": NO_CACHE_ARG,
|
|
22978
23045
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -22987,7 +23054,7 @@ var campaignsListCommand = defineCommand41({
|
|
|
22987
23054
|
const accountId = resolveAccountIdArg2(args5);
|
|
22988
23055
|
try {
|
|
22989
23056
|
const params = { "account-id": accountId };
|
|
22990
|
-
const statuses = resolveStatusFilter(args5);
|
|
23057
|
+
const statuses = resolveStatusFilter(args5, "campaigns");
|
|
22991
23058
|
if (statuses) params.statuses = statuses.join(",");
|
|
22992
23059
|
if (args5["campaign-group-id"]) params["campaign-group-id"] = String(args5["campaign-group-id"]);
|
|
22993
23060
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -23220,9 +23287,9 @@ import { defineCommand as defineCommand44 } from "citty";
|
|
|
23220
23287
|
function asRecord(value) {
|
|
23221
23288
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
23222
23289
|
}
|
|
23223
|
-
function readPath2(row,
|
|
23290
|
+
function readPath2(row, path48) {
|
|
23224
23291
|
let current = row;
|
|
23225
|
-
for (const segment of
|
|
23292
|
+
for (const segment of path48.split(".")) {
|
|
23226
23293
|
const record = asRecord(current);
|
|
23227
23294
|
if (!record) return void 0;
|
|
23228
23295
|
current = record[segment];
|
|
@@ -23232,10 +23299,10 @@ function readPath2(row, path49) {
|
|
|
23232
23299
|
function projectFields(rows, paths) {
|
|
23233
23300
|
return rows.map((row) => {
|
|
23234
23301
|
const projected = {};
|
|
23235
|
-
for (const
|
|
23236
|
-
const value = readPath2(row,
|
|
23302
|
+
for (const path48 of paths) {
|
|
23303
|
+
const value = readPath2(row, path48);
|
|
23237
23304
|
if (value !== void 0) {
|
|
23238
|
-
projected[
|
|
23305
|
+
projected[path48] = value;
|
|
23239
23306
|
}
|
|
23240
23307
|
}
|
|
23241
23308
|
return projected;
|
|
@@ -23248,16 +23315,16 @@ function shapeListRows(rows, args5, compact4) {
|
|
|
23248
23315
|
const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
|
|
23249
23316
|
if (paths.length > 0) {
|
|
23250
23317
|
const projected = projectFields(raw, paths).map((row, i) => {
|
|
23251
|
-
const missing = paths.filter((
|
|
23318
|
+
const missing = paths.filter((path48) => row[path48] === void 0);
|
|
23252
23319
|
const source = rows[i];
|
|
23253
23320
|
if (missing.length === 0 || source === void 0) return row;
|
|
23254
23321
|
const compactRow3 = compact4.row(source);
|
|
23255
|
-
for (const
|
|
23256
|
-
if (compactRow3[
|
|
23322
|
+
for (const path48 of missing) {
|
|
23323
|
+
if (compactRow3[path48] !== void 0) row[path48] = compactRow3[path48];
|
|
23257
23324
|
}
|
|
23258
23325
|
return row;
|
|
23259
23326
|
});
|
|
23260
|
-
const unmatched = paths.filter((
|
|
23327
|
+
const unmatched = paths.filter((path48) => projected.every((row) => row[path48] === void 0));
|
|
23261
23328
|
if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
|
|
23262
23329
|
const carried = /* @__PURE__ */ new Set([...compact4.columns, ...raw.flatMap((row) => Object.keys(row))]);
|
|
23263
23330
|
return {
|
|
@@ -23337,7 +23404,7 @@ var listArgs3 = {
|
|
|
23337
23404
|
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
23338
23405
|
"campaign-id": { type: "string", description: "Filter by campaign ID" },
|
|
23339
23406
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
23340
|
-
statuses: { type: "string", description: "
|
|
23407
|
+
statuses: { type: "string", description: statusesArgDescription("creatives") },
|
|
23341
23408
|
fields: {
|
|
23342
23409
|
type: "string",
|
|
23343
23410
|
description: "CSV of dotted paths to return instead of the compact row, e.g. id,content.textAd.landingPage"
|
|
@@ -23357,7 +23424,7 @@ var creativesListCommand = defineCommand44({
|
|
|
23357
23424
|
const accountId = resolveAccountIdArg2(args5);
|
|
23358
23425
|
try {
|
|
23359
23426
|
const params = { "account-id": accountId };
|
|
23360
|
-
const statuses = resolveStatusFilter(args5);
|
|
23427
|
+
const statuses = resolveStatusFilter(args5, "creatives");
|
|
23361
23428
|
if (statuses) params.statuses = statuses.join(",");
|
|
23362
23429
|
if (args5["campaign-id"]) params["campaign-id"] = String(args5["campaign-id"]);
|
|
23363
23430
|
if (args5.limit) params.limit = String(args5.limit);
|
|
@@ -24627,54 +24694,54 @@ function buildCustomConversionRule(input) {
|
|
|
24627
24694
|
function customConversionRuleRefusal(rule) {
|
|
24628
24695
|
return ruleNodeRefusal(rule, "rule");
|
|
24629
24696
|
}
|
|
24630
|
-
function branchRefusal(key, value,
|
|
24697
|
+
function branchRefusal(key, value, path48) {
|
|
24631
24698
|
if (!Array.isArray(value) || value.length === 0) {
|
|
24632
|
-
return `${
|
|
24699
|
+
return `${path48}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
24633
24700
|
}
|
|
24634
24701
|
for (const [index, child] of value.entries()) {
|
|
24635
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
24702
|
+
const refusal = ruleNodeRefusal(child, `${path48}.${key}[${index}]`);
|
|
24636
24703
|
if (refusal) {
|
|
24637
24704
|
return refusal;
|
|
24638
24705
|
}
|
|
24639
24706
|
}
|
|
24640
24707
|
return void 0;
|
|
24641
24708
|
}
|
|
24642
|
-
function conditionRefusal(key, value,
|
|
24643
|
-
return key === "and" || key === "or" ? branchRefusal(key, value,
|
|
24709
|
+
function conditionRefusal(key, value, path48) {
|
|
24710
|
+
return key === "and" || key === "or" ? branchRefusal(key, value, path48) : leafRefusal(key, value, path48);
|
|
24644
24711
|
}
|
|
24645
|
-
function ruleNodeRefusal(node,
|
|
24712
|
+
function ruleNodeRefusal(node, path48) {
|
|
24646
24713
|
if (!isRecord2(node)) {
|
|
24647
|
-
return `${
|
|
24714
|
+
return `${path48} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
24648
24715
|
}
|
|
24649
24716
|
const entries = Object.entries(node);
|
|
24650
24717
|
if (entries.length === 0) {
|
|
24651
|
-
return `${
|
|
24718
|
+
return `${path48} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
24652
24719
|
}
|
|
24653
24720
|
if (entries.length > 1) {
|
|
24654
|
-
return `${
|
|
24721
|
+
return `${path48} 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]}`;
|
|
24655
24722
|
}
|
|
24656
24723
|
for (const [key, value] of entries) {
|
|
24657
|
-
const refusal = conditionRefusal(key, value,
|
|
24724
|
+
const refusal = conditionRefusal(key, value, path48);
|
|
24658
24725
|
if (refusal) {
|
|
24659
24726
|
return refusal;
|
|
24660
24727
|
}
|
|
24661
24728
|
}
|
|
24662
24729
|
return void 0;
|
|
24663
24730
|
}
|
|
24664
|
-
function leafRefusal(field, condition,
|
|
24731
|
+
function leafRefusal(field, condition, path48) {
|
|
24665
24732
|
if (!isRecord2(condition)) {
|
|
24666
|
-
return `${
|
|
24733
|
+
return `${path48}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
24667
24734
|
}
|
|
24668
24735
|
const tests = Object.entries(condition);
|
|
24669
24736
|
if (tests.length === 0) {
|
|
24670
|
-
return `${
|
|
24737
|
+
return `${path48}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
24671
24738
|
}
|
|
24672
24739
|
if (tests.length > 1) {
|
|
24673
|
-
return `${
|
|
24740
|
+
return `${path48}.${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]}`;
|
|
24674
24741
|
}
|
|
24675
24742
|
for (const [operator] of tests) {
|
|
24676
24743
|
if (!RULE_OPERATORS[operator]) {
|
|
24677
|
-
return `${
|
|
24744
|
+
return `${path48}.${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)`;
|
|
24678
24745
|
}
|
|
24679
24746
|
}
|
|
24680
24747
|
return void 0;
|
|
@@ -25390,11 +25457,11 @@ var updateStatusSchema = z37.enum(UPDATE_STATUSES);
|
|
|
25390
25457
|
function currencyMinimums2(currencyCode) {
|
|
25391
25458
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
25392
25459
|
}
|
|
25393
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
25460
|
+
function validateDailyBudgetFloor(money, ctx, path48) {
|
|
25394
25461
|
if (money?.currencyCode) {
|
|
25395
25462
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
25396
25463
|
if (Number(money.amount) < min) {
|
|
25397
|
-
ctx.addIssue({ code: "custom", path:
|
|
25464
|
+
ctx.addIssue({ code: "custom", path: path48, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
25398
25465
|
}
|
|
25399
25466
|
}
|
|
25400
25467
|
}
|
|
@@ -26266,19 +26333,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
26266
26333
|
);
|
|
26267
26334
|
}
|
|
26268
26335
|
}
|
|
26269
|
-
function loadJsonFileArg3(
|
|
26270
|
-
if (typeof
|
|
26336
|
+
function loadJsonFileArg3(path48) {
|
|
26337
|
+
if (typeof path48 !== "string" || path48.length === 0) {
|
|
26271
26338
|
return {};
|
|
26272
26339
|
}
|
|
26273
26340
|
try {
|
|
26274
|
-
const parsed = JSON.parse(readFileSync9(
|
|
26341
|
+
const parsed = JSON.parse(readFileSync9(path48, "utf8"));
|
|
26275
26342
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
26276
|
-
failWriteValidation3(`${
|
|
26343
|
+
failWriteValidation3(`${path48} must contain a JSON object`);
|
|
26277
26344
|
}
|
|
26278
26345
|
return parsed;
|
|
26279
26346
|
} catch (err) {
|
|
26280
26347
|
if (err instanceof SyntaxError) {
|
|
26281
|
-
failWriteValidation3(`${
|
|
26348
|
+
failWriteValidation3(`${path48} is not valid JSON: ${err.message}`);
|
|
26282
26349
|
}
|
|
26283
26350
|
throw err;
|
|
26284
26351
|
}
|
|
@@ -31974,12 +32041,12 @@ function flowExists(slug) {
|
|
|
31974
32041
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
31975
32042
|
}
|
|
31976
32043
|
function readFlowTree(slug) {
|
|
31977
|
-
const
|
|
31978
|
-
if (!existsSync3(
|
|
32044
|
+
const path48 = join2(flowsDir(), slug, "_data.json");
|
|
32045
|
+
if (!existsSync3(path48)) {
|
|
31979
32046
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
31980
32047
|
}
|
|
31981
32048
|
try {
|
|
31982
|
-
return JSON.parse(readFileSync11(
|
|
32049
|
+
return JSON.parse(readFileSync11(path48, "utf-8"));
|
|
31983
32050
|
} catch (error) {
|
|
31984
32051
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
31985
32052
|
}
|
|
@@ -32939,12 +33006,12 @@ function readPeopleFile(args5) {
|
|
|
32939
33006
|
}
|
|
32940
33007
|
function unreadablePeopleFile(args5) {
|
|
32941
33008
|
if (!args5["people-file"]) return void 0;
|
|
32942
|
-
const
|
|
33009
|
+
const path48 = String(args5["people-file"]);
|
|
32943
33010
|
try {
|
|
32944
|
-
readFileSync12(
|
|
33011
|
+
readFileSync12(path48, "utf8");
|
|
32945
33012
|
return void 0;
|
|
32946
33013
|
} catch {
|
|
32947
|
-
return `Couldn't read --people-file ${
|
|
33014
|
+
return `Couldn't read --people-file ${path48}. Check the path, or pass the people inline with --person.`;
|
|
32948
33015
|
}
|
|
32949
33016
|
}
|
|
32950
33017
|
function peopleLimitError(args5) {
|
|
@@ -33916,11 +33983,11 @@ function parseFieldArgs(argv) {
|
|
|
33916
33983
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
33917
33984
|
const eq = pair.indexOf("=");
|
|
33918
33985
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
33919
|
-
const
|
|
33986
|
+
const path48 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
33920
33987
|
const problem = mappingRowProblem(field);
|
|
33921
33988
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
33922
|
-
if (
|
|
33923
|
-
mapping[field] =
|
|
33989
|
+
if (path48 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
33990
|
+
mapping[field] = path48;
|
|
33924
33991
|
}
|
|
33925
33992
|
return mapping;
|
|
33926
33993
|
}
|
|
@@ -35522,11 +35589,11 @@ function unwrap(response) {
|
|
|
35522
35589
|
}
|
|
35523
35590
|
return response.data;
|
|
35524
35591
|
}
|
|
35525
|
-
async function readAvatars(
|
|
35526
|
-
return unwrap(await apiGet(
|
|
35592
|
+
async function readAvatars(path48, params) {
|
|
35593
|
+
return unwrap(await apiGet(path48, params));
|
|
35527
35594
|
}
|
|
35528
|
-
async function writeAvatars(
|
|
35529
|
-
return unwrap(await apiPost(
|
|
35595
|
+
async function writeAvatars(path48, body) {
|
|
35596
|
+
return unwrap(await apiPost(path48, body));
|
|
35530
35597
|
}
|
|
35531
35598
|
|
|
35532
35599
|
// src/commands/avatars/create.ts
|
|
@@ -36435,12 +36502,12 @@ function missingFontFiles(urls, available) {
|
|
|
36435
36502
|
function planFontAdoption(sources, families) {
|
|
36436
36503
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
36437
36504
|
const byFamily = /* @__PURE__ */ new Map();
|
|
36438
|
-
for (const { path:
|
|
36439
|
-
const dir = posix.dirname(
|
|
36505
|
+
for (const { path: path48, source } of sources) {
|
|
36506
|
+
const dir = posix.dirname(path48);
|
|
36440
36507
|
for (const face of declaredFontFaces(source)) {
|
|
36441
36508
|
if (!wanted.has(face.family)) continue;
|
|
36442
36509
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
36443
|
-
perFile.set(
|
|
36510
|
+
perFile.set(path48, [...perFile.get(path48) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
36444
36511
|
byFamily.set(face.family, perFile);
|
|
36445
36512
|
}
|
|
36446
36513
|
}
|
|
@@ -49266,10 +49333,10 @@ function parseValueExpression(raw) {
|
|
|
49266
49333
|
return parts.map(parsePart);
|
|
49267
49334
|
}
|
|
49268
49335
|
function trackingFieldIds() {
|
|
49269
|
-
const
|
|
49270
|
-
if (!existsSync6(
|
|
49336
|
+
const path48 = join4(flowsDir(), "..", "tracking.ts");
|
|
49337
|
+
if (!existsSync6(path48)) return null;
|
|
49271
49338
|
try {
|
|
49272
|
-
const source = readFileSync15(
|
|
49339
|
+
const source = readFileSync15(path48, "utf-8");
|
|
49273
49340
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
49274
49341
|
if (!block2) return null;
|
|
49275
49342
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -49843,13 +49910,13 @@ function specsFromFile(parsed) {
|
|
|
49843
49910
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
49844
49911
|
});
|
|
49845
49912
|
}
|
|
49846
|
-
function readSpecFile(
|
|
49913
|
+
function readSpecFile(path48) {
|
|
49847
49914
|
let raw;
|
|
49848
49915
|
try {
|
|
49849
|
-
raw =
|
|
49916
|
+
raw = path48 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path48, "utf-8");
|
|
49850
49917
|
} catch (error) {
|
|
49851
49918
|
refuse(
|
|
49852
|
-
`Could not read ${
|
|
49919
|
+
`Could not read ${path48 === "-" ? "the mapping from stdin" : `"${path48}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
49853
49920
|
);
|
|
49854
49921
|
}
|
|
49855
49922
|
let parsed;
|
|
@@ -49857,7 +49924,7 @@ function readSpecFile(path49) {
|
|
|
49857
49924
|
parsed = JSON.parse(raw);
|
|
49858
49925
|
} catch (error) {
|
|
49859
49926
|
refuse(
|
|
49860
|
-
`${
|
|
49927
|
+
`${path48 === "-" ? "stdin" : `"${path48}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
49861
49928
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
49862
49929
|
);
|
|
49863
49930
|
}
|
|
@@ -50156,21 +50223,21 @@ var ARRAY_FIELDS = [
|
|
|
50156
50223
|
"tagIds"
|
|
50157
50224
|
];
|
|
50158
50225
|
var ARRAY_OWNERS = ["", "body"];
|
|
50159
|
-
function dropUnsetOptionals(sideEffect,
|
|
50226
|
+
function dropUnsetOptionals(sideEffect, path48) {
|
|
50160
50227
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
50161
50228
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
50162
50229
|
delete sideEffect[key];
|
|
50163
|
-
return [{ path:
|
|
50230
|
+
return [{ path: path48, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
50164
50231
|
});
|
|
50165
50232
|
}
|
|
50166
|
-
function fillNulledArrays(target2, prefix,
|
|
50233
|
+
function fillNulledArrays(target2, prefix, path48) {
|
|
50167
50234
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
50168
50235
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
50169
50236
|
target2[key] = [];
|
|
50170
|
-
return [{ path:
|
|
50237
|
+
return [{ path: path48, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
50171
50238
|
});
|
|
50172
50239
|
}
|
|
50173
|
-
function tidyEmailRecipients(sideEffect,
|
|
50240
|
+
function tidyEmailRecipients(sideEffect, path48) {
|
|
50174
50241
|
if (sideEffect.type !== "email") return [];
|
|
50175
50242
|
const config = sideEffect.encryptedConfig;
|
|
50176
50243
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -50181,7 +50248,7 @@ function tidyEmailRecipients(sideEffect, path49) {
|
|
|
50181
50248
|
const tidied = to.join(", ");
|
|
50182
50249
|
if (tidied === raw) return [];
|
|
50183
50250
|
config.email = tidied;
|
|
50184
|
-
return [{ path:
|
|
50251
|
+
return [{ path: path48, change: "tidied the recipient list's spacing and separators" }];
|
|
50185
50252
|
}
|
|
50186
50253
|
function sideEffectsOf(node) {
|
|
50187
50254
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -50190,13 +50257,13 @@ function sideEffectsOf(node) {
|
|
|
50190
50257
|
);
|
|
50191
50258
|
}
|
|
50192
50259
|
function normalizeSideEffect(sideEffect, where) {
|
|
50193
|
-
const
|
|
50260
|
+
const path48 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
50194
50261
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
50195
50262
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
50196
50263
|
if (!target2 || typeof target2 !== "object") return [];
|
|
50197
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
50264
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path48);
|
|
50198
50265
|
});
|
|
50199
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
50266
|
+
return [...dropUnsetOptionals(sideEffect, path48), ...arrays, ...tidyEmailRecipients(sideEffect, path48)];
|
|
50200
50267
|
}
|
|
50201
50268
|
function normalizeFlowTree(tree) {
|
|
50202
50269
|
const changes = [];
|
|
@@ -51586,10 +51653,10 @@ async function stageOps(ops) {
|
|
|
51586
51653
|
handleError5(err);
|
|
51587
51654
|
}
|
|
51588
51655
|
}
|
|
51589
|
-
async function draftAction2(
|
|
51656
|
+
async function draftAction2(path48, body, chat) {
|
|
51590
51657
|
const chatId = resolveChatId(chat);
|
|
51591
51658
|
try {
|
|
51592
|
-
const data = await apiPost(
|
|
51659
|
+
const data = await apiPost(path48, { chatId, ...body });
|
|
51593
51660
|
writeJsonEnvelope({ ok: true, data });
|
|
51594
51661
|
return data;
|
|
51595
51662
|
} catch (err) {
|
|
@@ -54118,9 +54185,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
54118
54185
|
}
|
|
54119
54186
|
return readFile28(pathOrUrl);
|
|
54120
54187
|
}
|
|
54121
|
-
async function isDirectory(
|
|
54188
|
+
async function isDirectory(path48) {
|
|
54122
54189
|
try {
|
|
54123
|
-
const s = await stat7(
|
|
54190
|
+
const s = await stat7(path48);
|
|
54124
54191
|
return s.isDirectory();
|
|
54125
54192
|
} catch {
|
|
54126
54193
|
return false;
|
|
@@ -54548,13 +54615,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
54548
54615
|
}
|
|
54549
54616
|
function disambiguate(paths) {
|
|
54550
54617
|
const taken = /* @__PURE__ */ new Set();
|
|
54551
|
-
return paths.map((
|
|
54552
|
-
if (!taken.has(
|
|
54553
|
-
taken.add(
|
|
54554
|
-
return
|
|
54618
|
+
return paths.map((path48) => {
|
|
54619
|
+
if (!taken.has(path48)) {
|
|
54620
|
+
taken.add(path48);
|
|
54621
|
+
return path48;
|
|
54555
54622
|
}
|
|
54556
|
-
const ext = extname3(
|
|
54557
|
-
const stem =
|
|
54623
|
+
const ext = extname3(path48);
|
|
54624
|
+
const stem = path48.slice(0, path48.length - ext.length);
|
|
54558
54625
|
let n = 2;
|
|
54559
54626
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
54560
54627
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -54680,10 +54747,10 @@ async function runDownloads(plan) {
|
|
|
54680
54747
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
54681
54748
|
const downloaded = [];
|
|
54682
54749
|
for (const [index, item] of fetched.entries()) {
|
|
54683
|
-
const
|
|
54750
|
+
const path48 = paths[index] ?? item.path;
|
|
54684
54751
|
try {
|
|
54685
|
-
await atomicWrite(
|
|
54686
|
-
downloaded.push({ input: item.input, output:
|
|
54752
|
+
await atomicWrite(path48, item.buffer);
|
|
54753
|
+
downloaded.push({ input: item.input, output: path48, bytes: item.buffer.length, contentType: item.contentType });
|
|
54687
54754
|
} catch (err) {
|
|
54688
54755
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
54689
54756
|
}
|
|
@@ -62870,374 +62937,11 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
|
62870
62937
|
}
|
|
62871
62938
|
});
|
|
62872
62939
|
|
|
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
|
-
/** Google Drive: the account that shared the folder with Baker. Absent for a link-shared folder. */
|
|
62923
|
-
sharedBy: z51.string().optional()
|
|
62924
|
-
});
|
|
62925
|
-
var mediaSourcesAddRequestSchema = z51.object({
|
|
62926
|
-
/** A profile URL or a Drive folder link, or an @handle together with `platform`. */
|
|
62927
|
-
input: z51.string().trim().min(1, "Pass the account's profile URL or @handle"),
|
|
62928
|
-
/** Needed only when `input` is a bare handle; a URL names its own platform. */
|
|
62929
|
-
platform: mediaSourcePlatformSchema.optional(),
|
|
62930
|
-
/** Auto-sync cadence. Omitted = weekly, except a Drive folder, which checks daily. */
|
|
62931
|
-
every: mediaSourceRefreshIntervalSchema.optional()
|
|
62932
|
-
});
|
|
62933
|
-
var mediaSourceKeySchema = z51.string().trim().regex(/^(instagram|tiktok|youtube|linkedin|facebook|google_drive):.+$/, "Pass a source key like tiktok:nike");
|
|
62934
|
-
var mediaSourcesSyncRequestSchema = z51.object({ key: mediaSourceKeySchema });
|
|
62935
|
-
var mediaSourcesRemoveRequestSchema = z51.object({ key: mediaSourceKeySchema });
|
|
62936
|
-
var mediaSourcesScheduleRequestSchema = z51.object({
|
|
62937
|
-
key: mediaSourceKeySchema,
|
|
62938
|
-
every: mediaSourceRefreshIntervalSchema
|
|
62939
|
-
});
|
|
62940
|
-
|
|
62941
|
-
// src/commands/media-sources/add.ts
|
|
62942
|
-
import { defineCommand as defineCommand184 } from "citty";
|
|
62943
|
-
|
|
62944
|
-
// src/commands/media-sources/shared.ts
|
|
62945
|
-
function driveRefusalFix(input, code) {
|
|
62946
|
-
const isDrive = /drive\.google\.com/i.test(input);
|
|
62947
|
-
if (!isDrive || code !== "NOT_FOUND" && code !== "FORBIDDEN") return void 0;
|
|
62948
|
-
return "Only the user can give Baker a folder, so tell them how, then carry on with the rest of the task. The quickest way: in Baker, open Images (or Videos) \u2192 Add source \u2192 Google Drive \u2192 Choose a folder, which connects their Google Drive and shares the folder in one step \u2014 once they do, it is connected and there is nothing to run. For a folder someone else owns, relay the message as written; once they say it's shared, run the same command again.";
|
|
62949
|
-
}
|
|
62950
|
-
function reportError2(err, input) {
|
|
62951
|
-
if (err instanceof ApiError) {
|
|
62952
|
-
const fix = input ? driveRefusalFix(input, err.code) : void 0;
|
|
62953
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message, ...fix ? { fix } : {} } });
|
|
62954
|
-
process.exit(1);
|
|
62955
|
-
}
|
|
62956
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
62957
|
-
process.exit(1);
|
|
62958
|
-
}
|
|
62959
|
-
function halfState(half) {
|
|
62960
|
-
if (!half) return null;
|
|
62961
|
-
return {
|
|
62962
|
-
status: half.syncStatus === "fetching" || half.syncStatus === "processing" ? "importing" : half.syncStatus,
|
|
62963
|
-
stored: half.storedCount ?? 0,
|
|
62964
|
-
...half.pendingItems ? { pending: half.pendingItems } : {},
|
|
62965
|
-
...half.failedItems ? { failed: half.failedItems } : {},
|
|
62966
|
-
...half.lastSyncedAt ? { lastSyncedAt: new Date(half.lastSyncedAt).toISOString() } : {},
|
|
62967
|
-
...half.errorMessage ? { error: half.errorMessage } : {}
|
|
62968
|
-
};
|
|
62969
|
-
}
|
|
62970
|
-
function compactSource(source) {
|
|
62971
|
-
return {
|
|
62972
|
-
key: source.key,
|
|
62973
|
-
platform: source.platform,
|
|
62974
|
-
label: source.label,
|
|
62975
|
-
url: source.profileUrl,
|
|
62976
|
-
autoSync: source.refreshInterval,
|
|
62977
|
-
images: halfState(source.images),
|
|
62978
|
-
videos: halfState(source.videos)
|
|
62979
|
-
};
|
|
62980
|
-
}
|
|
62981
|
-
function isImporting(source) {
|
|
62982
|
-
return [source.images, source.videos].some(
|
|
62983
|
-
(half) => half?.syncStatus === "fetching" || half?.syncStatus === "processing"
|
|
62984
|
-
);
|
|
62985
|
-
}
|
|
62986
|
-
|
|
62987
|
-
// src/commands/media-sources/add.ts
|
|
62988
|
-
registerSchema({
|
|
62989
|
-
command: "media-sources.add",
|
|
62990
|
-
description: "Connect a public social account or a shared Google Drive folder as a source for the image and video libraries \u2014 Instagram, TikTok, YouTube (videos only), LinkedIn company pages, Facebook pages, Google Drive folders. A social account's recent posts (up to a year back) are imported; a Drive folder's images and videos, subfolders included, are imported and new files keep arriving automatically. 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.",
|
|
62991
|
-
args: {
|
|
62992
|
-
input: {
|
|
62993
|
-
type: "string",
|
|
62994
|
-
description: "Profile URL or Drive folder link (names its own platform), or @handle together with --platform",
|
|
62995
|
-
required: true
|
|
62996
|
-
},
|
|
62997
|
-
platform: {
|
|
62998
|
-
type: "string",
|
|
62999
|
-
description: `Needed only for a bare handle: ${mediaSourcePlatformSchema.options.join("|")}`,
|
|
63000
|
-
required: false
|
|
63001
|
-
},
|
|
63002
|
-
every: {
|
|
63003
|
-
type: "string",
|
|
63004
|
-
description: `Auto-sync cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (default weekly; a Drive folder defaults to daily and also syncs on every change)`,
|
|
63005
|
-
required: false
|
|
63006
|
-
}
|
|
63007
|
-
}
|
|
63008
|
-
});
|
|
63009
|
-
var addCommand3 = defineCommand184({
|
|
63010
|
-
meta: {
|
|
63011
|
-
name: "add",
|
|
63012
|
-
description: "Connect a social account (Instagram, TikTok, YouTube, LinkedIn page, Facebook page) or a Google Drive folder as a media source. Start here with the profile URL or the folder link. A Drive folder must first be shared with Baker by someone on the team \u2014 if it isn't, the error says with which address.\n\nExamples:\n baker media-sources add https://www.tiktok.com/@acme\n baker media-sources add @acme --platform instagram --every daily\n baker media-sources add https://drive.google.com/drive/folders/1AbC\u2026"
|
|
63013
|
-
},
|
|
63014
|
-
args: {
|
|
63015
|
-
input: { type: "positional", description: "Profile URL, Drive folder link, or @handle", required: true },
|
|
63016
|
-
platform: {
|
|
63017
|
-
type: "string",
|
|
63018
|
-
description: "instagram|tiktok|youtube|linkedin|facebook|google_drive \u2014 only for a bare handle or folder id",
|
|
63019
|
-
required: false
|
|
63020
|
-
},
|
|
63021
|
-
every: { type: "string", description: "Auto-sync: never|daily|weekly|monthly", required: false }
|
|
63022
|
-
},
|
|
63023
|
-
run: async ({ args: args5 }) => {
|
|
63024
|
-
const parsed = mediaSourcesAddRequestSchema.safeParse({
|
|
63025
|
-
input: String(args5.input ?? ""),
|
|
63026
|
-
platform: args5.platform ? String(args5.platform).toLowerCase() : void 0,
|
|
63027
|
-
every: args5.every ? String(args5.every).toLowerCase() : void 0
|
|
63028
|
-
});
|
|
63029
|
-
if (!parsed.success) {
|
|
63030
|
-
const issue = parsed.error.issues[0];
|
|
63031
|
-
writeJson({
|
|
63032
|
-
ok: false,
|
|
63033
|
-
error: {
|
|
63034
|
-
code: "VALIDATION_ERROR",
|
|
63035
|
-
message: issue ? `${issue.path.join(".") || "input"}: ${issue.message}` : "Invalid request"
|
|
63036
|
-
}
|
|
63037
|
-
});
|
|
63038
|
-
process.exit(1);
|
|
63039
|
-
}
|
|
63040
|
-
try {
|
|
63041
|
-
const data = await apiPost("/api/media-sources/add", parsed.data, {
|
|
63042
|
-
timeoutMs: 12e4
|
|
63043
|
-
});
|
|
63044
|
-
const hints2 = [
|
|
63045
|
-
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.`
|
|
63046
|
-
];
|
|
63047
|
-
if (data.source.platform === "youtube") {
|
|
63048
|
-
hints2.push(
|
|
63049
|
-
"YouTube feeds the video library only, newest first, a batch per sync; videos over 20 minutes are skipped."
|
|
63050
|
-
);
|
|
63051
|
-
}
|
|
63052
|
-
if (data.source.platform === "google_drive") {
|
|
63053
|
-
hints2.push(
|
|
63054
|
-
"New files added to the folder (or its subfolders) are imported on their own within minutes; large originals are resized for the library, and the files in Drive stay untouched. A big folder imports in batches over the next hours."
|
|
63055
|
-
);
|
|
63056
|
-
}
|
|
63057
|
-
if (data.source.refreshInterval === "never") {
|
|
63058
|
-
hints2.push(
|
|
63059
|
-
`Auto-sync is off. If the user wants new posts to keep arriving: \`baker media-sources schedule ${data.source.key} --every weekly\`.`
|
|
63060
|
-
);
|
|
63061
|
-
}
|
|
63062
|
-
writeJson({
|
|
63063
|
-
ok: true,
|
|
63064
|
-
data: { created: data.created, source: compactSource(data.source), name: data.profile.displayName },
|
|
63065
|
-
hints: hints2
|
|
63066
|
-
});
|
|
63067
|
-
} catch (err) {
|
|
63068
|
-
reportError2(err, parsed.data.input);
|
|
63069
|
-
}
|
|
63070
|
-
}
|
|
63071
|
-
});
|
|
63072
|
-
|
|
63073
|
-
// src/commands/media-sources/list.ts
|
|
63074
|
-
import { defineCommand as defineCommand185 } from "citty";
|
|
63075
|
-
registerSchema({
|
|
63076
|
-
command: "media-sources.list",
|
|
63077
|
-
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.",
|
|
63078
|
-
args: {}
|
|
63079
|
-
});
|
|
63080
|
-
var listCommand17 = defineCommand185({
|
|
63081
|
-
meta: {
|
|
63082
|
-
name: "list",
|
|
63083
|
-
description: "List connected media sources (key, platform, import status, stored images/videos).\n\nExample: baker media-sources list"
|
|
63084
|
-
},
|
|
63085
|
-
args: {},
|
|
63086
|
-
run: async () => {
|
|
63087
|
-
try {
|
|
63088
|
-
const { sources } = await apiGet("/api/media-sources/list");
|
|
63089
|
-
const hints2 = [];
|
|
63090
|
-
if (sources.length === 0) {
|
|
63091
|
-
hints2.push(
|
|
63092
|
-
"No sources connected. Connect the brand's own accounts with `baker media-sources add <profile URL>` to fill the image and video libraries."
|
|
63093
|
-
);
|
|
63094
|
-
} else if (sources.some(isImporting)) {
|
|
63095
|
-
hints2.push("Some sources are still importing \u2014 their counts will grow over the next minutes.");
|
|
63096
|
-
}
|
|
63097
|
-
writeJson({ ok: true, data: sources.map(compactSource), hints: hints2.length > 0 ? hints2 : void 0 });
|
|
63098
|
-
} catch (err) {
|
|
63099
|
-
reportError2(err);
|
|
63100
|
-
}
|
|
63101
|
-
}
|
|
63102
|
-
});
|
|
63103
|
-
|
|
63104
|
-
// src/commands/media-sources/remove.ts
|
|
63105
|
-
import { defineCommand as defineCommand186 } from "citty";
|
|
63106
|
-
registerSchema({
|
|
63107
|
-
command: "media-sources.remove",
|
|
63108
|
-
description: "Disconnect a media source. Stops future imports; images and videos it already brought in stay in the library. Applies immediately.",
|
|
63109
|
-
args: { key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true } }
|
|
63110
|
-
});
|
|
63111
|
-
var removeCommand6 = defineCommand186({
|
|
63112
|
-
meta: {
|
|
63113
|
-
name: "remove",
|
|
63114
|
-
description: "Disconnect a media source (already-imported media stays).\n\nExample: baker media-sources remove tiktok:acme"
|
|
63115
|
-
},
|
|
63116
|
-
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
63117
|
-
run: async ({ args: args5 }) => {
|
|
63118
|
-
const parsed = mediaSourcesRemoveRequestSchema.safeParse({ key: String(args5.key ?? "") });
|
|
63119
|
-
if (!parsed.success) {
|
|
63120
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
63121
|
-
process.exit(1);
|
|
63122
|
-
}
|
|
63123
|
-
try {
|
|
63124
|
-
const data = await apiPost("/api/media-sources/remove", parsed.data);
|
|
63125
|
-
writeJson({ ok: true, data });
|
|
63126
|
-
} catch (err) {
|
|
63127
|
-
reportError2(err);
|
|
63128
|
-
}
|
|
63129
|
-
}
|
|
63130
|
-
});
|
|
63131
|
-
|
|
63132
|
-
// src/commands/media-sources/schedule.ts
|
|
63133
|
-
import { defineCommand as defineCommand187 } from "citty";
|
|
63134
|
-
registerSchema({
|
|
63135
|
-
command: "media-sources.schedule",
|
|
63136
|
-
description: "Set how often a connected source imports new posts on its own.",
|
|
63137
|
-
args: {
|
|
63138
|
-
key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true },
|
|
63139
|
-
every: {
|
|
63140
|
-
type: "string",
|
|
63141
|
-
description: `Cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (never = only on demand)`,
|
|
63142
|
-
required: true
|
|
63143
|
-
}
|
|
63144
|
-
}
|
|
63145
|
-
});
|
|
63146
|
-
var scheduleCommand = defineCommand187({
|
|
63147
|
-
meta: {
|
|
63148
|
-
name: "schedule",
|
|
63149
|
-
description: "Set a source's auto-sync cadence.\n\nExample: baker media-sources schedule tiktok:acme --every weekly"
|
|
63150
|
-
},
|
|
63151
|
-
args: {
|
|
63152
|
-
key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true },
|
|
63153
|
-
every: { type: "string", description: "never|daily|weekly|monthly", required: true }
|
|
63154
|
-
},
|
|
63155
|
-
run: async ({ args: args5 }) => {
|
|
63156
|
-
const parsed = mediaSourcesScheduleRequestSchema.safeParse({
|
|
63157
|
-
key: String(args5.key ?? ""),
|
|
63158
|
-
every: String(args5.every ?? "").toLowerCase()
|
|
63159
|
-
});
|
|
63160
|
-
if (!parsed.success) {
|
|
63161
|
-
const issue = parsed.error.issues[0];
|
|
63162
|
-
writeJson({
|
|
63163
|
-
ok: false,
|
|
63164
|
-
error: { code: "VALIDATION_ERROR", message: issue ? `${issue.path.join(".")}: ${issue.message}` : "" }
|
|
63165
|
-
});
|
|
63166
|
-
process.exit(1);
|
|
63167
|
-
}
|
|
63168
|
-
try {
|
|
63169
|
-
const data = await apiPost("/api/media-sources/schedule", parsed.data);
|
|
63170
|
-
writeJson({ ok: true, data: { ...data, autoSync: parsed.data.every } });
|
|
63171
|
-
} catch (err) {
|
|
63172
|
-
reportError2(err);
|
|
63173
|
-
}
|
|
63174
|
-
}
|
|
63175
|
-
});
|
|
63176
|
-
|
|
63177
|
-
// src/commands/media-sources/sync.ts
|
|
63178
|
-
import { defineCommand as defineCommand188 } from "citty";
|
|
63179
|
-
registerSchema({
|
|
63180
|
-
command: "media-sources.sync",
|
|
63181
|
-
description: "Import a connected source's new posts now. Runs in the background; only posts not yet in the library are fetched.",
|
|
63182
|
-
args: {
|
|
63183
|
-
key: { type: "string", description: "Source key from `media-sources list`, e.g. tiktok:acme", required: true }
|
|
63184
|
-
}
|
|
63185
|
-
});
|
|
63186
|
-
var syncCommand = defineCommand188({
|
|
63187
|
-
meta: {
|
|
63188
|
-
name: "sync",
|
|
63189
|
-
description: "Import a source's new posts now.\n\nExample: baker media-sources sync tiktok:acme"
|
|
63190
|
-
},
|
|
63191
|
-
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
63192
|
-
run: async ({ args: args5 }) => {
|
|
63193
|
-
const parsed = mediaSourcesSyncRequestSchema.safeParse({ key: String(args5.key ?? "") });
|
|
63194
|
-
if (!parsed.success) {
|
|
63195
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
63196
|
-
process.exit(1);
|
|
63197
|
-
}
|
|
63198
|
-
try {
|
|
63199
|
-
const data = await apiPost("/api/media-sources/sync", parsed.data);
|
|
63200
|
-
writeJson({
|
|
63201
|
-
ok: true,
|
|
63202
|
-
data,
|
|
63203
|
-
hints: data.started ? void 0 : ["An import was already running for this source; nothing new was started."]
|
|
63204
|
-
});
|
|
63205
|
-
} catch (err) {
|
|
63206
|
-
reportError2(err);
|
|
63207
|
-
}
|
|
63208
|
-
}
|
|
63209
|
-
});
|
|
63210
|
-
|
|
63211
|
-
// src/commands/media-sources/index.ts
|
|
63212
|
-
var mediaSourcesCommand = defineCommand189({
|
|
63213
|
-
meta: {
|
|
63214
|
-
name: "media-sources",
|
|
63215
|
-
description: `Connect social accounts and shared Google Drive folders whose images and videos fill the libraries: Instagram, TikTok, YouTube (videos), LinkedIn company pages, Facebook pages, Google Drive folders. Subcommands: add, list, sync, schedule, remove.
|
|
63216
|
-
|
|
63217
|
-
Examples:
|
|
63218
|
-
baker media-sources add https://www.tiktok.com/@acme
|
|
63219
|
-
baker media-sources add @acme --platform instagram --every daily
|
|
63220
|
-
baker media-sources add https://drive.google.com/drive/folders/1AbC\u2026
|
|
63221
|
-
baker media-sources list
|
|
63222
|
-
baker media-sources sync youtube:acme
|
|
63223
|
-
baker media-sources schedule linkedin:acme --every monthly
|
|
63224
|
-
baker media-sources remove facebook:acme
|
|
63225
|
-
Full guide: __tooling__/docs/tools/baker/media-sources.md`
|
|
63226
|
-
},
|
|
63227
|
-
subCommands: {
|
|
63228
|
-
add: addCommand3,
|
|
63229
|
-
list: listCommand17,
|
|
63230
|
-
sync: syncCommand,
|
|
63231
|
-
schedule: scheduleCommand,
|
|
63232
|
-
remove: removeCommand6
|
|
63233
|
-
}
|
|
63234
|
-
});
|
|
63235
|
-
|
|
63236
62940
|
// src/commands/research/index.ts
|
|
63237
|
-
import { defineCommand as
|
|
62941
|
+
import { defineCommand as defineCommand196 } from "citty";
|
|
63238
62942
|
|
|
63239
62943
|
// src/commands/research/advertisers.ts
|
|
63240
|
-
import { defineCommand as
|
|
62944
|
+
import { defineCommand as defineCommand184 } from "citty";
|
|
63241
62945
|
|
|
63242
62946
|
// src/commands/research/hints.ts
|
|
63243
62947
|
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.';
|
|
@@ -63439,7 +63143,7 @@ var FIELDS3 = {
|
|
|
63439
63143
|
etv: "Estimated traffic value (USD)",
|
|
63440
63144
|
visibility: "SERP visibility score (0-1)"
|
|
63441
63145
|
};
|
|
63442
|
-
var advertisersCommand =
|
|
63146
|
+
var advertisersCommand = defineCommand184({
|
|
63443
63147
|
meta: {
|
|
63444
63148
|
name: "advertisers",
|
|
63445
63149
|
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).
|
|
@@ -63495,7 +63199,7 @@ Examples:
|
|
|
63495
63199
|
});
|
|
63496
63200
|
|
|
63497
63201
|
// src/commands/research/autocomplete.ts
|
|
63498
|
-
import { defineCommand as
|
|
63202
|
+
import { defineCommand as defineCommand185 } from "citty";
|
|
63499
63203
|
registerSchema({
|
|
63500
63204
|
command: "research.autocomplete",
|
|
63501
63205
|
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).",
|
|
@@ -63518,7 +63222,7 @@ registerSchema({
|
|
|
63518
63222
|
var FIELDS4 = {
|
|
63519
63223
|
suggestion: "Autocomplete suggestion from Google"
|
|
63520
63224
|
};
|
|
63521
|
-
var autocompleteCommand =
|
|
63225
|
+
var autocompleteCommand = defineCommand185({
|
|
63522
63226
|
meta: {
|
|
63523
63227
|
name: "autocomplete",
|
|
63524
63228
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -63573,7 +63277,7 @@ Examples:
|
|
|
63573
63277
|
});
|
|
63574
63278
|
|
|
63575
63279
|
// src/commands/research/countries.ts
|
|
63576
|
-
import { defineCommand as
|
|
63280
|
+
import { defineCommand as defineCommand186 } from "citty";
|
|
63577
63281
|
registerSchema({
|
|
63578
63282
|
command: "research.countries",
|
|
63579
63283
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -63630,7 +63334,7 @@ var FIELDS5 = {
|
|
|
63630
63334
|
code: "Country code to pass as --location",
|
|
63631
63335
|
name: "Country name"
|
|
63632
63336
|
};
|
|
63633
|
-
var countriesCommand =
|
|
63337
|
+
var countriesCommand = defineCommand186({
|
|
63634
63338
|
meta: {
|
|
63635
63339
|
name: "countries",
|
|
63636
63340
|
description: "List all supported country codes for --location flag."
|
|
@@ -63641,7 +63345,7 @@ var countriesCommand = defineCommand192({
|
|
|
63641
63345
|
});
|
|
63642
63346
|
|
|
63643
63347
|
// src/commands/research/fetch.ts
|
|
63644
|
-
import { defineCommand as
|
|
63348
|
+
import { defineCommand as defineCommand187 } from "citty";
|
|
63645
63349
|
var CONTENT_PREVIEW_CHARS = 2e4;
|
|
63646
63350
|
var TIMEOUT_MS = 18e4;
|
|
63647
63351
|
registerSchema({
|
|
@@ -63714,7 +63418,7 @@ function fetchFix(code) {
|
|
|
63714
63418
|
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."
|
|
63715
63419
|
};
|
|
63716
63420
|
}
|
|
63717
|
-
var fetchCommand =
|
|
63421
|
+
var fetchCommand = defineCommand187({
|
|
63718
63422
|
meta: {
|
|
63719
63423
|
name: "fetch",
|
|
63720
63424
|
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.
|
|
@@ -63791,7 +63495,7 @@ Examples:
|
|
|
63791
63495
|
});
|
|
63792
63496
|
|
|
63793
63497
|
// src/commands/research/intent.ts
|
|
63794
|
-
import { defineCommand as
|
|
63498
|
+
import { defineCommand as defineCommand188 } from "citty";
|
|
63795
63499
|
registerSchema({
|
|
63796
63500
|
command: "research.intent",
|
|
63797
63501
|
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.",
|
|
@@ -63814,7 +63518,7 @@ var FIELDS7 = {
|
|
|
63814
63518
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
63815
63519
|
probability: "Confidence score 0.0-1.0"
|
|
63816
63520
|
};
|
|
63817
|
-
var intentCommand =
|
|
63521
|
+
var intentCommand = defineCommand188({
|
|
63818
63522
|
meta: {
|
|
63819
63523
|
name: "intent",
|
|
63820
63524
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -63862,7 +63566,7 @@ Examples:
|
|
|
63862
63566
|
});
|
|
63863
63567
|
|
|
63864
63568
|
// src/commands/research/keyword-gap.ts
|
|
63865
|
-
import { defineCommand as
|
|
63569
|
+
import { defineCommand as defineCommand189 } from "citty";
|
|
63866
63570
|
registerSchema({
|
|
63867
63571
|
command: "research.keyword-gap",
|
|
63868
63572
|
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.",
|
|
@@ -63891,7 +63595,7 @@ var FIELDS8 = {
|
|
|
63891
63595
|
cpc: "Cost per click USD",
|
|
63892
63596
|
their_position: "Competitor's ranking position"
|
|
63893
63597
|
};
|
|
63894
|
-
var keywordGapCommand =
|
|
63598
|
+
var keywordGapCommand = defineCommand189({
|
|
63895
63599
|
meta: {
|
|
63896
63600
|
name: "keyword-gap",
|
|
63897
63601
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -63966,7 +63670,7 @@ Examples:
|
|
|
63966
63670
|
});
|
|
63967
63671
|
|
|
63968
63672
|
// src/commands/research/keyword-metrics.ts
|
|
63969
|
-
import { defineCommand as
|
|
63673
|
+
import { defineCommand as defineCommand190 } from "citty";
|
|
63970
63674
|
|
|
63971
63675
|
// src/commands/research/keyword-metrics-rows.ts
|
|
63972
63676
|
var KEYWORD_METRICS_SOURCE = "keyword_planner_estimate_via_dataforseo";
|
|
@@ -64046,7 +63750,7 @@ registerSchema({
|
|
|
64046
63750
|
"no-cache": { type: "boolean", description: "Skip server cache, hit API directly", required: false }
|
|
64047
63751
|
}
|
|
64048
63752
|
});
|
|
64049
|
-
var keywordMetricsCommand =
|
|
63753
|
+
var keywordMetricsCommand = defineCommand190({
|
|
64050
63754
|
meta: {
|
|
64051
63755
|
name: "keyword-metrics",
|
|
64052
63756
|
description: `Volume, CPC and competition for keywords you name. No domain required.
|
|
@@ -64128,7 +63832,7 @@ Examples:
|
|
|
64128
63832
|
});
|
|
64129
63833
|
|
|
64130
63834
|
// src/commands/research/keywords-for-site.ts
|
|
64131
|
-
import { defineCommand as
|
|
63835
|
+
import { defineCommand as defineCommand191 } from "citty";
|
|
64132
63836
|
registerSchema({
|
|
64133
63837
|
command: "research.keywords-for-site",
|
|
64134
63838
|
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.",
|
|
@@ -64161,7 +63865,7 @@ var FIELDS9 = {
|
|
|
64161
63865
|
competition: "LOW, MEDIUM, or HIGH",
|
|
64162
63866
|
competition_index: "Competition score 0-100"
|
|
64163
63867
|
};
|
|
64164
|
-
var keywordsForSiteCommand =
|
|
63868
|
+
var keywordsForSiteCommand = defineCommand191({
|
|
64165
63869
|
meta: {
|
|
64166
63870
|
name: "keywords-for-site",
|
|
64167
63871
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -64223,7 +63927,7 @@ Examples:
|
|
|
64223
63927
|
});
|
|
64224
63928
|
|
|
64225
63929
|
// src/commands/research/languages.ts
|
|
64226
|
-
import { defineCommand as
|
|
63930
|
+
import { defineCommand as defineCommand192 } from "citty";
|
|
64227
63931
|
registerSchema({
|
|
64228
63932
|
command: "research.languages",
|
|
64229
63933
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -64253,7 +63957,7 @@ var FIELDS10 = {
|
|
|
64253
63957
|
code: "Language code to pass as --language",
|
|
64254
63958
|
name: "Language name (also accepted by --language)"
|
|
64255
63959
|
};
|
|
64256
|
-
var languagesCommand2 =
|
|
63960
|
+
var languagesCommand2 = defineCommand192({
|
|
64257
63961
|
meta: {
|
|
64258
63962
|
name: "languages",
|
|
64259
63963
|
description: "List all supported language codes for --language flag."
|
|
@@ -64264,7 +63968,7 @@ var languagesCommand2 = defineCommand198({
|
|
|
64264
63968
|
});
|
|
64265
63969
|
|
|
64266
63970
|
// src/commands/research/lighthouse.ts
|
|
64267
|
-
import { defineCommand as
|
|
63971
|
+
import { defineCommand as defineCommand193 } from "citty";
|
|
64268
63972
|
registerSchema({
|
|
64269
63973
|
command: "research.lighthouse",
|
|
64270
63974
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -64283,7 +63987,7 @@ var FIELDS11 = {
|
|
|
64283
63987
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
64284
63988
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
64285
63989
|
};
|
|
64286
|
-
var lighthouseCommand =
|
|
63990
|
+
var lighthouseCommand = defineCommand193({
|
|
64287
63991
|
meta: {
|
|
64288
63992
|
name: "lighthouse",
|
|
64289
63993
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -64321,7 +64025,7 @@ Examples:
|
|
|
64321
64025
|
});
|
|
64322
64026
|
|
|
64323
64027
|
// src/commands/research/relevant-pages.ts
|
|
64324
|
-
import { defineCommand as
|
|
64028
|
+
import { defineCommand as defineCommand194 } from "citty";
|
|
64325
64029
|
registerSchema({
|
|
64326
64030
|
command: "research.relevant-pages",
|
|
64327
64031
|
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).",
|
|
@@ -64347,7 +64051,7 @@ var FIELDS12 = {
|
|
|
64347
64051
|
keywords: "Total organic keywords the page ranks for",
|
|
64348
64052
|
top_10: "Keywords in positions 1-10"
|
|
64349
64053
|
};
|
|
64350
|
-
var relevantPagesCommand =
|
|
64054
|
+
var relevantPagesCommand = defineCommand194({
|
|
64351
64055
|
meta: {
|
|
64352
64056
|
name: "relevant-pages",
|
|
64353
64057
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -64394,7 +64098,7 @@ Examples:
|
|
|
64394
64098
|
});
|
|
64395
64099
|
|
|
64396
64100
|
// src/commands/research/web.ts
|
|
64397
|
-
import { defineCommand as
|
|
64101
|
+
import { defineCommand as defineCommand195 } from "citty";
|
|
64398
64102
|
registerSchema({
|
|
64399
64103
|
command: "research.web",
|
|
64400
64104
|
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).",
|
|
@@ -64445,7 +64149,7 @@ async function runDeepResearch(question) {
|
|
|
64445
64149
|
}
|
|
64446
64150
|
throw new Error("Deep research timed out");
|
|
64447
64151
|
}
|
|
64448
|
-
var webCommand =
|
|
64152
|
+
var webCommand = defineCommand195({
|
|
64449
64153
|
meta: {
|
|
64450
64154
|
name: "web",
|
|
64451
64155
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -64507,7 +64211,7 @@ Examples:
|
|
|
64507
64211
|
});
|
|
64508
64212
|
|
|
64509
64213
|
// src/commands/research/index.ts
|
|
64510
|
-
var researchCommand =
|
|
64214
|
+
var researchCommand = defineCommand196({
|
|
64511
64215
|
meta: {
|
|
64512
64216
|
name: "research",
|
|
64513
64217
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -64554,10 +64258,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
|
|
|
64554
64258
|
});
|
|
64555
64259
|
|
|
64556
64260
|
// src/commands/scheduled-agents/index.ts
|
|
64557
|
-
import { defineCommand as
|
|
64261
|
+
import { defineCommand as defineCommand207 } from "citty";
|
|
64558
64262
|
|
|
64559
64263
|
// src/commands/scheduled-agents/create.ts
|
|
64560
|
-
import { defineCommand as
|
|
64264
|
+
import { defineCommand as defineCommand197 } from "citty";
|
|
64561
64265
|
|
|
64562
64266
|
// src/commands/scheduled-agents/shared.ts
|
|
64563
64267
|
var TEMP_SCHEDULED_AGENT_PREFIX = "temp_agent_";
|
|
@@ -64924,7 +64628,7 @@ registerSchema({
|
|
|
64924
64628
|
}
|
|
64925
64629
|
}
|
|
64926
64630
|
});
|
|
64927
|
-
var createCommand3 =
|
|
64631
|
+
var createCommand3 = defineCommand197({
|
|
64928
64632
|
meta: {
|
|
64929
64633
|
name: "create",
|
|
64930
64634
|
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'
|
|
@@ -64981,7 +64685,7 @@ var createCommand3 = defineCommand203({
|
|
|
64981
64685
|
});
|
|
64982
64686
|
|
|
64983
64687
|
// src/commands/scheduled-agents/delete.ts
|
|
64984
|
-
import { defineCommand as
|
|
64688
|
+
import { defineCommand as defineCommand198 } from "citty";
|
|
64985
64689
|
registerSchema({
|
|
64986
64690
|
command: "scheduled-agents.delete",
|
|
64987
64691
|
description: "Stage deletion of a published scheduled agent, or cancel one this chat staged (temp_agent_*).",
|
|
@@ -64989,7 +64693,7 @@ registerSchema({
|
|
|
64989
64693
|
id: { type: "string", description: "Published scheduled agent ID or temp_agent_* draft ID", required: true }
|
|
64990
64694
|
}
|
|
64991
64695
|
});
|
|
64992
|
-
var deleteCommand3 =
|
|
64696
|
+
var deleteCommand3 = defineCommand198({
|
|
64993
64697
|
meta: {
|
|
64994
64698
|
name: "delete",
|
|
64995
64699
|
description: "Stage a scheduled agent deletion. Example: baker scheduled-agents delete <id-or-temp_agent_id>"
|
|
@@ -65018,7 +64722,7 @@ var deleteCommand3 = defineCommand204({
|
|
|
65018
64722
|
});
|
|
65019
64723
|
|
|
65020
64724
|
// src/commands/scheduled-agents/get.ts
|
|
65021
|
-
import { defineCommand as
|
|
64725
|
+
import { defineCommand as defineCommand199 } from "citty";
|
|
65022
64726
|
registerSchema({
|
|
65023
64727
|
command: "scheduled-agents.get",
|
|
65024
64728
|
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.",
|
|
@@ -65027,7 +64731,7 @@ registerSchema({
|
|
|
65027
64731
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
65028
64732
|
}
|
|
65029
64733
|
});
|
|
65030
|
-
var getCommand4 =
|
|
64734
|
+
var getCommand4 = defineCommand199({
|
|
65031
64735
|
meta: {
|
|
65032
64736
|
name: "get",
|
|
65033
64737
|
description: "Get a scheduled agent. Example: baker scheduled-agents get <id-or-temp_agent_id>"
|
|
@@ -65066,7 +64770,7 @@ var getCommand4 = defineCommand205({
|
|
|
65066
64770
|
});
|
|
65067
64771
|
|
|
65068
64772
|
// src/commands/scheduled-agents/list.ts
|
|
65069
|
-
import { defineCommand as
|
|
64773
|
+
import { defineCommand as defineCommand200 } from "citty";
|
|
65070
64774
|
var FULL_DESCRIPTION = "Return every item and staged change as stored, briefs included (tens of KB). Prefer `get <id>` for one item.";
|
|
65071
64775
|
registerSchema({
|
|
65072
64776
|
command: "scheduled-agents.list",
|
|
@@ -65076,7 +64780,7 @@ registerSchema({
|
|
|
65076
64780
|
full: { type: "boolean", description: FULL_DESCRIPTION, required: false }
|
|
65077
64781
|
}
|
|
65078
64782
|
});
|
|
65079
|
-
var
|
|
64783
|
+
var listCommand17 = defineCommand200({
|
|
65080
64784
|
meta: {
|
|
65081
64785
|
name: "list",
|
|
65082
64786
|
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."
|
|
@@ -65102,7 +64806,7 @@ var listCommand18 = defineCommand206({
|
|
|
65102
64806
|
});
|
|
65103
64807
|
|
|
65104
64808
|
// src/commands/scheduled-agents/run.ts
|
|
65105
|
-
import { defineCommand as
|
|
64809
|
+
import { defineCommand as defineCommand201 } from "citty";
|
|
65106
64810
|
registerSchema({
|
|
65107
64811
|
command: "scheduled-agents.run",
|
|
65108
64812
|
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.",
|
|
@@ -65110,7 +64814,7 @@ registerSchema({
|
|
|
65110
64814
|
id: { type: "string", description: "Published scheduled agent ID", required: true }
|
|
65111
64815
|
}
|
|
65112
64816
|
});
|
|
65113
|
-
var runCommand2 =
|
|
64817
|
+
var runCommand2 = defineCommand201({
|
|
65114
64818
|
meta: {
|
|
65115
64819
|
name: "run",
|
|
65116
64820
|
description: "Run a published scheduled agent now. Example: baker scheduled-agents run <id>"
|
|
@@ -65142,7 +64846,7 @@ var runCommand2 = defineCommand207({
|
|
|
65142
64846
|
});
|
|
65143
64847
|
|
|
65144
64848
|
// src/commands/scheduled-agents/targets.ts
|
|
65145
|
-
import { defineCommand as
|
|
64849
|
+
import { defineCommand as defineCommand202 } from "citty";
|
|
65146
64850
|
var ARGS2 = {
|
|
65147
64851
|
trigger: {
|
|
65148
64852
|
type: "string",
|
|
@@ -65176,7 +64880,7 @@ registerSchema({
|
|
|
65176
64880
|
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.",
|
|
65177
64881
|
args: ARGS2
|
|
65178
64882
|
});
|
|
65179
|
-
var targetsCommand =
|
|
64883
|
+
var targetsCommand = defineCommand202({
|
|
65180
64884
|
meta: {
|
|
65181
64885
|
name: "targets",
|
|
65182
64886
|
description: `What a trigger can be pointed at \u2014 so "when a Task is picked up" becomes "when THIS Task is picked up".
|
|
@@ -65219,7 +64923,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65219
64923
|
// src/commands/scheduled-agents/templates.ts
|
|
65220
64924
|
import { readFile as readFile32 } from "fs/promises";
|
|
65221
64925
|
import path46 from "path";
|
|
65222
|
-
import { defineCommand as
|
|
64926
|
+
import { defineCommand as defineCommand203 } from "citty";
|
|
65223
64927
|
registerSchema({
|
|
65224
64928
|
command: "scheduled-agents.templates",
|
|
65225
64929
|
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.",
|
|
@@ -65274,7 +64978,7 @@ registerSchema({
|
|
|
65274
64978
|
}
|
|
65275
64979
|
}
|
|
65276
64980
|
});
|
|
65277
|
-
var templatesCommand =
|
|
64981
|
+
var templatesCommand = defineCommand203({
|
|
65278
64982
|
meta: {
|
|
65279
64983
|
name: "templates",
|
|
65280
64984
|
description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
|
|
@@ -65370,7 +65074,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65370
65074
|
});
|
|
65371
65075
|
|
|
65372
65076
|
// src/commands/scheduled-agents/triggers.ts
|
|
65373
|
-
import { defineCommand as
|
|
65077
|
+
import { defineCommand as defineCommand204 } from "citty";
|
|
65374
65078
|
var ARGS3 = {
|
|
65375
65079
|
trigger: {
|
|
65376
65080
|
type: "string",
|
|
@@ -65456,7 +65160,7 @@ function shapeTriggerCatalog(response, filter) {
|
|
|
65456
65160
|
}
|
|
65457
65161
|
return { ok: true, data: { groups, reacting: catalog.reacting } };
|
|
65458
65162
|
}
|
|
65459
|
-
var triggersCommand2 =
|
|
65163
|
+
var triggersCommand2 = defineCommand204({
|
|
65460
65164
|
meta: {
|
|
65461
65165
|
name: "triggers",
|
|
65462
65166
|
description: `Everything that can start a scheduled agent.
|
|
@@ -65486,7 +65190,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65486
65190
|
});
|
|
65487
65191
|
|
|
65488
65192
|
// src/commands/scheduled-agents/unstage.ts
|
|
65489
|
-
import { defineCommand as
|
|
65193
|
+
import { defineCommand as defineCommand205 } from "citty";
|
|
65490
65194
|
registerSchema({
|
|
65491
65195
|
command: "scheduled-agents.unstage",
|
|
65492
65196
|
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.",
|
|
@@ -65512,7 +65216,7 @@ function unstageBody(args5, chatId) {
|
|
|
65512
65216
|
}
|
|
65513
65217
|
return { chatId, ref: args5.ref, index };
|
|
65514
65218
|
}
|
|
65515
|
-
var unstageCommand =
|
|
65219
|
+
var unstageCommand = defineCommand205({
|
|
65516
65220
|
meta: {
|
|
65517
65221
|
name: "unstage",
|
|
65518
65222
|
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"
|
|
@@ -65543,7 +65247,7 @@ var unstageCommand = defineCommand211({
|
|
|
65543
65247
|
});
|
|
65544
65248
|
|
|
65545
65249
|
// src/commands/scheduled-agents/update.ts
|
|
65546
|
-
import { defineCommand as
|
|
65250
|
+
import { defineCommand as defineCommand206 } from "citty";
|
|
65547
65251
|
registerSchema({
|
|
65548
65252
|
command: "scheduled-agents.update",
|
|
65549
65253
|
description: "Stage an update to a published scheduled agent, or to one this chat staged (temp_agent_*).",
|
|
@@ -65570,7 +65274,7 @@ registerSchema({
|
|
|
65570
65274
|
enabled: { type: "string", description: "Replacement enabled state", required: false, enum: ["true", "false"] }
|
|
65571
65275
|
}
|
|
65572
65276
|
});
|
|
65573
|
-
var updateCommand4 =
|
|
65277
|
+
var updateCommand4 = defineCommand206({
|
|
65574
65278
|
meta: {
|
|
65575
65279
|
name: "update",
|
|
65576
65280
|
description: "Stage a scheduled agent update. Examples: baker scheduled-agents update <id> --enabled false | baker scheduled-agents update <id> --trigger form.submitted --form quote"
|
|
@@ -65641,7 +65345,7 @@ var updateCommand4 = defineCommand212({
|
|
|
65641
65345
|
});
|
|
65642
65346
|
|
|
65643
65347
|
// src/commands/scheduled-agents/index.ts
|
|
65644
|
-
var scheduledAgentsCommand =
|
|
65348
|
+
var scheduledAgentsCommand = defineCommand207({
|
|
65645
65349
|
meta: {
|
|
65646
65350
|
name: "scheduled-agents",
|
|
65647
65351
|
description: `Manage Scheduled agents. Subcommands: list, get, triggers, targets, create, update, delete, unstage, run, templates.
|
|
@@ -65670,7 +65374,7 @@ Examples:
|
|
|
65670
65374
|
Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
65671
65375
|
},
|
|
65672
65376
|
subCommands: {
|
|
65673
|
-
list:
|
|
65377
|
+
list: listCommand17,
|
|
65674
65378
|
get: getCommand4,
|
|
65675
65379
|
triggers: triggersCommand2,
|
|
65676
65380
|
targets: targetsCommand,
|
|
@@ -65684,14 +65388,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
65684
65388
|
});
|
|
65685
65389
|
|
|
65686
65390
|
// src/commands/schema.ts
|
|
65687
|
-
import { defineCommand as
|
|
65391
|
+
import { defineCommand as defineCommand208 } from "citty";
|
|
65688
65392
|
function narrowToFamily(commandName, available) {
|
|
65689
65393
|
const segments = commandName.split(".");
|
|
65690
65394
|
const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
|
|
65691
65395
|
const siblings = available.filter((name) => name.startsWith(prefix));
|
|
65692
65396
|
return siblings.length > 0 ? siblings : available;
|
|
65693
65397
|
}
|
|
65694
|
-
var schemaCommand2 =
|
|
65398
|
+
var schemaCommand2 = defineCommand208({
|
|
65695
65399
|
meta: {
|
|
65696
65400
|
name: "schema",
|
|
65697
65401
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images search (or images.search)"
|
|
@@ -65736,10 +65440,10 @@ var schemaCommand2 = defineCommand214({
|
|
|
65736
65440
|
});
|
|
65737
65441
|
|
|
65738
65442
|
// src/commands/studio/index.ts
|
|
65739
|
-
import { defineCommand as
|
|
65443
|
+
import { defineCommand as defineCommand217 } from "citty";
|
|
65740
65444
|
|
|
65741
65445
|
// src/commands/studio/animate.ts
|
|
65742
|
-
import { defineCommand as
|
|
65446
|
+
import { defineCommand as defineCommand209 } from "citty";
|
|
65743
65447
|
|
|
65744
65448
|
// src/commands/studio/spokenPace.ts
|
|
65745
65449
|
var WORDS_PER_SECOND3 = SPOKEN_WORDS_PER_SECOND;
|
|
@@ -65965,7 +65669,7 @@ function parseImageRefs(spec) {
|
|
|
65965
65669
|
}
|
|
65966
65670
|
var defaultDeps = {
|
|
65967
65671
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
65968
|
-
upload: (
|
|
65672
|
+
upload: (path48) => uploadLocalImage({ file: path48, contentType: detectImageContentType(path48), source: "uploaded" })
|
|
65969
65673
|
};
|
|
65970
65674
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
65971
65675
|
const refs = parseImageRefs(spec);
|
|
@@ -65985,10 +65689,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
65985
65689
|
}
|
|
65986
65690
|
return { imageIds, added };
|
|
65987
65691
|
}
|
|
65988
|
-
function uploadFailure(
|
|
65692
|
+
function uploadFailure(path48) {
|
|
65989
65693
|
return (error) => {
|
|
65990
65694
|
if (error instanceof ApiError) throw error;
|
|
65991
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
65695
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path48}" as an image.`);
|
|
65992
65696
|
};
|
|
65993
65697
|
}
|
|
65994
65698
|
|
|
@@ -66252,7 +65956,7 @@ async function adByHandHintFor(body) {
|
|
|
66252
65956
|
return null;
|
|
66253
65957
|
}
|
|
66254
65958
|
}
|
|
66255
|
-
var animateCommand =
|
|
65959
|
+
var animateCommand = defineCommand209({
|
|
66256
65960
|
meta: {
|
|
66257
65961
|
name: "animate",
|
|
66258
65962
|
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"
|
|
@@ -66377,7 +66081,7 @@ var animateCommand = defineCommand215({
|
|
|
66377
66081
|
});
|
|
66378
66082
|
|
|
66379
66083
|
// src/commands/studio/generate.ts
|
|
66380
|
-
import { defineCommand as
|
|
66084
|
+
import { defineCommand as defineCommand210 } from "citty";
|
|
66381
66085
|
var MODEL_LIST2 = IMAGE_MODEL_IDS;
|
|
66382
66086
|
var DEFAULT_MAX_WAIT_MS2 = 24e4;
|
|
66383
66087
|
registerSchema({
|
|
@@ -66513,7 +66217,7 @@ function buildGenerateBody(args5, prompt) {
|
|
|
66513
66217
|
}
|
|
66514
66218
|
return body;
|
|
66515
66219
|
}
|
|
66516
|
-
var generateCommand =
|
|
66220
|
+
var generateCommand = defineCommand210({
|
|
66517
66221
|
meta: {
|
|
66518
66222
|
name: "generate",
|
|
66519
66223
|
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]]'"
|
|
@@ -66596,7 +66300,7 @@ var generateCommand = defineCommand216({
|
|
|
66596
66300
|
});
|
|
66597
66301
|
|
|
66598
66302
|
// src/commands/studio/get.ts
|
|
66599
|
-
import { defineCommand as
|
|
66303
|
+
import { defineCommand as defineCommand211 } from "citty";
|
|
66600
66304
|
registerSchema({
|
|
66601
66305
|
command: "studio.get",
|
|
66602
66306
|
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.",
|
|
@@ -66605,7 +66309,7 @@ registerSchema({
|
|
|
66605
66309
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66606
66310
|
}
|
|
66607
66311
|
});
|
|
66608
|
-
var getCommand5 =
|
|
66312
|
+
var getCommand5 = defineCommand211({
|
|
66609
66313
|
meta: {
|
|
66610
66314
|
name: "get",
|
|
66611
66315
|
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"
|
|
@@ -66634,7 +66338,7 @@ var getCommand5 = defineCommand217({
|
|
|
66634
66338
|
});
|
|
66635
66339
|
|
|
66636
66340
|
// src/commands/studio/improve.ts
|
|
66637
|
-
import { defineCommand as
|
|
66341
|
+
import { defineCommand as defineCommand212 } from "citty";
|
|
66638
66342
|
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.";
|
|
66639
66343
|
registerSchema({
|
|
66640
66344
|
command: "studio.improve",
|
|
@@ -66659,7 +66363,7 @@ registerSchema({
|
|
|
66659
66363
|
}
|
|
66660
66364
|
}
|
|
66661
66365
|
});
|
|
66662
|
-
var improveCommand =
|
|
66366
|
+
var improveCommand = defineCommand212({
|
|
66663
66367
|
meta: {
|
|
66664
66368
|
name: "improve",
|
|
66665
66369
|
description: `${DESCRIPTION2}
|
|
@@ -66703,7 +66407,7 @@ Examples:
|
|
|
66703
66407
|
});
|
|
66704
66408
|
|
|
66705
66409
|
// src/commands/studio/keep.ts
|
|
66706
|
-
import { defineCommand as
|
|
66410
|
+
import { defineCommand as defineCommand213 } from "citty";
|
|
66707
66411
|
registerSchema({
|
|
66708
66412
|
command: "studio.keep",
|
|
66709
66413
|
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.",
|
|
@@ -66713,7 +66417,7 @@ registerSchema({
|
|
|
66713
66417
|
undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
|
|
66714
66418
|
}
|
|
66715
66419
|
});
|
|
66716
|
-
var keepCommand =
|
|
66420
|
+
var keepCommand = defineCommand213({
|
|
66717
66421
|
meta: {
|
|
66718
66422
|
name: "keep",
|
|
66719
66423
|
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"
|
|
@@ -66764,7 +66468,7 @@ var keepCommand = defineCommand219({
|
|
|
66764
66468
|
});
|
|
66765
66469
|
|
|
66766
66470
|
// src/commands/studio/list.ts
|
|
66767
|
-
import { defineCommand as
|
|
66471
|
+
import { defineCommand as defineCommand214 } from "citty";
|
|
66768
66472
|
registerSchema({
|
|
66769
66473
|
command: "studio.list",
|
|
66770
66474
|
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.",
|
|
@@ -66775,7 +66479,7 @@ registerSchema({
|
|
|
66775
66479
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
66776
66480
|
}
|
|
66777
66481
|
});
|
|
66778
|
-
var
|
|
66482
|
+
var listCommand18 = defineCommand214({
|
|
66779
66483
|
meta: {
|
|
66780
66484
|
name: "list",
|
|
66781
66485
|
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"
|
|
@@ -66809,7 +66513,7 @@ var listCommand19 = defineCommand220({
|
|
|
66809
66513
|
});
|
|
66810
66514
|
|
|
66811
66515
|
// src/commands/studio/models.ts
|
|
66812
|
-
import { defineCommand as
|
|
66516
|
+
import { defineCommand as defineCommand215 } from "citty";
|
|
66813
66517
|
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.";
|
|
66814
66518
|
registerSchema({
|
|
66815
66519
|
command: "studio.models",
|
|
@@ -66896,7 +66600,7 @@ function buildModelCards(kind, model) {
|
|
|
66896
66600
|
const selected = model ? ids.filter((id) => id === model) : ids;
|
|
66897
66601
|
return selected.map((id) => build(id));
|
|
66898
66602
|
}
|
|
66899
|
-
var modelsCommand =
|
|
66603
|
+
var modelsCommand = defineCommand215({
|
|
66900
66604
|
meta: {
|
|
66901
66605
|
name: "models",
|
|
66902
66606
|
description: `${DESCRIPTION3}
|
|
@@ -66943,13 +66647,13 @@ Examples:
|
|
|
66943
66647
|
});
|
|
66944
66648
|
|
|
66945
66649
|
// src/commands/studio/skills.ts
|
|
66946
|
-
import { defineCommand as
|
|
66650
|
+
import { defineCommand as defineCommand216 } from "citty";
|
|
66947
66651
|
registerSchema({
|
|
66948
66652
|
command: "studio.skills",
|
|
66949
66653
|
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.",
|
|
66950
66654
|
args: {}
|
|
66951
66655
|
});
|
|
66952
|
-
var skillsCommand =
|
|
66656
|
+
var skillsCommand = defineCommand216({
|
|
66953
66657
|
meta: {
|
|
66954
66658
|
name: "skills",
|
|
66955
66659
|
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"
|
|
@@ -66973,7 +66677,7 @@ var skillsCommand = defineCommand222({
|
|
|
66973
66677
|
});
|
|
66974
66678
|
|
|
66975
66679
|
// src/commands/studio/index.ts
|
|
66976
|
-
var studioCommand =
|
|
66680
|
+
var studioCommand = defineCommand217({
|
|
66977
66681
|
meta: {
|
|
66978
66682
|
name: "studio",
|
|
66979
66683
|
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.
|
|
@@ -67007,7 +66711,7 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
67007
66711
|
generate: generateCommand,
|
|
67008
66712
|
animate: animateCommand,
|
|
67009
66713
|
get: getCommand5,
|
|
67010
|
-
list:
|
|
66714
|
+
list: listCommand18,
|
|
67011
66715
|
keep: keepCommand,
|
|
67012
66716
|
models: modelsCommand,
|
|
67013
66717
|
skills: skillsCommand,
|
|
@@ -67016,10 +66720,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
67016
66720
|
});
|
|
67017
66721
|
|
|
67018
66722
|
// src/commands/tag-manager/index.ts
|
|
67019
|
-
import { defineCommand as
|
|
66723
|
+
import { defineCommand as defineCommand221 } from "citty";
|
|
67020
66724
|
|
|
67021
66725
|
// src/commands/tag-manager/draft.ts
|
|
67022
|
-
import { defineCommand as
|
|
66726
|
+
import { defineCommand as defineCommand218 } from "citty";
|
|
67023
66727
|
|
|
67024
66728
|
// src/commands/tag-manager/shared.ts
|
|
67025
66729
|
import { readFileSync as readFileSync21 } from "fs";
|
|
@@ -67086,10 +66790,10 @@ async function stageOp4(op) {
|
|
|
67086
66790
|
handleError8(err);
|
|
67087
66791
|
}
|
|
67088
66792
|
}
|
|
67089
|
-
async function draftAction3(
|
|
66793
|
+
async function draftAction3(path48, body, chat) {
|
|
67090
66794
|
const chatId = resolveChatId(chat);
|
|
67091
66795
|
try {
|
|
67092
|
-
const data = await apiPost(
|
|
66796
|
+
const data = await apiPost(path48, { chatId, ...body });
|
|
67093
66797
|
writeJsonEnvelope({ ok: true, data });
|
|
67094
66798
|
return data;
|
|
67095
66799
|
} catch (err) {
|
|
@@ -67142,13 +66846,13 @@ registerSchema({
|
|
|
67142
66846
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
67143
66847
|
}
|
|
67144
66848
|
});
|
|
67145
|
-
var draftCommand5 =
|
|
66849
|
+
var draftCommand5 = defineCommand218({
|
|
67146
66850
|
meta: {
|
|
67147
66851
|
name: "draft",
|
|
67148
66852
|
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."
|
|
67149
66853
|
},
|
|
67150
66854
|
subCommands: {
|
|
67151
|
-
list:
|
|
66855
|
+
list: defineCommand218({
|
|
67152
66856
|
meta: {
|
|
67153
66857
|
name: "list",
|
|
67154
66858
|
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
@@ -67161,7 +66865,7 @@ var draftCommand5 = defineCommand224({
|
|
|
67161
66865
|
await draftList2(args5.json === true, args5.chat);
|
|
67162
66866
|
}
|
|
67163
66867
|
}),
|
|
67164
|
-
show:
|
|
66868
|
+
show: defineCommand218({
|
|
67165
66869
|
meta: {
|
|
67166
66870
|
name: "show",
|
|
67167
66871
|
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
@@ -67178,7 +66882,7 @@ var draftCommand5 = defineCommand224({
|
|
|
67178
66882
|
);
|
|
67179
66883
|
}
|
|
67180
66884
|
}),
|
|
67181
|
-
amend:
|
|
66885
|
+
amend: defineCommand218({
|
|
67182
66886
|
meta: {
|
|
67183
66887
|
name: "amend",
|
|
67184
66888
|
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."
|
|
@@ -67195,7 +66899,7 @@ var draftCommand5 = defineCommand224({
|
|
|
67195
66899
|
});
|
|
67196
66900
|
}
|
|
67197
66901
|
}),
|
|
67198
|
-
remove:
|
|
66902
|
+
remove: defineCommand218({
|
|
67199
66903
|
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
67200
66904
|
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
67201
66905
|
run: async ({ args: args5 }) => {
|
|
@@ -67204,7 +66908,7 @@ var draftCommand5 = defineCommand224({
|
|
|
67204
66908
|
});
|
|
67205
66909
|
}
|
|
67206
66910
|
}),
|
|
67207
|
-
clear:
|
|
66911
|
+
clear: defineCommand218({
|
|
67208
66912
|
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
67209
66913
|
run: async () => {
|
|
67210
66914
|
await draftAction3("/api/tag-manager/draft/clear", {});
|
|
@@ -67214,7 +66918,7 @@ var draftCommand5 = defineCommand224({
|
|
|
67214
66918
|
});
|
|
67215
66919
|
|
|
67216
66920
|
// src/commands/tag-manager/read.ts
|
|
67217
|
-
import { defineCommand as
|
|
66921
|
+
import { defineCommand as defineCommand219 } from "citty";
|
|
67218
66922
|
registerSchema({
|
|
67219
66923
|
command: "tagManager.containers",
|
|
67220
66924
|
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.",
|
|
@@ -67255,7 +66959,7 @@ function containersHints(containers) {
|
|
|
67255
66959
|
}))
|
|
67256
66960
|
});
|
|
67257
66961
|
}
|
|
67258
|
-
var containersCommand =
|
|
66962
|
+
var containersCommand = defineCommand219({
|
|
67259
66963
|
meta: {
|
|
67260
66964
|
name: "containers",
|
|
67261
66965
|
description: `List Tag Manager containers reachable by this company's connection.
|
|
@@ -67272,7 +66976,7 @@ Start here:
|
|
|
67272
66976
|
}
|
|
67273
66977
|
}
|
|
67274
66978
|
});
|
|
67275
|
-
var readCommand =
|
|
66979
|
+
var readCommand = defineCommand219({
|
|
67276
66980
|
meta: {
|
|
67277
66981
|
name: "read",
|
|
67278
66982
|
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
@@ -67314,7 +67018,7 @@ Examples:
|
|
|
67314
67018
|
});
|
|
67315
67019
|
|
|
67316
67020
|
// src/commands/tag-manager/write-commands.ts
|
|
67317
|
-
import { defineCommand as
|
|
67021
|
+
import { defineCommand as defineCommand220 } from "citty";
|
|
67318
67022
|
var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
|
|
67319
67023
|
var ENTITIES = [
|
|
67320
67024
|
{
|
|
@@ -67370,10 +67074,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
|
|
|
67370
67074
|
});
|
|
67371
67075
|
}
|
|
67372
67076
|
function entityCommand(entity, noun, example) {
|
|
67373
|
-
return
|
|
67077
|
+
return defineCommand220({
|
|
67374
67078
|
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
67375
67079
|
subCommands: {
|
|
67376
|
-
create:
|
|
67080
|
+
create: defineCommand220({
|
|
67377
67081
|
meta: {
|
|
67378
67082
|
name: "create",
|
|
67379
67083
|
description: `Stage a new ${noun}
|
|
@@ -67395,7 +67099,7 @@ Examples:
|
|
|
67395
67099
|
});
|
|
67396
67100
|
}
|
|
67397
67101
|
}),
|
|
67398
|
-
update:
|
|
67102
|
+
update: defineCommand220({
|
|
67399
67103
|
meta: {
|
|
67400
67104
|
name: "update",
|
|
67401
67105
|
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
@@ -67415,7 +67119,7 @@ Examples:
|
|
|
67415
67119
|
});
|
|
67416
67120
|
}
|
|
67417
67121
|
}),
|
|
67418
|
-
delete:
|
|
67122
|
+
delete: defineCommand220({
|
|
67419
67123
|
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
67420
67124
|
args: {
|
|
67421
67125
|
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
@@ -67456,7 +67160,7 @@ function builtinTypes(args5) {
|
|
|
67456
67160
|
}
|
|
67457
67161
|
return raw.split(",").map((entry) => entry.trim());
|
|
67458
67162
|
}
|
|
67459
|
-
var builtinCommand =
|
|
67163
|
+
var builtinCommand = defineCommand220({
|
|
67460
67164
|
meta: {
|
|
67461
67165
|
name: "builtin",
|
|
67462
67166
|
description: `Enable or disable built-in variables
|
|
@@ -67466,7 +67170,7 @@ Examples:
|
|
|
67466
67170
|
baker tag-manager builtin disable --types formId`
|
|
67467
67171
|
},
|
|
67468
67172
|
subCommands: {
|
|
67469
|
-
enable:
|
|
67173
|
+
enable: defineCommand220({
|
|
67470
67174
|
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
67471
67175
|
args: {
|
|
67472
67176
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67480,7 +67184,7 @@ Examples:
|
|
|
67480
67184
|
});
|
|
67481
67185
|
}
|
|
67482
67186
|
}),
|
|
67483
|
-
disable:
|
|
67187
|
+
disable: defineCommand220({
|
|
67484
67188
|
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
67485
67189
|
args: {
|
|
67486
67190
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -67498,7 +67202,7 @@ Examples:
|
|
|
67498
67202
|
});
|
|
67499
67203
|
|
|
67500
67204
|
// src/commands/tag-manager/index.ts
|
|
67501
|
-
var tagManagerCommand =
|
|
67205
|
+
var tagManagerCommand = defineCommand221({
|
|
67502
67206
|
meta: {
|
|
67503
67207
|
name: "tag-manager",
|
|
67504
67208
|
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
@@ -67535,7 +67239,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
|
67535
67239
|
});
|
|
67536
67240
|
|
|
67537
67241
|
// src/commands/tags/index.ts
|
|
67538
|
-
import { defineCommand as
|
|
67242
|
+
import { defineCommand as defineCommand222 } from "citty";
|
|
67539
67243
|
|
|
67540
67244
|
// src/commands/tags/shared.ts
|
|
67541
67245
|
function failApi3(err) {
|
|
@@ -67615,7 +67319,7 @@ async function listTags(json) {
|
|
|
67615
67319
|
var listArgs12 = {
|
|
67616
67320
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
|
|
67617
67321
|
};
|
|
67618
|
-
var
|
|
67322
|
+
var listCommand19 = defineCommand222({
|
|
67619
67323
|
meta: {
|
|
67620
67324
|
name: "list",
|
|
67621
67325
|
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"
|
|
@@ -67634,7 +67338,7 @@ async function listDraft4(chat) {
|
|
|
67634
67338
|
failApi3(err);
|
|
67635
67339
|
}
|
|
67636
67340
|
}
|
|
67637
|
-
var draftCommand6 =
|
|
67341
|
+
var draftCommand6 = defineCommand222({
|
|
67638
67342
|
meta: {
|
|
67639
67343
|
name: "draft",
|
|
67640
67344
|
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."
|
|
@@ -67644,7 +67348,7 @@ var draftCommand6 = defineCommand228({
|
|
|
67644
67348
|
await listDraft4(args5.chat);
|
|
67645
67349
|
}
|
|
67646
67350
|
});
|
|
67647
|
-
var tagsCommand4 =
|
|
67351
|
+
var tagsCommand4 = defineCommand222({
|
|
67648
67352
|
meta: {
|
|
67649
67353
|
name: "tags",
|
|
67650
67354
|
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.
|
|
@@ -67661,7 +67365,7 @@ Examples:
|
|
|
67661
67365
|
Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
67662
67366
|
},
|
|
67663
67367
|
subCommands: {
|
|
67664
|
-
list:
|
|
67368
|
+
list: listCommand19,
|
|
67665
67369
|
draft: draftCommand6
|
|
67666
67370
|
},
|
|
67667
67371
|
// Bare `baker tags` lists the effective tags. `args` stays so citty knows this
|
|
@@ -67673,10 +67377,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
67673
67377
|
});
|
|
67674
67378
|
|
|
67675
67379
|
// src/commands/testimonials/index.ts
|
|
67676
|
-
import { defineCommand as
|
|
67380
|
+
import { defineCommand as defineCommand226 } from "citty";
|
|
67677
67381
|
|
|
67678
67382
|
// src/commands/testimonials/get.ts
|
|
67679
|
-
import { defineCommand as
|
|
67383
|
+
import { defineCommand as defineCommand223 } from "citty";
|
|
67680
67384
|
registerSchema({
|
|
67681
67385
|
command: "testimonials.get",
|
|
67682
67386
|
description: "Get a single testimonial by ID",
|
|
@@ -67684,7 +67388,7 @@ registerSchema({
|
|
|
67684
67388
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
67685
67389
|
}
|
|
67686
67390
|
});
|
|
67687
|
-
var getCommand6 =
|
|
67391
|
+
var getCommand6 = defineCommand223({
|
|
67688
67392
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
67689
67393
|
args: {
|
|
67690
67394
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -67721,7 +67425,7 @@ var getCommand6 = defineCommand229({
|
|
|
67721
67425
|
});
|
|
67722
67426
|
|
|
67723
67427
|
// src/commands/testimonials/list.ts
|
|
67724
|
-
import { defineCommand as
|
|
67428
|
+
import { defineCommand as defineCommand224 } from "citty";
|
|
67725
67429
|
|
|
67726
67430
|
// src/commands/testimonials/emptyCorpusHints.ts
|
|
67727
67431
|
function resolveEmptyReason({
|
|
@@ -67878,7 +67582,7 @@ function buildListParams(args5) {
|
|
|
67878
67582
|
}
|
|
67879
67583
|
return params;
|
|
67880
67584
|
}
|
|
67881
|
-
var
|
|
67585
|
+
var listCommand20 = defineCommand224({
|
|
67882
67586
|
meta: {
|
|
67883
67587
|
name: "list",
|
|
67884
67588
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -67938,7 +67642,7 @@ var listCommand21 = defineCommand230({
|
|
|
67938
67642
|
});
|
|
67939
67643
|
|
|
67940
67644
|
// src/commands/testimonials/search.ts
|
|
67941
|
-
import { defineCommand as
|
|
67645
|
+
import { defineCommand as defineCommand225 } from "citty";
|
|
67942
67646
|
var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
|
|
67943
67647
|
function languageBiasHint(results, requestedLanguage) {
|
|
67944
67648
|
if (requestedLanguage) {
|
|
@@ -68017,7 +67721,7 @@ function buildSearchRequest(query, args5) {
|
|
|
68017
67721
|
}
|
|
68018
67722
|
return body;
|
|
68019
67723
|
}
|
|
68020
|
-
var searchCommand3 =
|
|
67724
|
+
var searchCommand3 = defineCommand225({
|
|
68021
67725
|
meta: {
|
|
68022
67726
|
name: "search",
|
|
68023
67727
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -68081,7 +67785,7 @@ var searchCommand3 = defineCommand231({
|
|
|
68081
67785
|
var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
68082
67786
|
|
|
68083
67787
|
// src/commands/testimonials/index.ts
|
|
68084
|
-
var testimonialsCommand =
|
|
67788
|
+
var testimonialsCommand = defineCommand226({
|
|
68085
67789
|
meta: {
|
|
68086
67790
|
name: "testimonials",
|
|
68087
67791
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -68097,16 +67801,16 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
68097
67801
|
subCommands: {
|
|
68098
67802
|
get: getCommand6,
|
|
68099
67803
|
search: searchCommand3,
|
|
68100
|
-
list:
|
|
67804
|
+
list: listCommand20,
|
|
68101
67805
|
tags: tagsCommand5
|
|
68102
67806
|
}
|
|
68103
67807
|
});
|
|
68104
67808
|
|
|
68105
67809
|
// src/commands/videos/index.ts
|
|
68106
|
-
import { defineCommand as
|
|
67810
|
+
import { defineCommand as defineCommand234 } from "citty";
|
|
68107
67811
|
|
|
68108
67812
|
// src/commands/videos/delete.ts
|
|
68109
|
-
import { defineCommand as
|
|
67813
|
+
import { defineCommand as defineCommand227 } from "citty";
|
|
68110
67814
|
registerSchema({
|
|
68111
67815
|
command: "videos.delete",
|
|
68112
67816
|
description: "Delete a video by ID",
|
|
@@ -68120,7 +67824,7 @@ registerSchema({
|
|
|
68120
67824
|
}
|
|
68121
67825
|
}
|
|
68122
67826
|
});
|
|
68123
|
-
var deleteCommand4 =
|
|
67827
|
+
var deleteCommand4 = defineCommand227({
|
|
68124
67828
|
meta: {
|
|
68125
67829
|
name: "delete",
|
|
68126
67830
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -68161,7 +67865,7 @@ var deleteCommand4 = defineCommand233({
|
|
|
68161
67865
|
});
|
|
68162
67866
|
|
|
68163
67867
|
// src/commands/videos/describe.ts
|
|
68164
|
-
import { defineCommand as
|
|
67868
|
+
import { defineCommand as defineCommand228 } from "citty";
|
|
68165
67869
|
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.";
|
|
68166
67870
|
registerSchema({
|
|
68167
67871
|
command: "videos.describe",
|
|
@@ -68178,7 +67882,7 @@ registerSchema({
|
|
|
68178
67882
|
full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
|
|
68179
67883
|
}
|
|
68180
67884
|
});
|
|
68181
|
-
var describeCommand2 =
|
|
67885
|
+
var describeCommand2 = defineCommand228({
|
|
68182
67886
|
meta: {
|
|
68183
67887
|
name: "describe",
|
|
68184
67888
|
description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
|
|
@@ -68235,10 +67939,108 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
68235
67939
|
}
|
|
68236
67940
|
});
|
|
68237
67941
|
|
|
68238
|
-
// src/commands/videos/
|
|
68239
|
-
import {
|
|
67942
|
+
// src/commands/videos/get.ts
|
|
67943
|
+
import { defineCommand as defineCommand229 } from "citty";
|
|
67944
|
+
registerSchema({
|
|
67945
|
+
command: "videos.get",
|
|
67946
|
+
description: "Get a single video by ID",
|
|
67947
|
+
args: {
|
|
67948
|
+
id: { type: "string", description: "Video ID", required: true }
|
|
67949
|
+
}
|
|
67950
|
+
});
|
|
67951
|
+
var getCommand7 = defineCommand229({
|
|
67952
|
+
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
67953
|
+
args: {
|
|
67954
|
+
id: { type: "positional", description: "Video ID", required: false },
|
|
67955
|
+
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
67956
|
+
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
67957
|
+
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
67958
|
+
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
67959
|
+
},
|
|
67960
|
+
run: async ({ args: args5 }) => {
|
|
67961
|
+
try {
|
|
67962
|
+
const id = args5.id || args5["video-id"];
|
|
67963
|
+
if (!id) {
|
|
67964
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
67965
|
+
process.exit(1);
|
|
67966
|
+
}
|
|
67967
|
+
validateConvexId(id);
|
|
67968
|
+
const data = await apiGet("/api/videos/get", { id });
|
|
67969
|
+
writeOutput(
|
|
67970
|
+
{ ok: true, data },
|
|
67971
|
+
args5.output || "json",
|
|
67972
|
+
args5.fields ? args5.fields.split(",") : void 0,
|
|
67973
|
+
args5.full,
|
|
67974
|
+
videoNormalizer
|
|
67975
|
+
);
|
|
67976
|
+
} catch (err) {
|
|
67977
|
+
if (err instanceof ApiError) {
|
|
67978
|
+
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
67979
|
+
process.exit(1);
|
|
67980
|
+
}
|
|
67981
|
+
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
67982
|
+
process.exit(1);
|
|
67983
|
+
}
|
|
67984
|
+
}
|
|
67985
|
+
});
|
|
67986
|
+
|
|
67987
|
+
// src/commands/videos/group.ts
|
|
67988
|
+
import { defineCommand as defineCommand230 } from "citty";
|
|
67989
|
+
registerSchema({
|
|
67990
|
+
command: "videos.group",
|
|
67991
|
+
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
67992
|
+
args: {
|
|
67993
|
+
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
67994
|
+
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
67995
|
+
}
|
|
67996
|
+
});
|
|
67997
|
+
var groupCommand2 = defineCommand230({
|
|
67998
|
+
meta: {
|
|
67999
|
+
name: "group",
|
|
68000
|
+
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>"
|
|
68001
|
+
},
|
|
68002
|
+
args: {
|
|
68003
|
+
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
68004
|
+
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
68005
|
+
},
|
|
68006
|
+
run: async ({ args: args5 }) => {
|
|
68007
|
+
await runMediaGroupLookup({
|
|
68008
|
+
id: args5.id,
|
|
68009
|
+
groupKey: args5["group-key"],
|
|
68010
|
+
path: "/api/videos/group",
|
|
68011
|
+
idLabel: "a video or image id"
|
|
68012
|
+
});
|
|
68013
|
+
}
|
|
68014
|
+
});
|
|
68015
|
+
|
|
68016
|
+
// src/commands/videos/ingest.ts
|
|
68017
|
+
import { mkdtemp as mkdtemp3, rm as rm9, stat as stat11 } from "fs/promises";
|
|
68018
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
68240
68019
|
import path47 from "path";
|
|
68241
|
-
import { defineCommand as
|
|
68020
|
+
import { defineCommand as defineCommand231 } from "citty";
|
|
68021
|
+
|
|
68022
|
+
// src/lib/streamUpload.ts
|
|
68023
|
+
import { createHash as createHash2 } from "crypto";
|
|
68024
|
+
import { createReadStream } from "fs";
|
|
68025
|
+
import { Readable } from "stream";
|
|
68026
|
+
import { pipeline } from "stream/promises";
|
|
68027
|
+
async function hashFile(filePath) {
|
|
68028
|
+
const hash = createHash2("sha256");
|
|
68029
|
+
await pipeline(createReadStream(filePath), hash);
|
|
68030
|
+
return hash.digest("hex");
|
|
68031
|
+
}
|
|
68032
|
+
async function putFileStreamed(args5) {
|
|
68033
|
+
const body = Readable.toWeb(createReadStream(args5.filePath));
|
|
68034
|
+
return await fetch(args5.putUrl, {
|
|
68035
|
+
method: "PUT",
|
|
68036
|
+
body,
|
|
68037
|
+
headers: {
|
|
68038
|
+
"Content-Type": args5.contentType,
|
|
68039
|
+
"Content-Length": String(args5.sizeBytes)
|
|
68040
|
+
},
|
|
68041
|
+
duplex: "half"
|
|
68042
|
+
});
|
|
68043
|
+
}
|
|
68242
68044
|
|
|
68243
68045
|
// src/commands/videos/videoPlatforms.ts
|
|
68244
68046
|
var PLATFORM_DOMAINS = {
|
|
@@ -68247,7 +68049,6 @@ var PLATFORM_DOMAINS = {
|
|
|
68247
68049
|
tiktok: ["tiktok.com"],
|
|
68248
68050
|
twitter: ["twitter.com", "x.com", "vxtwitter.com", "fixvx.com"],
|
|
68249
68051
|
facebook: ["facebook.com", "fb.watch", "fb.com"],
|
|
68250
|
-
linkedin: ["linkedin.com", "lnkd.in"],
|
|
68251
68052
|
reddit: ["reddit.com", "redd.it"],
|
|
68252
68053
|
vimeo: ["vimeo.com"],
|
|
68253
68054
|
dailymotion: ["dailymotion.com", "dai.ly"],
|
|
@@ -68352,188 +68153,6 @@ function safePathname(rawUrl) {
|
|
|
68352
68153
|
}
|
|
68353
68154
|
}
|
|
68354
68155
|
|
|
68355
|
-
// src/commands/videos/fetch.ts
|
|
68356
|
-
registerSchema({
|
|
68357
|
-
command: "videos.fetch",
|
|
68358
|
-
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.",
|
|
68359
|
-
args: {
|
|
68360
|
-
url: { type: "string", description: "Video page URL", required: true },
|
|
68361
|
-
out: { type: "string", description: "Directory to write the file into (created if missing)", required: true },
|
|
68362
|
-
"max-seconds": {
|
|
68363
|
-
type: "string",
|
|
68364
|
-
description: `Refuse videos longer than this many seconds (default ${MAX_VIDEO_INGEST_SECONDS})`,
|
|
68365
|
-
required: false
|
|
68366
|
-
},
|
|
68367
|
-
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
68368
|
-
"max-height": {
|
|
68369
|
-
type: "string",
|
|
68370
|
-
description: "Keep a version no taller than this many pixels (e.g. 1080) when the site offers one",
|
|
68371
|
-
required: false
|
|
68372
|
-
}
|
|
68373
|
-
}
|
|
68374
|
-
});
|
|
68375
|
-
function positiveInt(value) {
|
|
68376
|
-
const parsed = typeof value === "string" ? Number.parseInt(value, 10) : Number.NaN;
|
|
68377
|
-
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
68378
|
-
}
|
|
68379
|
-
var fetchCommand2 = defineCommand235({
|
|
68380
|
-
meta: {
|
|
68381
|
-
name: "fetch",
|
|
68382
|
-
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"
|
|
68383
|
-
},
|
|
68384
|
-
args: {
|
|
68385
|
-
url: { type: "positional", description: "Video page URL", required: true },
|
|
68386
|
-
out: { type: "string", description: "Directory to write the file into", required: true },
|
|
68387
|
-
"max-seconds": { type: "string", description: "Refuse videos longer than this", required: false },
|
|
68388
|
-
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
68389
|
-
"max-height": { type: "string", description: "Keep a version no taller than this (e.g. 1080)", required: false }
|
|
68390
|
-
},
|
|
68391
|
-
run: async ({ args: args5 }) => {
|
|
68392
|
-
const url = String(args5.url ?? "");
|
|
68393
|
-
const outDir = path47.resolve(String(args5.out ?? ""));
|
|
68394
|
-
const maxSeconds = positiveInt(args5["max-seconds"]) ?? MAX_VIDEO_INGEST_SECONDS;
|
|
68395
|
-
try {
|
|
68396
|
-
await mkdir15(outDir, { recursive: true });
|
|
68397
|
-
const vimeoCookie = captureVimeoCookie();
|
|
68398
|
-
const probe = await probeYtDlp({ url, vimeoCookie, cookieDir: outDir });
|
|
68399
|
-
if (isAudioOnly(probe.info)) {
|
|
68400
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "That link is audio, not video." } });
|
|
68401
|
-
process.exit(1);
|
|
68402
|
-
}
|
|
68403
|
-
const seconds = durationSeconds(probe.info);
|
|
68404
|
-
const tooLong = refuseByDuration(seconds, maxSeconds);
|
|
68405
|
-
if (tooLong) {
|
|
68406
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: tooLong } });
|
|
68407
|
-
process.exit(1);
|
|
68408
|
-
}
|
|
68409
|
-
const { filePath, tier, reducedQuality } = await runYtDlp({
|
|
68410
|
-
url,
|
|
68411
|
-
audioOnly: false,
|
|
68412
|
-
workDir: outDir,
|
|
68413
|
-
vimeoCookie,
|
|
68414
|
-
timeoutMs: positiveInt(args5["timeout-ms"]) ?? downloadTimeoutMs(seconds),
|
|
68415
|
-
maxHeight: positiveInt(args5["max-height"])
|
|
68416
|
-
});
|
|
68417
|
-
writeJson({
|
|
68418
|
-
ok: true,
|
|
68419
|
-
data: {
|
|
68420
|
-
file: filePath,
|
|
68421
|
-
durationSeconds: seconds,
|
|
68422
|
-
egress: tier,
|
|
68423
|
-
...reducedQuality ? { reducedQuality: true } : {}
|
|
68424
|
-
}
|
|
68425
|
-
});
|
|
68426
|
-
} catch (err) {
|
|
68427
|
-
const message = err instanceof YtDlpError ? `${err.message}: ${err.stderrTail}`.trim() : err instanceof Error ? err.message : String(err);
|
|
68428
|
-
writeJson({ ok: false, error: { code: "DOWNLOAD_FAILED", message } });
|
|
68429
|
-
process.exit(1);
|
|
68430
|
-
}
|
|
68431
|
-
}
|
|
68432
|
-
});
|
|
68433
|
-
|
|
68434
|
-
// src/commands/videos/get.ts
|
|
68435
|
-
import { defineCommand as defineCommand236 } from "citty";
|
|
68436
|
-
registerSchema({
|
|
68437
|
-
command: "videos.get",
|
|
68438
|
-
description: "Get a single video by ID",
|
|
68439
|
-
args: {
|
|
68440
|
-
id: { type: "string", description: "Video ID", required: true }
|
|
68441
|
-
}
|
|
68442
|
-
});
|
|
68443
|
-
var getCommand7 = defineCommand236({
|
|
68444
|
-
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
68445
|
-
args: {
|
|
68446
|
-
id: { type: "positional", description: "Video ID", required: false },
|
|
68447
|
-
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
68448
|
-
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
68449
|
-
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
68450
|
-
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
68451
|
-
},
|
|
68452
|
-
run: async ({ args: args5 }) => {
|
|
68453
|
-
try {
|
|
68454
|
-
const id = args5.id || args5["video-id"];
|
|
68455
|
-
if (!id) {
|
|
68456
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
68457
|
-
process.exit(1);
|
|
68458
|
-
}
|
|
68459
|
-
validateConvexId(id);
|
|
68460
|
-
const data = await apiGet("/api/videos/get", { id });
|
|
68461
|
-
writeOutput(
|
|
68462
|
-
{ ok: true, data },
|
|
68463
|
-
args5.output || "json",
|
|
68464
|
-
args5.fields ? args5.fields.split(",") : void 0,
|
|
68465
|
-
args5.full,
|
|
68466
|
-
videoNormalizer
|
|
68467
|
-
);
|
|
68468
|
-
} catch (err) {
|
|
68469
|
-
if (err instanceof ApiError) {
|
|
68470
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
68471
|
-
process.exit(1);
|
|
68472
|
-
}
|
|
68473
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
68474
|
-
process.exit(1);
|
|
68475
|
-
}
|
|
68476
|
-
}
|
|
68477
|
-
});
|
|
68478
|
-
|
|
68479
|
-
// src/commands/videos/group.ts
|
|
68480
|
-
import { defineCommand as defineCommand237 } from "citty";
|
|
68481
|
-
registerSchema({
|
|
68482
|
-
command: "videos.group",
|
|
68483
|
-
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
68484
|
-
args: {
|
|
68485
|
-
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
68486
|
-
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
68487
|
-
}
|
|
68488
|
-
});
|
|
68489
|
-
var groupCommand2 = defineCommand237({
|
|
68490
|
-
meta: {
|
|
68491
|
-
name: "group",
|
|
68492
|
-
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>"
|
|
68493
|
-
},
|
|
68494
|
-
args: {
|
|
68495
|
-
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
68496
|
-
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
68497
|
-
},
|
|
68498
|
-
run: async ({ args: args5 }) => {
|
|
68499
|
-
await runMediaGroupLookup({
|
|
68500
|
-
id: args5.id,
|
|
68501
|
-
groupKey: args5["group-key"],
|
|
68502
|
-
path: "/api/videos/group",
|
|
68503
|
-
idLabel: "a video or image id"
|
|
68504
|
-
});
|
|
68505
|
-
}
|
|
68506
|
-
});
|
|
68507
|
-
|
|
68508
|
-
// src/commands/videos/ingest.ts
|
|
68509
|
-
import { mkdtemp as mkdtemp3, rm as rm9, stat as stat11 } from "fs/promises";
|
|
68510
|
-
import { tmpdir as tmpdir4 } from "os";
|
|
68511
|
-
import path48 from "path";
|
|
68512
|
-
import { defineCommand as defineCommand238 } from "citty";
|
|
68513
|
-
|
|
68514
|
-
// src/lib/streamUpload.ts
|
|
68515
|
-
import { createHash as createHash2 } from "crypto";
|
|
68516
|
-
import { createReadStream } from "fs";
|
|
68517
|
-
import { Readable } from "stream";
|
|
68518
|
-
import { pipeline } from "stream/promises";
|
|
68519
|
-
async function hashFile(filePath) {
|
|
68520
|
-
const hash = createHash2("sha256");
|
|
68521
|
-
await pipeline(createReadStream(filePath), hash);
|
|
68522
|
-
return hash.digest("hex");
|
|
68523
|
-
}
|
|
68524
|
-
async function putFileStreamed(args5) {
|
|
68525
|
-
const body = Readable.toWeb(createReadStream(args5.filePath));
|
|
68526
|
-
return await fetch(args5.putUrl, {
|
|
68527
|
-
method: "PUT",
|
|
68528
|
-
body,
|
|
68529
|
-
headers: {
|
|
68530
|
-
"Content-Type": args5.contentType,
|
|
68531
|
-
"Content-Length": String(args5.sizeBytes)
|
|
68532
|
-
},
|
|
68533
|
-
duplex: "half"
|
|
68534
|
-
});
|
|
68535
|
-
}
|
|
68536
|
-
|
|
68537
68156
|
// src/commands/videos/ingest.ts
|
|
68538
68157
|
registerSchema({
|
|
68539
68158
|
command: "videos.ingest",
|
|
@@ -68562,7 +68181,7 @@ registerSchema({
|
|
|
68562
68181
|
"dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
|
|
68563
68182
|
}
|
|
68564
68183
|
});
|
|
68565
|
-
var ingestCommand2 =
|
|
68184
|
+
var ingestCommand2 = defineCommand231({
|
|
68566
68185
|
meta: {
|
|
68567
68186
|
name: "ingest",
|
|
68568
68187
|
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"
|
|
@@ -68748,7 +68367,7 @@ function ingestUrl(args5) {
|
|
|
68748
68367
|
}
|
|
68749
68368
|
async function downloadThenIngest(args5, country) {
|
|
68750
68369
|
const vimeoCookie = captureVimeoCookie();
|
|
68751
|
-
const workDir = await mkdtemp3(
|
|
68370
|
+
const workDir = await mkdtemp3(path47.join(tmpdir4(), "videos-ingest-"));
|
|
68752
68371
|
try {
|
|
68753
68372
|
const probe = await probeYtDlp({ url: args5.url, country, vimeoCookie, cookieDir: workDir });
|
|
68754
68373
|
if (isAudioOnly(probe.info)) {
|
|
@@ -68824,7 +68443,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
|
|
|
68824
68443
|
}
|
|
68825
68444
|
|
|
68826
68445
|
// src/commands/videos/search.ts
|
|
68827
|
-
import { defineCommand as
|
|
68446
|
+
import { defineCommand as defineCommand232 } from "citty";
|
|
68828
68447
|
registerSchema({
|
|
68829
68448
|
command: "videos.search",
|
|
68830
68449
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -68834,7 +68453,7 @@ registerSchema({
|
|
|
68834
68453
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
68835
68454
|
}
|
|
68836
68455
|
});
|
|
68837
|
-
var searchCommand4 =
|
|
68456
|
+
var searchCommand4 = defineCommand232({
|
|
68838
68457
|
meta: {
|
|
68839
68458
|
name: "search",
|
|
68840
68459
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -68886,7 +68505,7 @@ var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
|
68886
68505
|
// src/commands/videos/upload.ts
|
|
68887
68506
|
import { readFile as readFile33, stat as stat12 } from "fs/promises";
|
|
68888
68507
|
import { basename as basename3, extname as extname4 } from "path";
|
|
68889
|
-
import { defineCommand as
|
|
68508
|
+
import { defineCommand as defineCommand233 } from "citty";
|
|
68890
68509
|
var MIME_MAP = {
|
|
68891
68510
|
".mp4": "video/mp4",
|
|
68892
68511
|
".mov": "video/quicktime",
|
|
@@ -68928,7 +68547,7 @@ function detectContentType(filePath) {
|
|
|
68928
68547
|
function isRemoteUrl3(value) {
|
|
68929
68548
|
return /^https?:\/\//i.test(value);
|
|
68930
68549
|
}
|
|
68931
|
-
var uploadCommand2 =
|
|
68550
|
+
var uploadCommand2 = defineCommand233({
|
|
68932
68551
|
meta: {
|
|
68933
68552
|
name: "upload",
|
|
68934
68553
|
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"
|
|
@@ -69012,10 +68631,10 @@ var uploadCommand2 = defineCommand240({
|
|
|
69012
68631
|
});
|
|
69013
68632
|
|
|
69014
68633
|
// src/commands/videos/index.ts
|
|
69015
|
-
var videosCommand =
|
|
68634
|
+
var videosCommand = defineCommand234({
|
|
69016
68635
|
meta: {
|
|
69017
68636
|
name: "videos",
|
|
69018
|
-
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest,
|
|
68637
|
+
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, describe, delete, tags.
|
|
69019
68638
|
|
|
69020
68639
|
Examples:
|
|
69021
68640
|
baker videos search "product demo" --limit 5
|
|
@@ -69023,7 +68642,6 @@ Examples:
|
|
|
69023
68642
|
baker videos get <video-id>
|
|
69024
68643
|
baker videos upload ./demo.mp4
|
|
69025
68644
|
baker videos ingest https://www.youtube.com/watch?v=abc123
|
|
69026
|
-
baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips
|
|
69027
68645
|
baker videos describe <video-id> --description "Customer testimonial, 30s"
|
|
69028
68646
|
baker videos delete <video-id> --dry-run
|
|
69029
68647
|
baker videos tags
|
|
@@ -69035,7 +68653,6 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
69035
68653
|
search: searchCommand4,
|
|
69036
68654
|
upload: uploadCommand2,
|
|
69037
68655
|
ingest: ingestCommand2,
|
|
69038
|
-
fetch: fetchCommand2,
|
|
69039
68656
|
describe: describeCommand2,
|
|
69040
68657
|
delete: deleteCommand4,
|
|
69041
68658
|
tags: tagsCommand6
|
|
@@ -69043,10 +68660,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
69043
68660
|
});
|
|
69044
68661
|
|
|
69045
68662
|
// src/commands/winning-ads/index.ts
|
|
69046
|
-
import { defineCommand as
|
|
68663
|
+
import { defineCommand as defineCommand247 } from "citty";
|
|
69047
68664
|
|
|
69048
68665
|
// src/commands/winning-ads/advertisers.ts
|
|
69049
|
-
import { defineCommand as
|
|
68666
|
+
import { defineCommand as defineCommand235 } from "citty";
|
|
69050
68667
|
|
|
69051
68668
|
// src/commands/winning-ads/shared.ts
|
|
69052
68669
|
function splitList3(value) {
|
|
@@ -69055,7 +68672,7 @@ function splitList3(value) {
|
|
|
69055
68672
|
}
|
|
69056
68673
|
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
69057
68674
|
}
|
|
69058
|
-
function
|
|
68675
|
+
function reportError2(err) {
|
|
69059
68676
|
if (err instanceof ApiError) {
|
|
69060
68677
|
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
69061
68678
|
process.exit(1);
|
|
@@ -69099,7 +68716,7 @@ function advertiserNormalizer(record, full) {
|
|
|
69099
68716
|
last_synced_at: record.last_synced_at ?? null
|
|
69100
68717
|
};
|
|
69101
68718
|
}
|
|
69102
|
-
var advertisersCommand2 =
|
|
68719
|
+
var advertisersCommand2 = defineCommand235({
|
|
69103
68720
|
meta: {
|
|
69104
68721
|
name: "advertisers",
|
|
69105
68722
|
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'
|
|
@@ -69151,13 +68768,13 @@ var advertisersCommand2 = defineCommand242({
|
|
|
69151
68768
|
advertiserNormalizer
|
|
69152
68769
|
);
|
|
69153
68770
|
} catch (err) {
|
|
69154
|
-
|
|
68771
|
+
reportError2(err);
|
|
69155
68772
|
}
|
|
69156
68773
|
}
|
|
69157
68774
|
});
|
|
69158
68775
|
|
|
69159
68776
|
// src/commands/winning-ads/brief.ts
|
|
69160
|
-
import { defineCommand as
|
|
68777
|
+
import { defineCommand as defineCommand236 } from "citty";
|
|
69161
68778
|
registerSchema({
|
|
69162
68779
|
command: "winning-ads.brief",
|
|
69163
68780
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -69203,7 +68820,7 @@ function parseDna(raw) {
|
|
|
69203
68820
|
}
|
|
69204
68821
|
return parsed;
|
|
69205
68822
|
}
|
|
69206
|
-
var briefCommand =
|
|
68823
|
+
var briefCommand = defineCommand236({
|
|
69207
68824
|
meta: {
|
|
69208
68825
|
name: "brief",
|
|
69209
68826
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -69233,13 +68850,13 @@ var briefCommand = defineCommand243({
|
|
|
69233
68850
|
const data = await apiPost("/api/ad-library/brief", body);
|
|
69234
68851
|
writeJson({ ok: true, data });
|
|
69235
68852
|
} catch (err) {
|
|
69236
|
-
|
|
68853
|
+
reportError2(err);
|
|
69237
68854
|
}
|
|
69238
68855
|
}
|
|
69239
68856
|
});
|
|
69240
68857
|
|
|
69241
68858
|
// src/commands/winning-ads/content.ts
|
|
69242
|
-
import { defineCommand as
|
|
68859
|
+
import { defineCommand as defineCommand237 } from "citty";
|
|
69243
68860
|
registerSchema({
|
|
69244
68861
|
command: "winning-ads.content",
|
|
69245
68862
|
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.",
|
|
@@ -69252,7 +68869,7 @@ registerSchema({
|
|
|
69252
68869
|
}
|
|
69253
68870
|
}
|
|
69254
68871
|
});
|
|
69255
|
-
var contentCommand =
|
|
68872
|
+
var contentCommand = defineCommand237({
|
|
69256
68873
|
meta: {
|
|
69257
68874
|
name: "content",
|
|
69258
68875
|
description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
@@ -69295,13 +68912,13 @@ var contentCommand = defineCommand244({
|
|
|
69295
68912
|
adContentNormalizer
|
|
69296
68913
|
);
|
|
69297
68914
|
} catch (err) {
|
|
69298
|
-
|
|
68915
|
+
reportError2(err);
|
|
69299
68916
|
}
|
|
69300
68917
|
}
|
|
69301
68918
|
});
|
|
69302
68919
|
|
|
69303
68920
|
// src/commands/winning-ads/feed.ts
|
|
69304
|
-
import { defineCommand as
|
|
68921
|
+
import { defineCommand as defineCommand238 } from "citty";
|
|
69305
68922
|
function buildFeedParams(input) {
|
|
69306
68923
|
const params = {};
|
|
69307
68924
|
const advertiser = splitList3(input.advertiser);
|
|
@@ -69353,7 +68970,7 @@ registerSchema({
|
|
|
69353
68970
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
69354
68971
|
}
|
|
69355
68972
|
});
|
|
69356
|
-
var feedCommand2 =
|
|
68973
|
+
var feedCommand2 = defineCommand238({
|
|
69357
68974
|
meta: {
|
|
69358
68975
|
name: "feed",
|
|
69359
68976
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -69432,13 +69049,13 @@ var feedCommand2 = defineCommand245({
|
|
|
69432
69049
|
`);
|
|
69433
69050
|
}
|
|
69434
69051
|
} catch (err) {
|
|
69435
|
-
|
|
69052
|
+
reportError2(err);
|
|
69436
69053
|
}
|
|
69437
69054
|
}
|
|
69438
69055
|
});
|
|
69439
69056
|
|
|
69440
69057
|
// src/commands/winning-ads/follow.ts
|
|
69441
|
-
import { defineCommand as
|
|
69058
|
+
import { defineCommand as defineCommand239 } from "citty";
|
|
69442
69059
|
var PLATFORMS = adLibraryPlatformSchema.options;
|
|
69443
69060
|
registerSchema({
|
|
69444
69061
|
command: "winning-ads.follow",
|
|
@@ -69453,7 +69070,7 @@ registerSchema({
|
|
|
69453
69070
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
69454
69071
|
}
|
|
69455
69072
|
});
|
|
69456
|
-
var followCommand =
|
|
69073
|
+
var followCommand = defineCommand239({
|
|
69457
69074
|
meta: {
|
|
69458
69075
|
name: "follow",
|
|
69459
69076
|
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'
|
|
@@ -69494,13 +69111,13 @@ var followCommand = defineCommand246({
|
|
|
69494
69111
|
}
|
|
69495
69112
|
writeJson({ ok: true, data, hints: hints2 });
|
|
69496
69113
|
} catch (err) {
|
|
69497
|
-
|
|
69114
|
+
reportError2(err);
|
|
69498
69115
|
}
|
|
69499
69116
|
}
|
|
69500
69117
|
});
|
|
69501
69118
|
|
|
69502
69119
|
// src/commands/winning-ads/follow-competitors.ts
|
|
69503
|
-
import { defineCommand as
|
|
69120
|
+
import { defineCommand as defineCommand240 } from "citty";
|
|
69504
69121
|
var PLATFORMS2 = adLibraryPlatformSchema.options;
|
|
69505
69122
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
69506
69123
|
function buildFollowBatchBody(input) {
|
|
@@ -69533,7 +69150,7 @@ registerSchema({
|
|
|
69533
69150
|
}
|
|
69534
69151
|
}
|
|
69535
69152
|
});
|
|
69536
|
-
var followCompetitorsCommand =
|
|
69153
|
+
var followCompetitorsCommand = defineCommand240({
|
|
69537
69154
|
meta: {
|
|
69538
69155
|
name: "follow-competitors",
|
|
69539
69156
|
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"'
|
|
@@ -69602,13 +69219,13 @@ var followCompetitorsCommand = defineCommand247({
|
|
|
69602
69219
|
}
|
|
69603
69220
|
writeJson({ ok: true, data, hints: hints2.length > 0 ? hints2 : void 0 });
|
|
69604
69221
|
} catch (err) {
|
|
69605
|
-
|
|
69222
|
+
reportError2(err);
|
|
69606
69223
|
}
|
|
69607
69224
|
}
|
|
69608
69225
|
});
|
|
69609
69226
|
|
|
69610
69227
|
// src/commands/winning-ads/following.ts
|
|
69611
|
-
import { defineCommand as
|
|
69228
|
+
import { defineCommand as defineCommand241 } from "citty";
|
|
69612
69229
|
registerSchema({
|
|
69613
69230
|
command: "winning-ads.following",
|
|
69614
69231
|
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.",
|
|
@@ -69662,7 +69279,7 @@ function followingNormalizer(record, full) {
|
|
|
69662
69279
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
69663
69280
|
};
|
|
69664
69281
|
}
|
|
69665
|
-
var followingCommand =
|
|
69282
|
+
var followingCommand = defineCommand241({
|
|
69666
69283
|
meta: {
|
|
69667
69284
|
name: "following",
|
|
69668
69285
|
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"
|
|
@@ -69692,13 +69309,13 @@ var followingCommand = defineCommand248({
|
|
|
69692
69309
|
followingNormalizer
|
|
69693
69310
|
);
|
|
69694
69311
|
} catch (err) {
|
|
69695
|
-
|
|
69312
|
+
reportError2(err);
|
|
69696
69313
|
}
|
|
69697
69314
|
}
|
|
69698
69315
|
});
|
|
69699
69316
|
|
|
69700
69317
|
// src/commands/winning-ads/patterns.ts
|
|
69701
|
-
import { defineCommand as
|
|
69318
|
+
import { defineCommand as defineCommand242 } from "citty";
|
|
69702
69319
|
registerSchema({
|
|
69703
69320
|
command: "winning-ads.patterns",
|
|
69704
69321
|
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.",
|
|
@@ -69737,7 +69354,7 @@ function discriminatorRow(record) {
|
|
|
69737
69354
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
69738
69355
|
};
|
|
69739
69356
|
}
|
|
69740
|
-
var patternsCommand =
|
|
69357
|
+
var patternsCommand = defineCommand242({
|
|
69741
69358
|
meta: {
|
|
69742
69359
|
name: "patterns",
|
|
69743
69360
|
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"
|
|
@@ -69787,13 +69404,13 @@ var patternsCommand = defineCommand249({
|
|
|
69787
69404
|
(record) => discriminatorRow(record)
|
|
69788
69405
|
);
|
|
69789
69406
|
} catch (err) {
|
|
69790
|
-
|
|
69407
|
+
reportError2(err);
|
|
69791
69408
|
}
|
|
69792
69409
|
}
|
|
69793
69410
|
});
|
|
69794
69411
|
|
|
69795
69412
|
// src/commands/winning-ads/search.ts
|
|
69796
|
-
import { defineCommand as
|
|
69413
|
+
import { defineCommand as defineCommand243 } from "citty";
|
|
69797
69414
|
registerSchema({
|
|
69798
69415
|
command: "winning-ads.search",
|
|
69799
69416
|
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.",
|
|
@@ -69929,9 +69546,9 @@ function reportSearchError(err) {
|
|
|
69929
69546
|
writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
|
|
69930
69547
|
process.exit(1);
|
|
69931
69548
|
}
|
|
69932
|
-
|
|
69549
|
+
reportError2(err);
|
|
69933
69550
|
}
|
|
69934
|
-
var searchCommand5 =
|
|
69551
|
+
var searchCommand5 = defineCommand243({
|
|
69935
69552
|
meta: {
|
|
69936
69553
|
name: "search",
|
|
69937
69554
|
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"
|
|
@@ -70051,7 +69668,7 @@ var searchCommand5 = defineCommand250({
|
|
|
70051
69668
|
});
|
|
70052
69669
|
|
|
70053
69670
|
// src/commands/winning-ads/seeds.ts
|
|
70054
|
-
import { defineCommand as
|
|
69671
|
+
import { defineCommand as defineCommand244 } from "citty";
|
|
70055
69672
|
function leanRow(r) {
|
|
70056
69673
|
return {
|
|
70057
69674
|
key: r.key,
|
|
@@ -70079,7 +69696,7 @@ function makeSeedCommand(opts) {
|
|
|
70079
69696
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
70080
69697
|
}
|
|
70081
69698
|
});
|
|
70082
|
-
return
|
|
69699
|
+
return defineCommand244({
|
|
70083
69700
|
meta: { name: opts.name, description: opts.description },
|
|
70084
69701
|
args: {
|
|
70085
69702
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -70106,7 +69723,7 @@ function makeSeedCommand(opts) {
|
|
|
70106
69723
|
}
|
|
70107
69724
|
writeOutput({ ok: true, data: projected }, output);
|
|
70108
69725
|
} catch (err) {
|
|
70109
|
-
|
|
69726
|
+
reportError2(err);
|
|
70110
69727
|
}
|
|
70111
69728
|
}
|
|
70112
69729
|
});
|
|
@@ -70128,7 +69745,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
70128
69745
|
});
|
|
70129
69746
|
|
|
70130
69747
|
// src/commands/winning-ads/unfollow.ts
|
|
70131
|
-
import { defineCommand as
|
|
69748
|
+
import { defineCommand as defineCommand245 } from "citty";
|
|
70132
69749
|
registerSchema({
|
|
70133
69750
|
command: "winning-ads.unfollow",
|
|
70134
69751
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -70136,7 +69753,7 @@ registerSchema({
|
|
|
70136
69753
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
70137
69754
|
}
|
|
70138
69755
|
});
|
|
70139
|
-
var unfollowCommand =
|
|
69756
|
+
var unfollowCommand = defineCommand245({
|
|
70140
69757
|
meta: {
|
|
70141
69758
|
name: "unfollow",
|
|
70142
69759
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -70151,13 +69768,13 @@ var unfollowCommand = defineCommand252({
|
|
|
70151
69768
|
});
|
|
70152
69769
|
writeJson({ ok: true, data });
|
|
70153
69770
|
} catch (err) {
|
|
70154
|
-
|
|
69771
|
+
reportError2(err);
|
|
70155
69772
|
}
|
|
70156
69773
|
}
|
|
70157
69774
|
});
|
|
70158
69775
|
|
|
70159
69776
|
// src/commands/winning-ads/winners.ts
|
|
70160
|
-
import { defineCommand as
|
|
69777
|
+
import { defineCommand as defineCommand246 } from "citty";
|
|
70161
69778
|
registerSchema({
|
|
70162
69779
|
command: "winning-ads.winners",
|
|
70163
69780
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -70167,7 +69784,7 @@ registerSchema({
|
|
|
70167
69784
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
|
|
70168
69785
|
}
|
|
70169
69786
|
});
|
|
70170
|
-
var winnersCommand =
|
|
69787
|
+
var winnersCommand = defineCommand246({
|
|
70171
69788
|
meta: {
|
|
70172
69789
|
name: "winners",
|
|
70173
69790
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -70211,13 +69828,13 @@ var winnersCommand = defineCommand253({
|
|
|
70211
69828
|
winningAdNormalizer
|
|
70212
69829
|
);
|
|
70213
69830
|
} catch (err) {
|
|
70214
|
-
|
|
69831
|
+
reportError2(err);
|
|
70215
69832
|
}
|
|
70216
69833
|
}
|
|
70217
69834
|
});
|
|
70218
69835
|
|
|
70219
69836
|
// src/commands/winning-ads/index.ts
|
|
70220
|
-
var winningAdsCommand =
|
|
69837
|
+
var winningAdsCommand = defineCommand247({
|
|
70221
69838
|
meta: {
|
|
70222
69839
|
name: "winning-ads",
|
|
70223
69840
|
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.
|
|
@@ -70289,7 +69906,7 @@ function getCliVersion() {
|
|
|
70289
69906
|
}
|
|
70290
69907
|
|
|
70291
69908
|
// src/cli.ts
|
|
70292
|
-
var main =
|
|
69909
|
+
var main = defineCommand248({
|
|
70293
69910
|
meta: {
|
|
70294
69911
|
name: "baker",
|
|
70295
69912
|
version: getCliVersion(),
|
|
@@ -70329,7 +69946,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
70329
69946
|
history: historyCommand2,
|
|
70330
69947
|
hubspot: hubspotCommand,
|
|
70331
69948
|
"winning-ads": winningAdsCommand,
|
|
70332
|
-
"media-sources": mediaSourcesCommand,
|
|
70333
69949
|
mcp: mcpCommand,
|
|
70334
69950
|
schema: schemaCommand2
|
|
70335
69951
|
}
|