@koda-sl/baker-cli 0.400.0 → 0.402.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 +41 -2
- package/dist/{chunk-UW62VPTH.js → chunk-X7PLV5QH.js} +211 -116
- package/dist/chunk-X7PLV5QH.js.map +1 -0
- package/dist/cli.js +871 -388
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +8 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-UW62VPTH.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -98,7 +98,7 @@ import {
|
|
|
98
98
|
withoutCastName,
|
|
99
99
|
wordCount,
|
|
100
100
|
ytDlpBlockSignal
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-X7PLV5QH.js";
|
|
102
102
|
import {
|
|
103
103
|
NAME_CONTAINS_ARG,
|
|
104
104
|
csvOrJson,
|
|
@@ -21716,7 +21716,7 @@ var require_entry_node = __commonJS({
|
|
|
21716
21716
|
});
|
|
21717
21717
|
|
|
21718
21718
|
// src/cli.ts
|
|
21719
|
-
import { defineCommand as
|
|
21719
|
+
import { defineCommand as defineCommand280, runMain } from "citty";
|
|
21720
21720
|
|
|
21721
21721
|
// src/cache-flag.ts
|
|
21722
21722
|
var NO_CACHE_ARG = {
|
|
@@ -26291,6 +26291,9 @@ var chatChangeTypeSchema = z13.enum([
|
|
|
26291
26291
|
"image",
|
|
26292
26292
|
"video",
|
|
26293
26293
|
"followed-advertiser",
|
|
26294
|
+
// A connected social account feeding the image and video libraries, keyed
|
|
26295
|
+
// on `platform:handle`. Immediate — see convex/mediaSources/mutations.ts.
|
|
26296
|
+
"media-source",
|
|
26294
26297
|
// A landing page saved to the reference library, keyed on the page.
|
|
26295
26298
|
"landing-reference",
|
|
26296
26299
|
// One Studio batch — the takes of one brief, as a set. See convex/lib/validators.ts.
|
|
@@ -28469,6 +28472,10 @@ var imageSourceSchema = z25.enum([
|
|
|
28469
28472
|
"google_testimonial",
|
|
28470
28473
|
"trustpilot_testimonial",
|
|
28471
28474
|
"instagram",
|
|
28475
|
+
"tiktok",
|
|
28476
|
+
"linkedin",
|
|
28477
|
+
"facebook",
|
|
28478
|
+
"google_drive",
|
|
28472
28479
|
"pexels",
|
|
28473
28480
|
"pixabay",
|
|
28474
28481
|
// Retired stock provider — kept so existing library rows stay filterable.
|
|
@@ -30284,7 +30291,9 @@ var videoSourceSchema = z35.enum([
|
|
|
30284
30291
|
"bluesky",
|
|
30285
30292
|
"dailymotion",
|
|
30286
30293
|
"facebook",
|
|
30294
|
+
"google_drive",
|
|
30287
30295
|
"instagram",
|
|
30296
|
+
"linkedin",
|
|
30288
30297
|
"loom",
|
|
30289
30298
|
"newgrounds",
|
|
30290
30299
|
"ok",
|
|
@@ -34509,16 +34518,16 @@ async function runChatgptRead(reference, read, hintsFor4) {
|
|
|
34509
34518
|
}
|
|
34510
34519
|
}
|
|
34511
34520
|
var TRUNCATED_HINT = "These rows are the first 2,000, not the whole account \u2014 narrow the read (--campaign-id, --ad-group-id) before counting them or concluding something is missing.";
|
|
34512
|
-
async function getChatgptList(
|
|
34513
|
-
const { data, headers } = await apiGetWithHeaders(
|
|
34521
|
+
async function getChatgptList(path58, params) {
|
|
34522
|
+
const { data, headers } = await apiGetWithHeaders(path58, params);
|
|
34514
34523
|
return { data, truncated: headers.get(CHATGPT_ADS_TRUNCATED_HEADER) === "true" };
|
|
34515
34524
|
}
|
|
34516
|
-
async function runChatgptListRead(reference,
|
|
34525
|
+
async function runChatgptListRead(reference, path58, params, hintsFor4) {
|
|
34517
34526
|
let truncated = false;
|
|
34518
34527
|
await runChatgptRead(
|
|
34519
34528
|
reference,
|
|
34520
34529
|
async () => {
|
|
34521
|
-
const read = await getChatgptList(
|
|
34530
|
+
const read = await getChatgptList(path58, params);
|
|
34522
34531
|
truncated = read.truncated;
|
|
34523
34532
|
return read.data;
|
|
34524
34533
|
},
|
|
@@ -35323,7 +35332,7 @@ var MEMBER_ARGS = {
|
|
|
35323
35332
|
},
|
|
35324
35333
|
country: { type: "string", description: "Country of phones written without a +code, e.g. ES" }
|
|
35325
35334
|
};
|
|
35326
|
-
function membersFromArgs(args8, readFile42 = (
|
|
35335
|
+
function membersFromArgs(args8, readFile42 = (path58) => readFileSync2(path58, "utf8")) {
|
|
35327
35336
|
const fromFile = typeof args8.file === "string" && args8.file ? membersFromFile(readFile42(args8.file)) : { emails: [], phones: [] };
|
|
35328
35337
|
const given = [...csvArg(args8.emails) ?? [], ...fromFile.emails];
|
|
35329
35338
|
const givenPhones = [...csvArg(args8.phones) ?? [], ...fromFile.phones];
|
|
@@ -38698,9 +38707,9 @@ var COPY_LIST_FLAG = {
|
|
|
38698
38707
|
descriptions: "--descriptions",
|
|
38699
38708
|
longHeadlines: "--long-headlines"
|
|
38700
38709
|
};
|
|
38701
|
-
function valueAt(root,
|
|
38710
|
+
function valueAt(root, path58) {
|
|
38702
38711
|
let node = root;
|
|
38703
|
-
for (const key of
|
|
38712
|
+
for (const key of path58) {
|
|
38704
38713
|
if (node === null || typeof node !== "object") return void 0;
|
|
38705
38714
|
node = node[key];
|
|
38706
38715
|
}
|
|
@@ -38933,11 +38942,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
38933
38942
|
function rawTextEntries(value2, rawArgs) {
|
|
38934
38943
|
return repeatedValues(rawArgs, "text", value2).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
38935
38944
|
}
|
|
38936
|
-
function rawFileEntries(
|
|
38937
|
-
if (typeof
|
|
38945
|
+
function rawFileEntries(path58) {
|
|
38946
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
38938
38947
|
return [];
|
|
38939
38948
|
}
|
|
38940
|
-
return readFileSync4(
|
|
38949
|
+
return readFileSync4(path58, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
38941
38950
|
}
|
|
38942
38951
|
function keywordEntries(args8, rawArgs) {
|
|
38943
38952
|
const defaultMatch = typeof args8["match-type"] === "string" ? args8["match-type"].toUpperCase() : void 0;
|
|
@@ -38960,14 +38969,14 @@ function keywordEntries(args8, rawArgs) {
|
|
|
38960
38969
|
}
|
|
38961
38970
|
return entries;
|
|
38962
38971
|
}
|
|
38963
|
-
function loadJsonFileArg(
|
|
38964
|
-
if (typeof
|
|
38972
|
+
function loadJsonFileArg(path58) {
|
|
38973
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
38965
38974
|
return {};
|
|
38966
38975
|
}
|
|
38967
|
-
const inline =
|
|
38968
|
-
const source = inline ? "inline JSON" :
|
|
38976
|
+
const inline = path58.trimStart().startsWith("{");
|
|
38977
|
+
const source = inline ? "inline JSON" : path58;
|
|
38969
38978
|
try {
|
|
38970
|
-
const parsed = JSON.parse(inline ?
|
|
38979
|
+
const parsed = JSON.parse(inline ? path58 : readFileSync4(path58, "utf8"));
|
|
38971
38980
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
38972
38981
|
failWriteValidation2(`${source} must contain a JSON object`);
|
|
38973
38982
|
}
|
|
@@ -39104,10 +39113,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
39104
39113
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
39105
39114
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
39106
39115
|
}
|
|
39107
|
-
async function draftAction(
|
|
39116
|
+
async function draftAction(path58, body, chat) {
|
|
39108
39117
|
try {
|
|
39109
39118
|
const chatId = resolveChatId(chat);
|
|
39110
|
-
const response = await apiPost(
|
|
39119
|
+
const response = await apiPost(path58, { chatId, ...body });
|
|
39111
39120
|
writeJsonEnvelope(response);
|
|
39112
39121
|
} catch (err) {
|
|
39113
39122
|
handleGoogleError(err);
|
|
@@ -41527,14 +41536,14 @@ function mappingRowProblem(row) {
|
|
|
41527
41536
|
|
|
41528
41537
|
// ../api/src/event-sources/template.ts
|
|
41529
41538
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
41530
|
-
function mentionOf(
|
|
41531
|
-
return `{{${
|
|
41539
|
+
function mentionOf(path58) {
|
|
41540
|
+
return `{{${path58}}}`;
|
|
41532
41541
|
}
|
|
41533
41542
|
function templateMentions(template) {
|
|
41534
41543
|
const seen = [];
|
|
41535
41544
|
for (const match of template.matchAll(MENTION)) {
|
|
41536
|
-
const
|
|
41537
|
-
if (
|
|
41545
|
+
const path58 = (match[1] ?? "").trim();
|
|
41546
|
+
if (path58 !== "" && !seen.includes(path58)) seen.push(path58);
|
|
41538
41547
|
}
|
|
41539
41548
|
return seen;
|
|
41540
41549
|
}
|
|
@@ -44909,17 +44918,17 @@ function ignoredColumnHints(columns) {
|
|
|
44909
44918
|
`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.`
|
|
44910
44919
|
];
|
|
44911
44920
|
}
|
|
44912
|
-
function readRowsFile(
|
|
44913
|
-
const inline =
|
|
44921
|
+
function readRowsFile(path58) {
|
|
44922
|
+
const inline = path58.trimStart().startsWith("[") || path58.trimStart().startsWith("{");
|
|
44914
44923
|
let text2;
|
|
44915
44924
|
try {
|
|
44916
|
-
text2 = inline ?
|
|
44925
|
+
text2 = inline ? path58 : readFileSync6(path58, "utf8");
|
|
44917
44926
|
} catch (err) {
|
|
44918
|
-
failWriteValidation2(`could not read ${
|
|
44927
|
+
failWriteValidation2(`could not read ${path58}: ${err instanceof Error ? err.message : String(err)}`);
|
|
44919
44928
|
}
|
|
44920
44929
|
const parsed = parseConversionRowsText(text2);
|
|
44921
44930
|
if (!parsed.ok) {
|
|
44922
|
-
failWriteValidation2(`${inline ? "the conversions passed inline" :
|
|
44931
|
+
failWriteValidation2(`${inline ? "the conversions passed inline" : path58}: ${parsed.error}`);
|
|
44923
44932
|
}
|
|
44924
44933
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
44925
44934
|
}
|
|
@@ -46820,19 +46829,19 @@ function failWriteValidation3(message) {
|
|
|
46820
46829
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
46821
46830
|
process.exit(1);
|
|
46822
46831
|
}
|
|
46823
|
-
function loadJsonFileArg2(
|
|
46824
|
-
if (typeof
|
|
46832
|
+
function loadJsonFileArg2(path58) {
|
|
46833
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46825
46834
|
return {};
|
|
46826
46835
|
}
|
|
46827
46836
|
try {
|
|
46828
|
-
const parsed = JSON.parse(readFileSync7(
|
|
46837
|
+
const parsed = JSON.parse(readFileSync7(path58, "utf8"));
|
|
46829
46838
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
46830
|
-
failWriteValidation3(`${
|
|
46839
|
+
failWriteValidation3(`${path58} must contain a JSON object`);
|
|
46831
46840
|
}
|
|
46832
46841
|
return parsed;
|
|
46833
46842
|
} catch (err) {
|
|
46834
46843
|
if (err instanceof SyntaxError) {
|
|
46835
|
-
failWriteValidation3(`${
|
|
46844
|
+
failWriteValidation3(`${path58} is not valid JSON: ${err.message}`);
|
|
46836
46845
|
}
|
|
46837
46846
|
throw err;
|
|
46838
46847
|
}
|
|
@@ -46917,15 +46926,15 @@ function parseLocaleFlag(value2) {
|
|
|
46917
46926
|
}
|
|
46918
46927
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
46919
46928
|
}
|
|
46920
|
-
function loadTargetingFileArg(
|
|
46921
|
-
if (typeof
|
|
46929
|
+
function loadTargetingFileArg(path58) {
|
|
46930
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46922
46931
|
return void 0;
|
|
46923
46932
|
}
|
|
46924
|
-
const parsed = loadJsonFileArg2(
|
|
46933
|
+
const parsed = loadJsonFileArg2(path58);
|
|
46925
46934
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
46926
46935
|
if (!criteria.include) {
|
|
46927
46936
|
failWriteValidation3(
|
|
46928
|
-
`${
|
|
46937
|
+
`${path58} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
46929
46938
|
);
|
|
46930
46939
|
}
|
|
46931
46940
|
return criteria;
|
|
@@ -46960,14 +46969,14 @@ function parseCsvLine(line) {
|
|
|
46960
46969
|
cells.push(current);
|
|
46961
46970
|
return cells.map((cell3) => cell3.trim());
|
|
46962
46971
|
}
|
|
46963
|
-
function parseListFileArg(
|
|
46964
|
-
if (typeof
|
|
46972
|
+
function parseListFileArg(path58, maxRows) {
|
|
46973
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
46965
46974
|
return void 0;
|
|
46966
46975
|
}
|
|
46967
|
-
const raw = readFileSync7(
|
|
46976
|
+
const raw = readFileSync7(path58, "utf8");
|
|
46968
46977
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
46969
46978
|
if (lines.length < 2) {
|
|
46970
|
-
failWriteValidation3(`${
|
|
46979
|
+
failWriteValidation3(`${path58} needs a header row and at least one data row`);
|
|
46971
46980
|
}
|
|
46972
46981
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
46973
46982
|
const rows = [];
|
|
@@ -46986,7 +46995,7 @@ function parseListFileArg(path57, maxRows) {
|
|
|
46986
46995
|
}
|
|
46987
46996
|
}
|
|
46988
46997
|
if (rows.length > maxRows) {
|
|
46989
|
-
failWriteValidation3(`${
|
|
46998
|
+
failWriteValidation3(`${path58} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
46990
46999
|
}
|
|
46991
47000
|
return { columns, rows };
|
|
46992
47001
|
}
|
|
@@ -47082,11 +47091,11 @@ function readPositionals(args8) {
|
|
|
47082
47091
|
function splitIdList(raw) {
|
|
47083
47092
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
47084
47093
|
}
|
|
47085
|
-
function idsFileEntries(
|
|
47086
|
-
if (typeof
|
|
47094
|
+
function idsFileEntries(path58) {
|
|
47095
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
47087
47096
|
return [];
|
|
47088
47097
|
}
|
|
47089
|
-
return readFileSync7(
|
|
47098
|
+
return readFileSync7(path58, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
47090
47099
|
}
|
|
47091
47100
|
function requireTargets2(args8, entity) {
|
|
47092
47101
|
const positionals = readPositionals(args8);
|
|
@@ -49847,9 +49856,9 @@ import { defineCommand as defineCommand64 } from "citty";
|
|
|
49847
49856
|
function asRecord(value2) {
|
|
49848
49857
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? value2 : void 0;
|
|
49849
49858
|
}
|
|
49850
|
-
function readPath2(row,
|
|
49859
|
+
function readPath2(row, path58) {
|
|
49851
49860
|
let current = row;
|
|
49852
|
-
for (const segment of
|
|
49861
|
+
for (const segment of path58.split(".")) {
|
|
49853
49862
|
const record = asRecord(current);
|
|
49854
49863
|
if (!record) return void 0;
|
|
49855
49864
|
current = record[segment];
|
|
@@ -49859,10 +49868,10 @@ function readPath2(row, path57) {
|
|
|
49859
49868
|
function projectFields(rows, paths) {
|
|
49860
49869
|
return rows.map((row) => {
|
|
49861
49870
|
const projected = {};
|
|
49862
|
-
for (const
|
|
49863
|
-
const value2 = readPath2(row,
|
|
49871
|
+
for (const path58 of paths) {
|
|
49872
|
+
const value2 = readPath2(row, path58);
|
|
49864
49873
|
if (value2 !== void 0) {
|
|
49865
|
-
projected[
|
|
49874
|
+
projected[path58] = value2;
|
|
49866
49875
|
}
|
|
49867
49876
|
}
|
|
49868
49877
|
return projected;
|
|
@@ -49875,16 +49884,16 @@ function shapeListRows(rows, args8, compact5) {
|
|
|
49875
49884
|
const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
|
|
49876
49885
|
if (paths.length > 0) {
|
|
49877
49886
|
const projected = projectFields(raw, paths).map((row, i) => {
|
|
49878
|
-
const missing = paths.filter((
|
|
49887
|
+
const missing = paths.filter((path58) => row[path58] === void 0);
|
|
49879
49888
|
const source = rows[i];
|
|
49880
49889
|
if (missing.length === 0 || source === void 0) return row;
|
|
49881
49890
|
const compactRow3 = compact5.row(source);
|
|
49882
|
-
for (const
|
|
49883
|
-
if (compactRow3[
|
|
49891
|
+
for (const path58 of missing) {
|
|
49892
|
+
if (compactRow3[path58] !== void 0) row[path58] = compactRow3[path58];
|
|
49884
49893
|
}
|
|
49885
49894
|
return row;
|
|
49886
49895
|
});
|
|
49887
|
-
const unmatched = paths.filter((
|
|
49896
|
+
const unmatched = paths.filter((path58) => projected.every((row) => row[path58] === void 0));
|
|
49888
49897
|
if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
|
|
49889
49898
|
const carried = /* @__PURE__ */ new Set([...compact5.columns, ...raw.flatMap((row) => Object.keys(row))]);
|
|
49890
49899
|
return {
|
|
@@ -51244,54 +51253,54 @@ function ruleFields(node) {
|
|
|
51244
51253
|
([key, value2]) => (key === "and" || key === "or") && Array.isArray(value2) ? value2.flatMap(ruleFields) : [key]
|
|
51245
51254
|
);
|
|
51246
51255
|
}
|
|
51247
|
-
function branchRefusal(key, value2,
|
|
51256
|
+
function branchRefusal(key, value2, path58) {
|
|
51248
51257
|
if (!Array.isArray(value2) || value2.length === 0) {
|
|
51249
|
-
return `${
|
|
51258
|
+
return `${path58}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
51250
51259
|
}
|
|
51251
51260
|
for (const [index, child] of value2.entries()) {
|
|
51252
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
51261
|
+
const refusal = ruleNodeRefusal(child, `${path58}.${key}[${index}]`);
|
|
51253
51262
|
if (refusal) {
|
|
51254
51263
|
return refusal;
|
|
51255
51264
|
}
|
|
51256
51265
|
}
|
|
51257
51266
|
return void 0;
|
|
51258
51267
|
}
|
|
51259
|
-
function conditionRefusal(key, value2,
|
|
51260
|
-
return key === "and" || key === "or" ? branchRefusal(key, value2,
|
|
51268
|
+
function conditionRefusal(key, value2, path58) {
|
|
51269
|
+
return key === "and" || key === "or" ? branchRefusal(key, value2, path58) : leafRefusal(key, value2, path58);
|
|
51261
51270
|
}
|
|
51262
|
-
function ruleNodeRefusal(node,
|
|
51271
|
+
function ruleNodeRefusal(node, path58) {
|
|
51263
51272
|
if (!isRecord2(node)) {
|
|
51264
|
-
return `${
|
|
51273
|
+
return `${path58} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
51265
51274
|
}
|
|
51266
51275
|
const entries = Object.entries(node);
|
|
51267
51276
|
if (entries.length === 0) {
|
|
51268
|
-
return `${
|
|
51277
|
+
return `${path58} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
51269
51278
|
}
|
|
51270
51279
|
if (entries.length > 1) {
|
|
51271
|
-
return `${
|
|
51280
|
+
return `${path58} 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]}`;
|
|
51272
51281
|
}
|
|
51273
51282
|
for (const [key, value2] of entries) {
|
|
51274
|
-
const refusal = conditionRefusal(key, value2,
|
|
51283
|
+
const refusal = conditionRefusal(key, value2, path58);
|
|
51275
51284
|
if (refusal) {
|
|
51276
51285
|
return refusal;
|
|
51277
51286
|
}
|
|
51278
51287
|
}
|
|
51279
51288
|
return void 0;
|
|
51280
51289
|
}
|
|
51281
|
-
function leafRefusal(field, condition,
|
|
51290
|
+
function leafRefusal(field, condition, path58) {
|
|
51282
51291
|
if (!isRecord2(condition)) {
|
|
51283
|
-
return `${
|
|
51292
|
+
return `${path58}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
51284
51293
|
}
|
|
51285
51294
|
const tests = Object.entries(condition);
|
|
51286
51295
|
if (tests.length === 0) {
|
|
51287
|
-
return `${
|
|
51296
|
+
return `${path58}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
51288
51297
|
}
|
|
51289
51298
|
if (tests.length > 1) {
|
|
51290
|
-
return `${
|
|
51299
|
+
return `${path58}.${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]}`;
|
|
51291
51300
|
}
|
|
51292
51301
|
for (const [operator] of tests) {
|
|
51293
51302
|
if (!RULE_OPERATORS[operator]) {
|
|
51294
|
-
return `${
|
|
51303
|
+
return `${path58}.${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)`;
|
|
51295
51304
|
}
|
|
51296
51305
|
}
|
|
51297
51306
|
return void 0;
|
|
@@ -52007,11 +52016,11 @@ var updateStatusSchema2 = z45.enum(UPDATE_STATUSES);
|
|
|
52007
52016
|
function currencyMinimums2(currencyCode) {
|
|
52008
52017
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
52009
52018
|
}
|
|
52010
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
52019
|
+
function validateDailyBudgetFloor(money, ctx, path58) {
|
|
52011
52020
|
if (money?.currencyCode) {
|
|
52012
52021
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
52013
52022
|
if (Number(money.amount) < min) {
|
|
52014
|
-
ctx.addIssue({ code: "custom", path:
|
|
52023
|
+
ctx.addIssue({ code: "custom", path: path58, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
52015
52024
|
}
|
|
52016
52025
|
}
|
|
52017
52026
|
}
|
|
@@ -52929,19 +52938,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
52929
52938
|
);
|
|
52930
52939
|
}
|
|
52931
52940
|
}
|
|
52932
|
-
function loadJsonFileArg3(
|
|
52933
|
-
if (typeof
|
|
52941
|
+
function loadJsonFileArg3(path58) {
|
|
52942
|
+
if (typeof path58 !== "string" || path58.length === 0) {
|
|
52934
52943
|
return {};
|
|
52935
52944
|
}
|
|
52936
52945
|
try {
|
|
52937
|
-
const parsed = JSON.parse(readFileSync11(
|
|
52946
|
+
const parsed = JSON.parse(readFileSync11(path58, "utf8"));
|
|
52938
52947
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
52939
|
-
failWriteValidation4(`${
|
|
52948
|
+
failWriteValidation4(`${path58} must contain a JSON object`);
|
|
52940
52949
|
}
|
|
52941
52950
|
return parsed;
|
|
52942
52951
|
} catch (err) {
|
|
52943
52952
|
if (err instanceof SyntaxError) {
|
|
52944
|
-
failWriteValidation4(`${
|
|
52953
|
+
failWriteValidation4(`${path58} is not valid JSON: ${err.message}`);
|
|
52945
52954
|
}
|
|
52946
52955
|
throw err;
|
|
52947
52956
|
}
|
|
@@ -58712,12 +58721,12 @@ function flowExists(slug) {
|
|
|
58712
58721
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
58713
58722
|
}
|
|
58714
58723
|
function readFlowTree(slug) {
|
|
58715
|
-
const
|
|
58716
|
-
if (!existsSync3(
|
|
58724
|
+
const path58 = join2(flowsDir(), slug, "_data.json");
|
|
58725
|
+
if (!existsSync3(path58)) {
|
|
58717
58726
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
58718
58727
|
}
|
|
58719
58728
|
try {
|
|
58720
|
-
return JSON.parse(readFileSync13(
|
|
58729
|
+
return JSON.parse(readFileSync13(path58, "utf-8"));
|
|
58721
58730
|
} catch (error) {
|
|
58722
58731
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
58723
58732
|
}
|
|
@@ -59677,12 +59686,12 @@ function readPeopleFile(args8) {
|
|
|
59677
59686
|
}
|
|
59678
59687
|
function unreadablePeopleFile(args8) {
|
|
59679
59688
|
if (!args8["people-file"]) return void 0;
|
|
59680
|
-
const
|
|
59689
|
+
const path58 = String(args8["people-file"]);
|
|
59681
59690
|
try {
|
|
59682
|
-
readFileSync14(
|
|
59691
|
+
readFileSync14(path58, "utf8");
|
|
59683
59692
|
return void 0;
|
|
59684
59693
|
} catch {
|
|
59685
|
-
return `Couldn't read --people-file ${
|
|
59694
|
+
return `Couldn't read --people-file ${path58}. Check the path, or pass the people inline with --person.`;
|
|
59686
59695
|
}
|
|
59687
59696
|
}
|
|
59688
59697
|
function peopleLimitError(args8) {
|
|
@@ -60654,11 +60663,11 @@ function parseFieldArgs(argv) {
|
|
|
60654
60663
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
60655
60664
|
const eq = pair.indexOf("=");
|
|
60656
60665
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
60657
|
-
const
|
|
60666
|
+
const path58 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
60658
60667
|
const problem = mappingRowProblem(field);
|
|
60659
60668
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
60660
|
-
if (
|
|
60661
|
-
mapping[field] =
|
|
60669
|
+
if (path58 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
60670
|
+
mapping[field] = path58;
|
|
60662
60671
|
}
|
|
60663
60672
|
return mapping;
|
|
60664
60673
|
}
|
|
@@ -62260,11 +62269,11 @@ function unwrap(response) {
|
|
|
62260
62269
|
}
|
|
62261
62270
|
return response.data;
|
|
62262
62271
|
}
|
|
62263
|
-
async function readAvatars(
|
|
62264
|
-
return unwrap(await apiGet(
|
|
62272
|
+
async function readAvatars(path58, params) {
|
|
62273
|
+
return unwrap(await apiGet(path58, params));
|
|
62265
62274
|
}
|
|
62266
|
-
async function writeAvatars(
|
|
62267
|
-
return unwrap(await apiPost(
|
|
62275
|
+
async function writeAvatars(path58, body) {
|
|
62276
|
+
return unwrap(await apiPost(path58, body));
|
|
62268
62277
|
}
|
|
62269
62278
|
|
|
62270
62279
|
// src/commands/avatars/create.ts
|
|
@@ -63173,12 +63182,12 @@ function missingFontFiles(urls, available) {
|
|
|
63173
63182
|
function planFontAdoption(sources, families) {
|
|
63174
63183
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
63175
63184
|
const byFamily = /* @__PURE__ */ new Map();
|
|
63176
|
-
for (const { path:
|
|
63177
|
-
const dir = posix.dirname(
|
|
63185
|
+
for (const { path: path58, source } of sources) {
|
|
63186
|
+
const dir = posix.dirname(path58);
|
|
63178
63187
|
for (const face of declaredFontFaces(source)) {
|
|
63179
63188
|
if (!wanted.has(face.family)) continue;
|
|
63180
63189
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
63181
|
-
perFile.set(
|
|
63190
|
+
perFile.set(path58, [...perFile.get(path58) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
63182
63191
|
byFamily.set(face.family, perFile);
|
|
63183
63192
|
}
|
|
63184
63193
|
}
|
|
@@ -71764,8 +71773,8 @@ function extensionPrompt(format, legend, hasElementRefs) {
|
|
|
71764
71773
|
"{{plate_spec}}"
|
|
71765
71774
|
].join("\n");
|
|
71766
71775
|
}
|
|
71767
|
-
function ingestNode(id,
|
|
71768
|
-
return { id, type: "ingest", params: { source: "path", path:
|
|
71776
|
+
function ingestNode(id, path58, expect) {
|
|
71777
|
+
return { id, type: "ingest", params: { source: "path", path: path58, expect } };
|
|
71769
71778
|
}
|
|
71770
71779
|
function annotateBlueprintWithLabels(blueprintInput, elementsInput) {
|
|
71771
71780
|
if (!blueprintInput || typeof blueprintInput !== "object") return blueprintInput;
|
|
@@ -78685,10 +78694,10 @@ function parseValueExpression(raw) {
|
|
|
78685
78694
|
return parts.map(parsePart);
|
|
78686
78695
|
}
|
|
78687
78696
|
function trackingFieldIds() {
|
|
78688
|
-
const
|
|
78689
|
-
if (!existsSync9(
|
|
78697
|
+
const path58 = join4(flowsDir(), "..", "tracking.ts");
|
|
78698
|
+
if (!existsSync9(path58)) return null;
|
|
78690
78699
|
try {
|
|
78691
|
-
const source = readFileSync17(
|
|
78700
|
+
const source = readFileSync17(path58, "utf-8");
|
|
78692
78701
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
78693
78702
|
if (!block2) return null;
|
|
78694
78703
|
const ids2 = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -79270,13 +79279,13 @@ function specsFromFile(parsed) {
|
|
|
79270
79279
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
79271
79280
|
});
|
|
79272
79281
|
}
|
|
79273
|
-
function readSpecFile(
|
|
79282
|
+
function readSpecFile(path58) {
|
|
79274
79283
|
let raw;
|
|
79275
79284
|
try {
|
|
79276
|
-
raw =
|
|
79285
|
+
raw = path58 === "-" ? readFileSync18(0, "utf-8") : readFileSync18(path58, "utf-8");
|
|
79277
79286
|
} catch (error) {
|
|
79278
79287
|
refuse(
|
|
79279
|
-
`Could not read ${
|
|
79288
|
+
`Could not read ${path58 === "-" ? "the mapping from stdin" : `"${path58}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
79280
79289
|
);
|
|
79281
79290
|
}
|
|
79282
79291
|
let parsed;
|
|
@@ -79284,7 +79293,7 @@ function readSpecFile(path57) {
|
|
|
79284
79293
|
parsed = JSON.parse(raw);
|
|
79285
79294
|
} catch (error) {
|
|
79286
79295
|
refuse(
|
|
79287
|
-
`${
|
|
79296
|
+
`${path58 === "-" ? "stdin" : `"${path58}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
79288
79297
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
79289
79298
|
);
|
|
79290
79299
|
}
|
|
@@ -79583,21 +79592,21 @@ var ARRAY_FIELDS = [
|
|
|
79583
79592
|
"tagIds"
|
|
79584
79593
|
];
|
|
79585
79594
|
var ARRAY_OWNERS = ["", "body"];
|
|
79586
|
-
function dropUnsetOptionals(sideEffect,
|
|
79595
|
+
function dropUnsetOptionals(sideEffect, path58) {
|
|
79587
79596
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
79588
79597
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
79589
79598
|
delete sideEffect[key];
|
|
79590
|
-
return [{ path:
|
|
79599
|
+
return [{ path: path58, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
79591
79600
|
});
|
|
79592
79601
|
}
|
|
79593
|
-
function fillNulledArrays(target2, prefix,
|
|
79602
|
+
function fillNulledArrays(target2, prefix, path58) {
|
|
79594
79603
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
79595
79604
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
79596
79605
|
target2[key] = [];
|
|
79597
|
-
return [{ path:
|
|
79606
|
+
return [{ path: path58, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
79598
79607
|
});
|
|
79599
79608
|
}
|
|
79600
|
-
function tidyEmailRecipients(sideEffect,
|
|
79609
|
+
function tidyEmailRecipients(sideEffect, path58) {
|
|
79601
79610
|
if (sideEffect.type !== "email") return [];
|
|
79602
79611
|
const config = sideEffect.encryptedConfig;
|
|
79603
79612
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -79608,7 +79617,7 @@ function tidyEmailRecipients(sideEffect, path57) {
|
|
|
79608
79617
|
const tidied = to.join(", ");
|
|
79609
79618
|
if (tidied === raw) return [];
|
|
79610
79619
|
config.email = tidied;
|
|
79611
|
-
return [{ path:
|
|
79620
|
+
return [{ path: path58, change: "tidied the recipient list's spacing and separators" }];
|
|
79612
79621
|
}
|
|
79613
79622
|
function sideEffectsOf(node) {
|
|
79614
79623
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -79617,13 +79626,13 @@ function sideEffectsOf(node) {
|
|
|
79617
79626
|
);
|
|
79618
79627
|
}
|
|
79619
79628
|
function normalizeSideEffect(sideEffect, where) {
|
|
79620
|
-
const
|
|
79629
|
+
const path58 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
79621
79630
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
79622
79631
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
79623
79632
|
if (!target2 || typeof target2 !== "object") return [];
|
|
79624
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
79633
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path58);
|
|
79625
79634
|
});
|
|
79626
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
79635
|
+
return [...dropUnsetOptionals(sideEffect, path58), ...arrays, ...tidyEmailRecipients(sideEffect, path58)];
|
|
79627
79636
|
}
|
|
79628
79637
|
function normalizeFlowTree(tree) {
|
|
79629
79638
|
const changes = [];
|
|
@@ -81015,10 +81024,10 @@ async function stageOps(ops) {
|
|
|
81015
81024
|
handleError5(err);
|
|
81016
81025
|
}
|
|
81017
81026
|
}
|
|
81018
|
-
async function draftAction2(
|
|
81027
|
+
async function draftAction2(path58, body, chat) {
|
|
81019
81028
|
const chatId = resolveChatId(chat);
|
|
81020
81029
|
try {
|
|
81021
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
81030
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path58, { chatId, ...body }));
|
|
81022
81031
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
81023
81032
|
return data;
|
|
81024
81033
|
} catch (err) {
|
|
@@ -83548,9 +83557,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
83548
83557
|
}
|
|
83549
83558
|
return readFile37(pathOrUrl);
|
|
83550
83559
|
}
|
|
83551
|
-
async function isDirectory(
|
|
83560
|
+
async function isDirectory(path58) {
|
|
83552
83561
|
try {
|
|
83553
|
-
const s = await stat8(
|
|
83562
|
+
const s = await stat8(path58);
|
|
83554
83563
|
return s.isDirectory();
|
|
83555
83564
|
} catch {
|
|
83556
83565
|
return false;
|
|
@@ -83978,13 +83987,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
83978
83987
|
}
|
|
83979
83988
|
function disambiguate(paths) {
|
|
83980
83989
|
const taken = /* @__PURE__ */ new Set();
|
|
83981
|
-
return paths.map((
|
|
83982
|
-
if (!taken.has(
|
|
83983
|
-
taken.add(
|
|
83984
|
-
return
|
|
83990
|
+
return paths.map((path58) => {
|
|
83991
|
+
if (!taken.has(path58)) {
|
|
83992
|
+
taken.add(path58);
|
|
83993
|
+
return path58;
|
|
83985
83994
|
}
|
|
83986
|
-
const ext = extname4(
|
|
83987
|
-
const stem =
|
|
83995
|
+
const ext = extname4(path58);
|
|
83996
|
+
const stem = path58.slice(0, path58.length - ext.length);
|
|
83988
83997
|
let n = 2;
|
|
83989
83998
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
83990
83999
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -84110,10 +84119,10 @@ async function runDownloads(plan) {
|
|
|
84110
84119
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
84111
84120
|
const downloaded = [];
|
|
84112
84121
|
for (const [index, item] of fetched.entries()) {
|
|
84113
|
-
const
|
|
84122
|
+
const path58 = paths[index] ?? item.path;
|
|
84114
84123
|
try {
|
|
84115
|
-
await atomicWrite(
|
|
84116
|
-
downloaded.push({ input: item.input, output:
|
|
84124
|
+
await atomicWrite(path58, item.buffer);
|
|
84125
|
+
downloaded.push({ input: item.input, output: path58, bytes: item.buffer.length, contentType: item.contentType });
|
|
84117
84126
|
} catch (err) {
|
|
84118
84127
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
84119
84128
|
}
|
|
@@ -92300,11 +92309,365 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
|
92300
92309
|
}
|
|
92301
92310
|
});
|
|
92302
92311
|
|
|
92312
|
+
// src/commands/media-sources/index.ts
|
|
92313
|
+
import { defineCommand as defineCommand214 } from "citty";
|
|
92314
|
+
|
|
92315
|
+
// ../api/src/media-sources.ts
|
|
92316
|
+
import { z as z64 } from "zod";
|
|
92317
|
+
var mediaSourcePlatformSchema = z64.enum([
|
|
92318
|
+
"instagram",
|
|
92319
|
+
"tiktok",
|
|
92320
|
+
"youtube",
|
|
92321
|
+
"linkedin",
|
|
92322
|
+
"facebook",
|
|
92323
|
+
"google_drive"
|
|
92324
|
+
]);
|
|
92325
|
+
var mediaSourceRefreshIntervalSchema = z64.enum(["never", "daily", "weekly", "monthly"]);
|
|
92326
|
+
var mediaSourceSyncStatusSchema = z64.enum(["idle", "fetching", "processing", "error"]);
|
|
92327
|
+
var mediaSourceHalfSchema = z64.object({
|
|
92328
|
+
sourceId: z64.string(),
|
|
92329
|
+
syncStatus: mediaSourceSyncStatusSchema,
|
|
92330
|
+
storedCount: z64.number().optional(),
|
|
92331
|
+
pendingItems: z64.number().optional(),
|
|
92332
|
+
failedItems: z64.number().optional(),
|
|
92333
|
+
lastSyncedAt: z64.number().optional(),
|
|
92334
|
+
errorMessage: z64.string().optional()
|
|
92335
|
+
});
|
|
92336
|
+
var mediaSourceSummarySchema = z64.object({
|
|
92337
|
+
key: z64.string(),
|
|
92338
|
+
platform: mediaSourcePlatformSchema,
|
|
92339
|
+
platformLabel: z64.string(),
|
|
92340
|
+
handle: z64.string(),
|
|
92341
|
+
label: z64.string(),
|
|
92342
|
+
profileUrl: z64.string(),
|
|
92343
|
+
profileImageUrl: z64.string().optional(),
|
|
92344
|
+
refreshInterval: mediaSourceRefreshIntervalSchema,
|
|
92345
|
+
/** Absent for a platform that feeds no images (YouTube). */
|
|
92346
|
+
images: mediaSourceHalfSchema.optional(),
|
|
92347
|
+
videos: mediaSourceHalfSchema.optional(),
|
|
92348
|
+
createdAt: z64.number()
|
|
92349
|
+
});
|
|
92350
|
+
var mediaSourceProfileSchema = z64.object({
|
|
92351
|
+
platform: mediaSourcePlatformSchema,
|
|
92352
|
+
handle: z64.string(),
|
|
92353
|
+
displayName: z64.string(),
|
|
92354
|
+
avatarUrl: z64.string(),
|
|
92355
|
+
bio: z64.string(),
|
|
92356
|
+
followers: z64.number().optional(),
|
|
92357
|
+
postCount: z64.number().optional(),
|
|
92358
|
+
isPrivate: z64.boolean(),
|
|
92359
|
+
profileUrl: z64.string(),
|
|
92360
|
+
channelId: z64.string().optional()
|
|
92361
|
+
});
|
|
92362
|
+
var mediaSourcesAddRequestSchema = z64.object({
|
|
92363
|
+
/** A profile URL or a Drive folder link, or an @handle together with `platform`. */
|
|
92364
|
+
input: z64.string().trim().min(1, "Pass the account's profile URL or @handle"),
|
|
92365
|
+
/** Needed only when `input` is a bare handle; a URL names its own platform. */
|
|
92366
|
+
platform: mediaSourcePlatformSchema.optional(),
|
|
92367
|
+
/** Auto-sync cadence. Omitted = weekly, for every platform. */
|
|
92368
|
+
every: mediaSourceRefreshIntervalSchema.optional()
|
|
92369
|
+
});
|
|
92370
|
+
var mediaSourceKeySchema = z64.string().trim().regex(/^(instagram|tiktok|youtube|linkedin|facebook|google_drive):.+$/, "Pass a source key like tiktok:nike");
|
|
92371
|
+
var mediaSourcesSyncRequestSchema = z64.object({ key: mediaSourceKeySchema });
|
|
92372
|
+
var mediaSourcesRemoveRequestSchema = z64.object({ key: mediaSourceKeySchema });
|
|
92373
|
+
var mediaSourcesScheduleRequestSchema = z64.object({
|
|
92374
|
+
key: mediaSourceKeySchema,
|
|
92375
|
+
every: mediaSourceRefreshIntervalSchema
|
|
92376
|
+
});
|
|
92377
|
+
|
|
92378
|
+
// src/commands/media-sources/add.ts
|
|
92379
|
+
import { defineCommand as defineCommand209 } from "citty";
|
|
92380
|
+
|
|
92381
|
+
// src/commands/media-sources/shared.ts
|
|
92382
|
+
function driveRefusalFix(input, code) {
|
|
92383
|
+
if (!/drive\.google\.com/i.test(input) || code !== "BAD_REQUEST") return void 0;
|
|
92384
|
+
return `A Google Drive folder is never added by link \u2014 don't retry. Call request_connection with platform "google-drive" and choose "media-folder": the card lets the user pick the folder in the chat (only the Baker team can for now; anyone else is told the team will set it up). A connected result carries the new source's mediaSourceKey; if it is declined, carry on with the rest of the task.`;
|
|
92385
|
+
}
|
|
92386
|
+
function reportError2(err, input) {
|
|
92387
|
+
if (err instanceof ApiError) {
|
|
92388
|
+
const fix = input ? driveRefusalFix(input, err.code) : void 0;
|
|
92389
|
+
writeJson({ ok: false, error: { code: err.code, message: err.message, ...fix ? { fix } : {} } });
|
|
92390
|
+
process.exit(1);
|
|
92391
|
+
}
|
|
92392
|
+
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
92393
|
+
process.exit(1);
|
|
92394
|
+
}
|
|
92395
|
+
function halfState(half) {
|
|
92396
|
+
if (!half) return null;
|
|
92397
|
+
return {
|
|
92398
|
+
status: half.syncStatus === "fetching" || half.syncStatus === "processing" ? "importing" : half.syncStatus,
|
|
92399
|
+
stored: half.storedCount ?? 0,
|
|
92400
|
+
...half.pendingItems ? { pending: half.pendingItems } : {},
|
|
92401
|
+
...half.failedItems ? { failed: half.failedItems } : {},
|
|
92402
|
+
...half.lastSyncedAt ? { lastSyncedAt: new Date(half.lastSyncedAt).toISOString() } : {},
|
|
92403
|
+
...half.errorMessage ? { error: half.errorMessage } : {}
|
|
92404
|
+
};
|
|
92405
|
+
}
|
|
92406
|
+
function compactSource(source) {
|
|
92407
|
+
return {
|
|
92408
|
+
key: source.key,
|
|
92409
|
+
platform: source.platform,
|
|
92410
|
+
label: source.label,
|
|
92411
|
+
url: source.profileUrl,
|
|
92412
|
+
autoSync: source.refreshInterval,
|
|
92413
|
+
images: halfState(source.images),
|
|
92414
|
+
videos: halfState(source.videos)
|
|
92415
|
+
};
|
|
92416
|
+
}
|
|
92417
|
+
function isImporting(source) {
|
|
92418
|
+
return [source.images, source.videos].some(
|
|
92419
|
+
(half) => half?.syncStatus === "fetching" || half?.syncStatus === "processing"
|
|
92420
|
+
);
|
|
92421
|
+
}
|
|
92422
|
+
|
|
92423
|
+
// src/commands/media-sources/add.ts
|
|
92424
|
+
registerSchema({
|
|
92425
|
+
command: "media-sources.add",
|
|
92426
|
+
description: "Connect a public social account as a source for the image and video libraries \u2014 Instagram, TikTok, YouTube (videos only), LinkedIn company pages, Facebook pages. Its recent posts (up to a year back) are imported. A Google Drive folder is not added here: ask for it with request_connection (platform google-drive, choose media-folder) and the user picks it in the chat. Everything is described and made searchable in the background. Applies immediately and shows on the chat as an already-applied change. Adding a source that is already connected is a no-op.",
|
|
92427
|
+
args: {
|
|
92428
|
+
input: {
|
|
92429
|
+
type: "string",
|
|
92430
|
+
description: "Profile URL (names its own platform), or @handle together with --platform",
|
|
92431
|
+
required: true
|
|
92432
|
+
},
|
|
92433
|
+
platform: {
|
|
92434
|
+
type: "string",
|
|
92435
|
+
description: `Needed only for a bare handle: ${mediaSourcePlatformSchema.options.join("|")}`,
|
|
92436
|
+
required: false
|
|
92437
|
+
},
|
|
92438
|
+
every: {
|
|
92439
|
+
type: "string",
|
|
92440
|
+
description: `Auto-sync cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (default weekly for every source)`,
|
|
92441
|
+
required: false
|
|
92442
|
+
}
|
|
92443
|
+
}
|
|
92444
|
+
});
|
|
92445
|
+
var addCommand3 = defineCommand209({
|
|
92446
|
+
meta: {
|
|
92447
|
+
name: "add",
|
|
92448
|
+
description: "Connect a social account (Instagram, TikTok, YouTube, LinkedIn page, Facebook page) as a media source. Start here with the profile URL. A Google Drive folder is never added by link: call request_connection with platform google-drive and choose media-folder, and the user picks the folder in the chat.\n\nExamples:\n baker media-sources add https://www.tiktok.com/@acme\n baker media-sources add @acme --platform instagram --every daily"
|
|
92449
|
+
},
|
|
92450
|
+
args: {
|
|
92451
|
+
input: { type: "positional", description: "Profile URL or @handle", required: true },
|
|
92452
|
+
platform: {
|
|
92453
|
+
type: "string",
|
|
92454
|
+
description: "instagram|tiktok|youtube|linkedin|facebook \u2014 only for a bare handle",
|
|
92455
|
+
required: false
|
|
92456
|
+
},
|
|
92457
|
+
every: { type: "string", description: "Auto-sync: never|daily|weekly|monthly", required: false }
|
|
92458
|
+
},
|
|
92459
|
+
run: async ({ args: args8 }) => {
|
|
92460
|
+
const parsed = mediaSourcesAddRequestSchema.safeParse({
|
|
92461
|
+
input: String(args8.input ?? ""),
|
|
92462
|
+
platform: args8.platform ? String(args8.platform).toLowerCase() : void 0,
|
|
92463
|
+
every: args8.every ? String(args8.every).toLowerCase() : void 0
|
|
92464
|
+
});
|
|
92465
|
+
if (!parsed.success) {
|
|
92466
|
+
const issue = parsed.error.issues[0];
|
|
92467
|
+
writeJson({
|
|
92468
|
+
ok: false,
|
|
92469
|
+
error: {
|
|
92470
|
+
code: "VALIDATION_ERROR",
|
|
92471
|
+
message: issue ? `${issue.path.join(".") || "input"}: ${issue.message}` : "Invalid request"
|
|
92472
|
+
}
|
|
92473
|
+
});
|
|
92474
|
+
process.exit(1);
|
|
92475
|
+
}
|
|
92476
|
+
try {
|
|
92477
|
+
const data = await apiPost("/api/media-sources/add", parsed.data, {
|
|
92478
|
+
timeoutMs: 12e4
|
|
92479
|
+
});
|
|
92480
|
+
const hints2 = [
|
|
92481
|
+
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.`
|
|
92482
|
+
];
|
|
92483
|
+
if (data.source.platform === "youtube") {
|
|
92484
|
+
hints2.push(
|
|
92485
|
+
"YouTube feeds the video library only, newest first, a batch per sync; videos over 20 minutes are skipped."
|
|
92486
|
+
);
|
|
92487
|
+
}
|
|
92488
|
+
if (data.source.refreshInterval === "never") {
|
|
92489
|
+
hints2.push(
|
|
92490
|
+
`Auto-sync is off. If the user wants new posts to keep arriving: \`baker media-sources schedule ${data.source.key} --every weekly\`.`
|
|
92491
|
+
);
|
|
92492
|
+
}
|
|
92493
|
+
writeJson({
|
|
92494
|
+
ok: true,
|
|
92495
|
+
data: { created: data.created, source: compactSource(data.source), name: data.profile.displayName },
|
|
92496
|
+
hints: hints2
|
|
92497
|
+
});
|
|
92498
|
+
} catch (err) {
|
|
92499
|
+
reportError2(err, parsed.data.input);
|
|
92500
|
+
}
|
|
92501
|
+
}
|
|
92502
|
+
});
|
|
92503
|
+
|
|
92504
|
+
// src/commands/media-sources/list.ts
|
|
92505
|
+
import { defineCommand as defineCommand210 } from "citty";
|
|
92506
|
+
registerSchema({
|
|
92507
|
+
command: "media-sources.list",
|
|
92508
|
+
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.",
|
|
92509
|
+
args: {}
|
|
92510
|
+
});
|
|
92511
|
+
var listCommand18 = defineCommand210({
|
|
92512
|
+
meta: {
|
|
92513
|
+
name: "list",
|
|
92514
|
+
description: "List connected media sources (key, platform, import status, stored images/videos).\n\nExample: baker media-sources list"
|
|
92515
|
+
},
|
|
92516
|
+
args: {},
|
|
92517
|
+
run: async () => {
|
|
92518
|
+
try {
|
|
92519
|
+
const { sources } = await apiGet("/api/media-sources/list");
|
|
92520
|
+
const hints2 = [];
|
|
92521
|
+
if (sources.length === 0) {
|
|
92522
|
+
hints2.push(
|
|
92523
|
+
"No sources connected. Connect the brand's own accounts with `baker media-sources add <profile URL>` to fill the image and video libraries."
|
|
92524
|
+
);
|
|
92525
|
+
} else if (sources.some(isImporting)) {
|
|
92526
|
+
hints2.push("Some sources are still importing \u2014 their counts will grow over the next minutes.");
|
|
92527
|
+
}
|
|
92528
|
+
writeJson({ ok: true, data: sources.map(compactSource), hints: hints2.length > 0 ? hints2 : void 0 });
|
|
92529
|
+
} catch (err) {
|
|
92530
|
+
reportError2(err);
|
|
92531
|
+
}
|
|
92532
|
+
}
|
|
92533
|
+
});
|
|
92534
|
+
|
|
92535
|
+
// src/commands/media-sources/remove.ts
|
|
92536
|
+
import { defineCommand as defineCommand211 } from "citty";
|
|
92537
|
+
registerSchema({
|
|
92538
|
+
command: "media-sources.remove",
|
|
92539
|
+
description: "Disconnect a media source. Stops future imports; images and videos it already brought in stay in the library. Applies immediately.",
|
|
92540
|
+
args: { key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true } }
|
|
92541
|
+
});
|
|
92542
|
+
var removeCommand7 = defineCommand211({
|
|
92543
|
+
meta: {
|
|
92544
|
+
name: "remove",
|
|
92545
|
+
description: "Disconnect a media source (already-imported media stays).\n\nExample: baker media-sources remove tiktok:acme"
|
|
92546
|
+
},
|
|
92547
|
+
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
92548
|
+
run: async ({ args: args8 }) => {
|
|
92549
|
+
const parsed = mediaSourcesRemoveRequestSchema.safeParse({ key: String(args8.key ?? "") });
|
|
92550
|
+
if (!parsed.success) {
|
|
92551
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
92552
|
+
process.exit(1);
|
|
92553
|
+
}
|
|
92554
|
+
try {
|
|
92555
|
+
const data = await apiPost("/api/media-sources/remove", parsed.data);
|
|
92556
|
+
writeJson({ ok: true, data });
|
|
92557
|
+
} catch (err) {
|
|
92558
|
+
reportError2(err);
|
|
92559
|
+
}
|
|
92560
|
+
}
|
|
92561
|
+
});
|
|
92562
|
+
|
|
92563
|
+
// src/commands/media-sources/schedule.ts
|
|
92564
|
+
import { defineCommand as defineCommand212 } from "citty";
|
|
92565
|
+
registerSchema({
|
|
92566
|
+
command: "media-sources.schedule",
|
|
92567
|
+
description: "Set how often a connected source imports new posts on its own.",
|
|
92568
|
+
args: {
|
|
92569
|
+
key: { type: "string", description: "Source key, e.g. tiktok:acme", required: true },
|
|
92570
|
+
every: {
|
|
92571
|
+
type: "string",
|
|
92572
|
+
description: `Cadence: ${mediaSourceRefreshIntervalSchema.options.join("|")} (never = only on demand)`,
|
|
92573
|
+
required: true
|
|
92574
|
+
}
|
|
92575
|
+
}
|
|
92576
|
+
});
|
|
92577
|
+
var scheduleCommand = defineCommand212({
|
|
92578
|
+
meta: {
|
|
92579
|
+
name: "schedule",
|
|
92580
|
+
description: "Set a source's auto-sync cadence.\n\nExample: baker media-sources schedule tiktok:acme --every weekly"
|
|
92581
|
+
},
|
|
92582
|
+
args: {
|
|
92583
|
+
key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true },
|
|
92584
|
+
every: { type: "string", description: "never|daily|weekly|monthly", required: true }
|
|
92585
|
+
},
|
|
92586
|
+
run: async ({ args: args8 }) => {
|
|
92587
|
+
const parsed = mediaSourcesScheduleRequestSchema.safeParse({
|
|
92588
|
+
key: String(args8.key ?? ""),
|
|
92589
|
+
every: String(args8.every ?? "").toLowerCase()
|
|
92590
|
+
});
|
|
92591
|
+
if (!parsed.success) {
|
|
92592
|
+
const issue = parsed.error.issues[0];
|
|
92593
|
+
writeJson({
|
|
92594
|
+
ok: false,
|
|
92595
|
+
error: { code: "VALIDATION_ERROR", message: issue ? `${issue.path.join(".")}: ${issue.message}` : "" }
|
|
92596
|
+
});
|
|
92597
|
+
process.exit(1);
|
|
92598
|
+
}
|
|
92599
|
+
try {
|
|
92600
|
+
const data = await apiPost("/api/media-sources/schedule", parsed.data);
|
|
92601
|
+
writeJson({ ok: true, data: { ...data, autoSync: parsed.data.every } });
|
|
92602
|
+
} catch (err) {
|
|
92603
|
+
reportError2(err);
|
|
92604
|
+
}
|
|
92605
|
+
}
|
|
92606
|
+
});
|
|
92607
|
+
|
|
92608
|
+
// src/commands/media-sources/sync.ts
|
|
92609
|
+
import { defineCommand as defineCommand213 } from "citty";
|
|
92610
|
+
registerSchema({
|
|
92611
|
+
command: "media-sources.sync",
|
|
92612
|
+
description: "Import a connected source's new posts now. Runs in the background; only posts not yet in the library are fetched.",
|
|
92613
|
+
args: {
|
|
92614
|
+
key: { type: "string", description: "Source key from `media-sources list`, e.g. tiktok:acme", required: true }
|
|
92615
|
+
}
|
|
92616
|
+
});
|
|
92617
|
+
var syncCommand = defineCommand213({
|
|
92618
|
+
meta: {
|
|
92619
|
+
name: "sync",
|
|
92620
|
+
description: "Import a source's new posts now.\n\nExample: baker media-sources sync tiktok:acme"
|
|
92621
|
+
},
|
|
92622
|
+
args: { key: { type: "positional", description: "Source key, e.g. tiktok:acme", required: true } },
|
|
92623
|
+
run: async ({ args: args8 }) => {
|
|
92624
|
+
const parsed = mediaSourcesSyncRequestSchema.safeParse({ key: String(args8.key ?? "") });
|
|
92625
|
+
if (!parsed.success) {
|
|
92626
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: parsed.error.issues[0]?.message ?? "" } });
|
|
92627
|
+
process.exit(1);
|
|
92628
|
+
}
|
|
92629
|
+
try {
|
|
92630
|
+
const data = await apiPost("/api/media-sources/sync", parsed.data);
|
|
92631
|
+
writeJson({
|
|
92632
|
+
ok: true,
|
|
92633
|
+
data,
|
|
92634
|
+
hints: data.started ? void 0 : ["An import was already running for this source; nothing new was started."]
|
|
92635
|
+
});
|
|
92636
|
+
} catch (err) {
|
|
92637
|
+
reportError2(err);
|
|
92638
|
+
}
|
|
92639
|
+
}
|
|
92640
|
+
});
|
|
92641
|
+
|
|
92642
|
+
// src/commands/media-sources/index.ts
|
|
92643
|
+
var mediaSourcesCommand = defineCommand214({
|
|
92644
|
+
meta: {
|
|
92645
|
+
name: "media-sources",
|
|
92646
|
+
description: `Connect social accounts whose images and videos fill the libraries: Instagram, TikTok, YouTube (videos), LinkedIn company pages, Facebook pages. A Google Drive folder is picked by the user in the chat (request_connection, platform google-drive, choose media-folder), never added here; once connected, list, sync, schedule and remove manage it like any source. Subcommands: add, list, sync, schedule, remove.
|
|
92647
|
+
|
|
92648
|
+
Examples:
|
|
92649
|
+
baker media-sources add https://www.tiktok.com/@acme
|
|
92650
|
+
baker media-sources add @acme --platform instagram --every daily
|
|
92651
|
+
baker media-sources list
|
|
92652
|
+
baker media-sources sync youtube:acme
|
|
92653
|
+
baker media-sources schedule linkedin:acme --every monthly
|
|
92654
|
+
baker media-sources remove facebook:acme
|
|
92655
|
+
Full guide: __tooling__/docs/tools/baker/media-sources.md`
|
|
92656
|
+
},
|
|
92657
|
+
subCommands: {
|
|
92658
|
+
add: addCommand3,
|
|
92659
|
+
list: listCommand18,
|
|
92660
|
+
sync: syncCommand,
|
|
92661
|
+
schedule: scheduleCommand,
|
|
92662
|
+
remove: removeCommand7
|
|
92663
|
+
}
|
|
92664
|
+
});
|
|
92665
|
+
|
|
92303
92666
|
// src/commands/research/index.ts
|
|
92304
|
-
import { defineCommand as
|
|
92667
|
+
import { defineCommand as defineCommand227 } from "citty";
|
|
92305
92668
|
|
|
92306
92669
|
// src/commands/research/advertisers.ts
|
|
92307
|
-
import { defineCommand as
|
|
92670
|
+
import { defineCommand as defineCommand215 } from "citty";
|
|
92308
92671
|
|
|
92309
92672
|
// src/commands/research/hints.ts
|
|
92310
92673
|
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.';
|
|
@@ -92506,7 +92869,7 @@ var FIELDS3 = {
|
|
|
92506
92869
|
etv: "Estimated traffic value (USD)",
|
|
92507
92870
|
visibility: "SERP visibility score (0-1)"
|
|
92508
92871
|
};
|
|
92509
|
-
var advertisersCommand =
|
|
92872
|
+
var advertisersCommand = defineCommand215({
|
|
92510
92873
|
meta: {
|
|
92511
92874
|
name: "advertisers",
|
|
92512
92875
|
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).
|
|
@@ -92562,7 +92925,7 @@ Examples:
|
|
|
92562
92925
|
});
|
|
92563
92926
|
|
|
92564
92927
|
// src/commands/research/autocomplete.ts
|
|
92565
|
-
import { defineCommand as
|
|
92928
|
+
import { defineCommand as defineCommand216 } from "citty";
|
|
92566
92929
|
registerSchema({
|
|
92567
92930
|
command: "research.autocomplete",
|
|
92568
92931
|
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).",
|
|
@@ -92585,7 +92948,7 @@ registerSchema({
|
|
|
92585
92948
|
var FIELDS4 = {
|
|
92586
92949
|
suggestion: "Autocomplete suggestion from Google"
|
|
92587
92950
|
};
|
|
92588
|
-
var autocompleteCommand =
|
|
92951
|
+
var autocompleteCommand = defineCommand216({
|
|
92589
92952
|
meta: {
|
|
92590
92953
|
name: "autocomplete",
|
|
92591
92954
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -92640,7 +93003,7 @@ Examples:
|
|
|
92640
93003
|
});
|
|
92641
93004
|
|
|
92642
93005
|
// src/commands/research/countries.ts
|
|
92643
|
-
import { defineCommand as
|
|
93006
|
+
import { defineCommand as defineCommand217 } from "citty";
|
|
92644
93007
|
registerSchema({
|
|
92645
93008
|
command: "research.countries",
|
|
92646
93009
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -92697,7 +93060,7 @@ var FIELDS5 = {
|
|
|
92697
93060
|
code: "Country code to pass as --location",
|
|
92698
93061
|
name: "Country name"
|
|
92699
93062
|
};
|
|
92700
|
-
var countriesCommand =
|
|
93063
|
+
var countriesCommand = defineCommand217({
|
|
92701
93064
|
meta: {
|
|
92702
93065
|
name: "countries",
|
|
92703
93066
|
description: "List all supported country codes for --location flag."
|
|
@@ -92708,7 +93071,7 @@ var countriesCommand = defineCommand211({
|
|
|
92708
93071
|
});
|
|
92709
93072
|
|
|
92710
93073
|
// src/commands/research/fetch.ts
|
|
92711
|
-
import { defineCommand as
|
|
93074
|
+
import { defineCommand as defineCommand218 } from "citty";
|
|
92712
93075
|
var CONTENT_PREVIEW_CHARS = 2e4;
|
|
92713
93076
|
var TIMEOUT_MS = 18e4;
|
|
92714
93077
|
registerSchema({
|
|
@@ -92781,7 +93144,7 @@ function fetchFix(code) {
|
|
|
92781
93144
|
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."
|
|
92782
93145
|
};
|
|
92783
93146
|
}
|
|
92784
|
-
var fetchCommand =
|
|
93147
|
+
var fetchCommand = defineCommand218({
|
|
92785
93148
|
meta: {
|
|
92786
93149
|
name: "fetch",
|
|
92787
93150
|
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.
|
|
@@ -92858,7 +93221,7 @@ Examples:
|
|
|
92858
93221
|
});
|
|
92859
93222
|
|
|
92860
93223
|
// src/commands/research/intent.ts
|
|
92861
|
-
import { defineCommand as
|
|
93224
|
+
import { defineCommand as defineCommand219 } from "citty";
|
|
92862
93225
|
registerSchema({
|
|
92863
93226
|
command: "research.intent",
|
|
92864
93227
|
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.",
|
|
@@ -92881,7 +93244,7 @@ var FIELDS7 = {
|
|
|
92881
93244
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
92882
93245
|
probability: "Confidence score 0.0-1.0"
|
|
92883
93246
|
};
|
|
92884
|
-
var intentCommand =
|
|
93247
|
+
var intentCommand = defineCommand219({
|
|
92885
93248
|
meta: {
|
|
92886
93249
|
name: "intent",
|
|
92887
93250
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -92929,7 +93292,7 @@ Examples:
|
|
|
92929
93292
|
});
|
|
92930
93293
|
|
|
92931
93294
|
// src/commands/research/keyword-gap.ts
|
|
92932
|
-
import { defineCommand as
|
|
93295
|
+
import { defineCommand as defineCommand220 } from "citty";
|
|
92933
93296
|
registerSchema({
|
|
92934
93297
|
command: "research.keyword-gap",
|
|
92935
93298
|
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.",
|
|
@@ -92958,7 +93321,7 @@ var FIELDS8 = {
|
|
|
92958
93321
|
cpc: "Cost per click USD",
|
|
92959
93322
|
their_position: "Competitor's ranking position"
|
|
92960
93323
|
};
|
|
92961
|
-
var keywordGapCommand =
|
|
93324
|
+
var keywordGapCommand = defineCommand220({
|
|
92962
93325
|
meta: {
|
|
92963
93326
|
name: "keyword-gap",
|
|
92964
93327
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -93033,7 +93396,7 @@ Examples:
|
|
|
93033
93396
|
});
|
|
93034
93397
|
|
|
93035
93398
|
// src/commands/research/keyword-metrics.ts
|
|
93036
|
-
import { defineCommand as
|
|
93399
|
+
import { defineCommand as defineCommand221 } from "citty";
|
|
93037
93400
|
|
|
93038
93401
|
// src/commands/research/keyword-metrics-rows.ts
|
|
93039
93402
|
var KEYWORD_METRICS_SOURCE = "keyword_planner_estimate_via_dataforseo";
|
|
@@ -93113,7 +93476,7 @@ registerSchema({
|
|
|
93113
93476
|
"no-cache": { type: "boolean", description: "Skip server cache, hit API directly", required: false }
|
|
93114
93477
|
}
|
|
93115
93478
|
});
|
|
93116
|
-
var keywordMetricsCommand =
|
|
93479
|
+
var keywordMetricsCommand = defineCommand221({
|
|
93117
93480
|
meta: {
|
|
93118
93481
|
name: "keyword-metrics",
|
|
93119
93482
|
description: `Volume, CPC and competition for keywords you name. No domain required.
|
|
@@ -93195,7 +93558,7 @@ Examples:
|
|
|
93195
93558
|
});
|
|
93196
93559
|
|
|
93197
93560
|
// src/commands/research/keywords-for-site.ts
|
|
93198
|
-
import { defineCommand as
|
|
93561
|
+
import { defineCommand as defineCommand222 } from "citty";
|
|
93199
93562
|
registerSchema({
|
|
93200
93563
|
command: "research.keywords-for-site",
|
|
93201
93564
|
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.",
|
|
@@ -93228,7 +93591,7 @@ var FIELDS9 = {
|
|
|
93228
93591
|
competition: "LOW, MEDIUM, or HIGH",
|
|
93229
93592
|
competition_index: "Competition score 0-100"
|
|
93230
93593
|
};
|
|
93231
|
-
var keywordsForSiteCommand =
|
|
93594
|
+
var keywordsForSiteCommand = defineCommand222({
|
|
93232
93595
|
meta: {
|
|
93233
93596
|
name: "keywords-for-site",
|
|
93234
93597
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -93290,7 +93653,7 @@ Examples:
|
|
|
93290
93653
|
});
|
|
93291
93654
|
|
|
93292
93655
|
// src/commands/research/languages.ts
|
|
93293
|
-
import { defineCommand as
|
|
93656
|
+
import { defineCommand as defineCommand223 } from "citty";
|
|
93294
93657
|
registerSchema({
|
|
93295
93658
|
command: "research.languages",
|
|
93296
93659
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -93320,7 +93683,7 @@ var FIELDS10 = {
|
|
|
93320
93683
|
code: "Language code to pass as --language",
|
|
93321
93684
|
name: "Language name (also accepted by --language)"
|
|
93322
93685
|
};
|
|
93323
|
-
var languagesCommand2 =
|
|
93686
|
+
var languagesCommand2 = defineCommand223({
|
|
93324
93687
|
meta: {
|
|
93325
93688
|
name: "languages",
|
|
93326
93689
|
description: "List all supported language codes for --language flag."
|
|
@@ -93331,7 +93694,7 @@ var languagesCommand2 = defineCommand217({
|
|
|
93331
93694
|
});
|
|
93332
93695
|
|
|
93333
93696
|
// src/commands/research/lighthouse.ts
|
|
93334
|
-
import { defineCommand as
|
|
93697
|
+
import { defineCommand as defineCommand224 } from "citty";
|
|
93335
93698
|
registerSchema({
|
|
93336
93699
|
command: "research.lighthouse",
|
|
93337
93700
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -93350,7 +93713,7 @@ var FIELDS11 = {
|
|
|
93350
93713
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
93351
93714
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
93352
93715
|
};
|
|
93353
|
-
var lighthouseCommand =
|
|
93716
|
+
var lighthouseCommand = defineCommand224({
|
|
93354
93717
|
meta: {
|
|
93355
93718
|
name: "lighthouse",
|
|
93356
93719
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -93388,7 +93751,7 @@ Examples:
|
|
|
93388
93751
|
});
|
|
93389
93752
|
|
|
93390
93753
|
// src/commands/research/relevant-pages.ts
|
|
93391
|
-
import { defineCommand as
|
|
93754
|
+
import { defineCommand as defineCommand225 } from "citty";
|
|
93392
93755
|
registerSchema({
|
|
93393
93756
|
command: "research.relevant-pages",
|
|
93394
93757
|
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).",
|
|
@@ -93414,7 +93777,7 @@ var FIELDS12 = {
|
|
|
93414
93777
|
keywords: "Total organic keywords the page ranks for",
|
|
93415
93778
|
top_10: "Keywords in positions 1-10"
|
|
93416
93779
|
};
|
|
93417
|
-
var relevantPagesCommand =
|
|
93780
|
+
var relevantPagesCommand = defineCommand225({
|
|
93418
93781
|
meta: {
|
|
93419
93782
|
name: "relevant-pages",
|
|
93420
93783
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -93461,7 +93824,7 @@ Examples:
|
|
|
93461
93824
|
});
|
|
93462
93825
|
|
|
93463
93826
|
// src/commands/research/web.ts
|
|
93464
|
-
import { defineCommand as
|
|
93827
|
+
import { defineCommand as defineCommand226 } from "citty";
|
|
93465
93828
|
registerSchema({
|
|
93466
93829
|
command: "research.web",
|
|
93467
93830
|
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).",
|
|
@@ -93512,7 +93875,7 @@ async function runDeepResearch(question) {
|
|
|
93512
93875
|
}
|
|
93513
93876
|
throw new Error("Deep research timed out");
|
|
93514
93877
|
}
|
|
93515
|
-
var webCommand =
|
|
93878
|
+
var webCommand = defineCommand226({
|
|
93516
93879
|
meta: {
|
|
93517
93880
|
name: "web",
|
|
93518
93881
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -93574,7 +93937,7 @@ Examples:
|
|
|
93574
93937
|
});
|
|
93575
93938
|
|
|
93576
93939
|
// src/commands/research/index.ts
|
|
93577
|
-
var researchCommand =
|
|
93940
|
+
var researchCommand = defineCommand227({
|
|
93578
93941
|
meta: {
|
|
93579
93942
|
name: "research",
|
|
93580
93943
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -93621,10 +93984,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
|
|
|
93621
93984
|
});
|
|
93622
93985
|
|
|
93623
93986
|
// src/commands/scheduled-agents/index.ts
|
|
93624
|
-
import { defineCommand as
|
|
93987
|
+
import { defineCommand as defineCommand238 } from "citty";
|
|
93625
93988
|
|
|
93626
93989
|
// src/commands/scheduled-agents/create.ts
|
|
93627
|
-
import { defineCommand as
|
|
93990
|
+
import { defineCommand as defineCommand228 } from "citty";
|
|
93628
93991
|
|
|
93629
93992
|
// src/commands/scheduled-agents/shared.ts
|
|
93630
93993
|
var TEMP_SCHEDULED_AGENT_PREFIX = "temp_agent_";
|
|
@@ -93991,7 +94354,7 @@ registerSchema({
|
|
|
93991
94354
|
}
|
|
93992
94355
|
}
|
|
93993
94356
|
});
|
|
93994
|
-
var createCommand3 =
|
|
94357
|
+
var createCommand3 = defineCommand228({
|
|
93995
94358
|
meta: {
|
|
93996
94359
|
name: "create",
|
|
93997
94360
|
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'
|
|
@@ -94048,7 +94411,7 @@ var createCommand3 = defineCommand222({
|
|
|
94048
94411
|
});
|
|
94049
94412
|
|
|
94050
94413
|
// src/commands/scheduled-agents/delete.ts
|
|
94051
|
-
import { defineCommand as
|
|
94414
|
+
import { defineCommand as defineCommand229 } from "citty";
|
|
94052
94415
|
registerSchema({
|
|
94053
94416
|
command: "scheduled-agents.delete",
|
|
94054
94417
|
description: "Stage deletion of a published scheduled agent, or cancel one this chat staged (temp_agent_*).",
|
|
@@ -94056,7 +94419,7 @@ registerSchema({
|
|
|
94056
94419
|
id: { type: "string", description: "Published scheduled agent ID or temp_agent_* draft ID", required: true }
|
|
94057
94420
|
}
|
|
94058
94421
|
});
|
|
94059
|
-
var deleteCommand3 =
|
|
94422
|
+
var deleteCommand3 = defineCommand229({
|
|
94060
94423
|
meta: {
|
|
94061
94424
|
name: "delete",
|
|
94062
94425
|
description: "Stage a scheduled agent deletion. Example: baker scheduled-agents delete <id-or-temp_agent_id>"
|
|
@@ -94085,7 +94448,7 @@ var deleteCommand3 = defineCommand223({
|
|
|
94085
94448
|
});
|
|
94086
94449
|
|
|
94087
94450
|
// src/commands/scheduled-agents/get.ts
|
|
94088
|
-
import { defineCommand as
|
|
94451
|
+
import { defineCommand as defineCommand230 } from "citty";
|
|
94089
94452
|
registerSchema({
|
|
94090
94453
|
command: "scheduled-agents.get",
|
|
94091
94454
|
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.",
|
|
@@ -94094,7 +94457,7 @@ registerSchema({
|
|
|
94094
94457
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
94095
94458
|
}
|
|
94096
94459
|
});
|
|
94097
|
-
var getCommand4 =
|
|
94460
|
+
var getCommand4 = defineCommand230({
|
|
94098
94461
|
meta: {
|
|
94099
94462
|
name: "get",
|
|
94100
94463
|
description: "Get a scheduled agent. Example: baker scheduled-agents get <id-or-temp_agent_id>"
|
|
@@ -94133,7 +94496,7 @@ var getCommand4 = defineCommand224({
|
|
|
94133
94496
|
});
|
|
94134
94497
|
|
|
94135
94498
|
// src/commands/scheduled-agents/list.ts
|
|
94136
|
-
import { defineCommand as
|
|
94499
|
+
import { defineCommand as defineCommand231 } from "citty";
|
|
94137
94500
|
var FULL_DESCRIPTION2 = "Return every item and staged change as stored, briefs included (tens of KB). Prefer `get <id>` for one item.";
|
|
94138
94501
|
registerSchema({
|
|
94139
94502
|
command: "scheduled-agents.list",
|
|
@@ -94143,7 +94506,7 @@ registerSchema({
|
|
|
94143
94506
|
full: { type: "boolean", description: FULL_DESCRIPTION2, required: false }
|
|
94144
94507
|
}
|
|
94145
94508
|
});
|
|
94146
|
-
var
|
|
94509
|
+
var listCommand19 = defineCommand231({
|
|
94147
94510
|
meta: {
|
|
94148
94511
|
name: "list",
|
|
94149
94512
|
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."
|
|
@@ -94169,7 +94532,7 @@ var listCommand18 = defineCommand225({
|
|
|
94169
94532
|
});
|
|
94170
94533
|
|
|
94171
94534
|
// src/commands/scheduled-agents/run.ts
|
|
94172
|
-
import { defineCommand as
|
|
94535
|
+
import { defineCommand as defineCommand232 } from "citty";
|
|
94173
94536
|
registerSchema({
|
|
94174
94537
|
command: "scheduled-agents.run",
|
|
94175
94538
|
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.",
|
|
@@ -94177,7 +94540,7 @@ registerSchema({
|
|
|
94177
94540
|
id: { type: "string", description: "Published scheduled agent ID", required: true }
|
|
94178
94541
|
}
|
|
94179
94542
|
});
|
|
94180
|
-
var runCommand2 =
|
|
94543
|
+
var runCommand2 = defineCommand232({
|
|
94181
94544
|
meta: {
|
|
94182
94545
|
name: "run",
|
|
94183
94546
|
description: "Run a published scheduled agent now. Example: baker scheduled-agents run <id>"
|
|
@@ -94209,7 +94572,7 @@ var runCommand2 = defineCommand226({
|
|
|
94209
94572
|
});
|
|
94210
94573
|
|
|
94211
94574
|
// src/commands/scheduled-agents/targets.ts
|
|
94212
|
-
import { defineCommand as
|
|
94575
|
+
import { defineCommand as defineCommand233 } from "citty";
|
|
94213
94576
|
var ARGS9 = {
|
|
94214
94577
|
trigger: {
|
|
94215
94578
|
type: "string",
|
|
@@ -94243,7 +94606,7 @@ registerSchema({
|
|
|
94243
94606
|
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.",
|
|
94244
94607
|
args: ARGS9
|
|
94245
94608
|
});
|
|
94246
|
-
var targetsCommand =
|
|
94609
|
+
var targetsCommand = defineCommand233({
|
|
94247
94610
|
meta: {
|
|
94248
94611
|
name: "targets",
|
|
94249
94612
|
description: `What a trigger can be pointed at \u2014 so "when a Task is picked up" becomes "when THIS Task is picked up".
|
|
@@ -94286,7 +94649,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94286
94649
|
// src/commands/scheduled-agents/templates.ts
|
|
94287
94650
|
import { readFile as readFile41 } from "fs/promises";
|
|
94288
94651
|
import path55 from "path";
|
|
94289
|
-
import { defineCommand as
|
|
94652
|
+
import { defineCommand as defineCommand234 } from "citty";
|
|
94290
94653
|
registerSchema({
|
|
94291
94654
|
command: "scheduled-agents.templates",
|
|
94292
94655
|
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.",
|
|
@@ -94341,7 +94704,7 @@ registerSchema({
|
|
|
94341
94704
|
}
|
|
94342
94705
|
}
|
|
94343
94706
|
});
|
|
94344
|
-
var templatesCommand =
|
|
94707
|
+
var templatesCommand = defineCommand234({
|
|
94345
94708
|
meta: {
|
|
94346
94709
|
name: "templates",
|
|
94347
94710
|
description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
|
|
@@ -94437,7 +94800,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94437
94800
|
});
|
|
94438
94801
|
|
|
94439
94802
|
// src/commands/scheduled-agents/triggers.ts
|
|
94440
|
-
import { defineCommand as
|
|
94803
|
+
import { defineCommand as defineCommand235 } from "citty";
|
|
94441
94804
|
var ARGS10 = {
|
|
94442
94805
|
trigger: {
|
|
94443
94806
|
type: "string",
|
|
@@ -94523,7 +94886,7 @@ function shapeTriggerCatalog(response, filter) {
|
|
|
94523
94886
|
}
|
|
94524
94887
|
return { ok: true, data: { groups, reacting: catalog.reacting } };
|
|
94525
94888
|
}
|
|
94526
|
-
var triggersCommand2 =
|
|
94889
|
+
var triggersCommand2 = defineCommand235({
|
|
94527
94890
|
meta: {
|
|
94528
94891
|
name: "triggers",
|
|
94529
94892
|
description: `Everything that can start a scheduled agent.
|
|
@@ -94553,7 +94916,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94553
94916
|
});
|
|
94554
94917
|
|
|
94555
94918
|
// src/commands/scheduled-agents/unstage.ts
|
|
94556
|
-
import { defineCommand as
|
|
94919
|
+
import { defineCommand as defineCommand236 } from "citty";
|
|
94557
94920
|
registerSchema({
|
|
94558
94921
|
command: "scheduled-agents.unstage",
|
|
94559
94922
|
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.",
|
|
@@ -94579,7 +94942,7 @@ function unstageBody(args8, chatId) {
|
|
|
94579
94942
|
}
|
|
94580
94943
|
return { chatId, ref: args8.ref, index };
|
|
94581
94944
|
}
|
|
94582
|
-
var unstageCommand =
|
|
94945
|
+
var unstageCommand = defineCommand236({
|
|
94583
94946
|
meta: {
|
|
94584
94947
|
name: "unstage",
|
|
94585
94948
|
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"
|
|
@@ -94610,7 +94973,7 @@ var unstageCommand = defineCommand230({
|
|
|
94610
94973
|
});
|
|
94611
94974
|
|
|
94612
94975
|
// src/commands/scheduled-agents/update.ts
|
|
94613
|
-
import { defineCommand as
|
|
94976
|
+
import { defineCommand as defineCommand237 } from "citty";
|
|
94614
94977
|
registerSchema({
|
|
94615
94978
|
command: "scheduled-agents.update",
|
|
94616
94979
|
description: "Stage an update to a published scheduled agent, or to one this chat staged (temp_agent_*).",
|
|
@@ -94637,7 +95000,7 @@ registerSchema({
|
|
|
94637
95000
|
enabled: { type: "string", description: "Replacement enabled state", required: false, enum: ["true", "false"] }
|
|
94638
95001
|
}
|
|
94639
95002
|
});
|
|
94640
|
-
var updateCommand4 =
|
|
95003
|
+
var updateCommand4 = defineCommand237({
|
|
94641
95004
|
meta: {
|
|
94642
95005
|
name: "update",
|
|
94643
95006
|
description: "Stage a scheduled agent update. Examples: baker scheduled-agents update <id> --enabled false | baker scheduled-agents update <id> --trigger form.submitted --form quote"
|
|
@@ -94708,7 +95071,7 @@ var updateCommand4 = defineCommand231({
|
|
|
94708
95071
|
});
|
|
94709
95072
|
|
|
94710
95073
|
// src/commands/scheduled-agents/index.ts
|
|
94711
|
-
var scheduledAgentsCommand =
|
|
95074
|
+
var scheduledAgentsCommand = defineCommand238({
|
|
94712
95075
|
meta: {
|
|
94713
95076
|
name: "scheduled-agents",
|
|
94714
95077
|
description: `Manage Scheduled agents. Subcommands: list, get, triggers, targets, create, update, delete, unstage, run, templates.
|
|
@@ -94737,7 +95100,7 @@ Examples:
|
|
|
94737
95100
|
Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
94738
95101
|
},
|
|
94739
95102
|
subCommands: {
|
|
94740
|
-
list:
|
|
95103
|
+
list: listCommand19,
|
|
94741
95104
|
get: getCommand4,
|
|
94742
95105
|
triggers: triggersCommand2,
|
|
94743
95106
|
targets: targetsCommand,
|
|
@@ -94751,14 +95114,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
94751
95114
|
});
|
|
94752
95115
|
|
|
94753
95116
|
// src/commands/schema.ts
|
|
94754
|
-
import { defineCommand as
|
|
95117
|
+
import { defineCommand as defineCommand239 } from "citty";
|
|
94755
95118
|
function narrowToFamily(commandName, available) {
|
|
94756
95119
|
const segments = commandName.split(".");
|
|
94757
95120
|
const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
|
|
94758
95121
|
const siblings = available.filter((name) => name.startsWith(prefix));
|
|
94759
95122
|
return siblings.length > 0 ? siblings : available;
|
|
94760
95123
|
}
|
|
94761
|
-
var schemaCommand2 =
|
|
95124
|
+
var schemaCommand2 = defineCommand239({
|
|
94762
95125
|
meta: {
|
|
94763
95126
|
name: "schema",
|
|
94764
95127
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images search (or images.search)"
|
|
@@ -94803,10 +95166,10 @@ var schemaCommand2 = defineCommand233({
|
|
|
94803
95166
|
});
|
|
94804
95167
|
|
|
94805
95168
|
// src/commands/studio/index.ts
|
|
94806
|
-
import { defineCommand as
|
|
95169
|
+
import { defineCommand as defineCommand248 } from "citty";
|
|
94807
95170
|
|
|
94808
95171
|
// src/commands/studio/animate.ts
|
|
94809
|
-
import { defineCommand as
|
|
95172
|
+
import { defineCommand as defineCommand240 } from "citty";
|
|
94810
95173
|
|
|
94811
95174
|
// src/commands/studio/spokenPace.ts
|
|
94812
95175
|
var WORDS_PER_SECOND = SPOKEN_WORDS_PER_SECOND;
|
|
@@ -95032,7 +95395,7 @@ function parseImageRefs(spec) {
|
|
|
95032
95395
|
}
|
|
95033
95396
|
var defaultDeps = {
|
|
95034
95397
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
95035
|
-
upload: (
|
|
95398
|
+
upload: (path58) => uploadLocalImage({ file: path58, contentType: detectImageContentType(path58), source: "uploaded" })
|
|
95036
95399
|
};
|
|
95037
95400
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
95038
95401
|
const refs = parseImageRefs(spec);
|
|
@@ -95052,10 +95415,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
95052
95415
|
}
|
|
95053
95416
|
return { imageIds, added };
|
|
95054
95417
|
}
|
|
95055
|
-
function uploadFailure(
|
|
95418
|
+
function uploadFailure(path58) {
|
|
95056
95419
|
return (error) => {
|
|
95057
95420
|
if (error instanceof ApiError) throw error;
|
|
95058
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
95421
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path58}" as an image.`);
|
|
95059
95422
|
};
|
|
95060
95423
|
}
|
|
95061
95424
|
|
|
@@ -95319,7 +95682,7 @@ async function adByHandHintFor(body) {
|
|
|
95319
95682
|
return null;
|
|
95320
95683
|
}
|
|
95321
95684
|
}
|
|
95322
|
-
var animateCommand =
|
|
95685
|
+
var animateCommand = defineCommand240({
|
|
95323
95686
|
meta: {
|
|
95324
95687
|
name: "animate",
|
|
95325
95688
|
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"
|
|
@@ -95444,7 +95807,7 @@ var animateCommand = defineCommand234({
|
|
|
95444
95807
|
});
|
|
95445
95808
|
|
|
95446
95809
|
// src/commands/studio/generate.ts
|
|
95447
|
-
import { defineCommand as
|
|
95810
|
+
import { defineCommand as defineCommand241 } from "citty";
|
|
95448
95811
|
var MODEL_LIST2 = IMAGE_MODEL_IDS;
|
|
95449
95812
|
var DEFAULT_MAX_WAIT_MS2 = 24e4;
|
|
95450
95813
|
registerSchema({
|
|
@@ -95580,7 +95943,7 @@ function buildGenerateBody(args8, prompt) {
|
|
|
95580
95943
|
}
|
|
95581
95944
|
return body;
|
|
95582
95945
|
}
|
|
95583
|
-
var generateCommand =
|
|
95946
|
+
var generateCommand = defineCommand241({
|
|
95584
95947
|
meta: {
|
|
95585
95948
|
name: "generate",
|
|
95586
95949
|
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 (default \u2014 fast, best at editing a reference and at extreme ratios), google/gemini-3-pro-image (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]]'"
|
|
@@ -95663,7 +96026,7 @@ var generateCommand = defineCommand235({
|
|
|
95663
96026
|
});
|
|
95664
96027
|
|
|
95665
96028
|
// src/commands/studio/get.ts
|
|
95666
|
-
import { defineCommand as
|
|
96029
|
+
import { defineCommand as defineCommand242 } from "citty";
|
|
95667
96030
|
registerSchema({
|
|
95668
96031
|
command: "studio.get",
|
|
95669
96032
|
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.",
|
|
@@ -95672,7 +96035,7 @@ registerSchema({
|
|
|
95672
96035
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
95673
96036
|
}
|
|
95674
96037
|
});
|
|
95675
|
-
var getCommand5 =
|
|
96038
|
+
var getCommand5 = defineCommand242({
|
|
95676
96039
|
meta: {
|
|
95677
96040
|
name: "get",
|
|
95678
96041
|
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"
|
|
@@ -95701,7 +96064,7 @@ var getCommand5 = defineCommand236({
|
|
|
95701
96064
|
});
|
|
95702
96065
|
|
|
95703
96066
|
// src/commands/studio/improve.ts
|
|
95704
|
-
import { defineCommand as
|
|
96067
|
+
import { defineCommand as defineCommand243 } from "citty";
|
|
95705
96068
|
var DESCRIPTION7 = "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.";
|
|
95706
96069
|
registerSchema({
|
|
95707
96070
|
command: "studio.improve",
|
|
@@ -95726,7 +96089,7 @@ registerSchema({
|
|
|
95726
96089
|
}
|
|
95727
96090
|
}
|
|
95728
96091
|
});
|
|
95729
|
-
var improveCommand =
|
|
96092
|
+
var improveCommand = defineCommand243({
|
|
95730
96093
|
meta: {
|
|
95731
96094
|
name: "improve",
|
|
95732
96095
|
description: `${DESCRIPTION7}
|
|
@@ -95770,7 +96133,7 @@ Examples:
|
|
|
95770
96133
|
});
|
|
95771
96134
|
|
|
95772
96135
|
// src/commands/studio/keep.ts
|
|
95773
|
-
import { defineCommand as
|
|
96136
|
+
import { defineCommand as defineCommand244 } from "citty";
|
|
95774
96137
|
registerSchema({
|
|
95775
96138
|
command: "studio.keep",
|
|
95776
96139
|
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.",
|
|
@@ -95780,7 +96143,7 @@ registerSchema({
|
|
|
95780
96143
|
undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
|
|
95781
96144
|
}
|
|
95782
96145
|
});
|
|
95783
|
-
var keepCommand =
|
|
96146
|
+
var keepCommand = defineCommand244({
|
|
95784
96147
|
meta: {
|
|
95785
96148
|
name: "keep",
|
|
95786
96149
|
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"
|
|
@@ -95831,7 +96194,7 @@ var keepCommand = defineCommand238({
|
|
|
95831
96194
|
});
|
|
95832
96195
|
|
|
95833
96196
|
// src/commands/studio/list.ts
|
|
95834
|
-
import { defineCommand as
|
|
96197
|
+
import { defineCommand as defineCommand245 } from "citty";
|
|
95835
96198
|
registerSchema({
|
|
95836
96199
|
command: "studio.list",
|
|
95837
96200
|
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.",
|
|
@@ -95842,7 +96205,7 @@ registerSchema({
|
|
|
95842
96205
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
95843
96206
|
}
|
|
95844
96207
|
});
|
|
95845
|
-
var
|
|
96208
|
+
var listCommand20 = defineCommand245({
|
|
95846
96209
|
meta: {
|
|
95847
96210
|
name: "list",
|
|
95848
96211
|
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"
|
|
@@ -95876,7 +96239,7 @@ var listCommand19 = defineCommand239({
|
|
|
95876
96239
|
});
|
|
95877
96240
|
|
|
95878
96241
|
// src/commands/studio/models.ts
|
|
95879
|
-
import { defineCommand as
|
|
96242
|
+
import { defineCommand as defineCommand246 } from "citty";
|
|
95880
96243
|
var DESCRIPTION8 = "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.";
|
|
95881
96244
|
registerSchema({
|
|
95882
96245
|
command: "studio.models",
|
|
@@ -95963,7 +96326,7 @@ function buildModelCards(kind, model) {
|
|
|
95963
96326
|
const selected = model ? ids2.filter((id) => id === model) : ids2;
|
|
95964
96327
|
return selected.map((id) => build(id));
|
|
95965
96328
|
}
|
|
95966
|
-
var modelsCommand =
|
|
96329
|
+
var modelsCommand = defineCommand246({
|
|
95967
96330
|
meta: {
|
|
95968
96331
|
name: "models",
|
|
95969
96332
|
description: `${DESCRIPTION8}
|
|
@@ -96010,13 +96373,13 @@ Examples:
|
|
|
96010
96373
|
});
|
|
96011
96374
|
|
|
96012
96375
|
// src/commands/studio/skills.ts
|
|
96013
|
-
import { defineCommand as
|
|
96376
|
+
import { defineCommand as defineCommand247 } from "citty";
|
|
96014
96377
|
registerSchema({
|
|
96015
96378
|
command: "studio.skills",
|
|
96016
96379
|
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.",
|
|
96017
96380
|
args: {}
|
|
96018
96381
|
});
|
|
96019
|
-
var skillsCommand =
|
|
96382
|
+
var skillsCommand = defineCommand247({
|
|
96020
96383
|
meta: {
|
|
96021
96384
|
name: "skills",
|
|
96022
96385
|
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"
|
|
@@ -96040,7 +96403,7 @@ var skillsCommand = defineCommand241({
|
|
|
96040
96403
|
});
|
|
96041
96404
|
|
|
96042
96405
|
// src/commands/studio/index.ts
|
|
96043
|
-
var studioCommand =
|
|
96406
|
+
var studioCommand = defineCommand248({
|
|
96044
96407
|
meta: {
|
|
96045
96408
|
name: "studio",
|
|
96046
96409
|
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.
|
|
@@ -96074,7 +96437,7 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
96074
96437
|
generate: generateCommand,
|
|
96075
96438
|
animate: animateCommand,
|
|
96076
96439
|
get: getCommand5,
|
|
96077
|
-
list:
|
|
96440
|
+
list: listCommand20,
|
|
96078
96441
|
keep: keepCommand,
|
|
96079
96442
|
models: modelsCommand,
|
|
96080
96443
|
skills: skillsCommand,
|
|
@@ -96083,10 +96446,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
96083
96446
|
});
|
|
96084
96447
|
|
|
96085
96448
|
// src/commands/tag-manager/index.ts
|
|
96086
|
-
import { defineCommand as
|
|
96449
|
+
import { defineCommand as defineCommand252 } from "citty";
|
|
96087
96450
|
|
|
96088
96451
|
// src/commands/tag-manager/draft.ts
|
|
96089
|
-
import { defineCommand as
|
|
96452
|
+
import { defineCommand as defineCommand249 } from "citty";
|
|
96090
96453
|
|
|
96091
96454
|
// src/commands/tag-manager/shared.ts
|
|
96092
96455
|
import { readFileSync as readFileSync23 } from "fs";
|
|
@@ -96155,10 +96518,10 @@ async function stageOp4(op) {
|
|
|
96155
96518
|
handleError8(err);
|
|
96156
96519
|
}
|
|
96157
96520
|
}
|
|
96158
|
-
async function draftAction3(
|
|
96521
|
+
async function draftAction3(path58, body, chat) {
|
|
96159
96522
|
const chatId = resolveChatId(chat);
|
|
96160
96523
|
try {
|
|
96161
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
96524
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path58, { chatId, ...body }));
|
|
96162
96525
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
96163
96526
|
return data;
|
|
96164
96527
|
} catch (err) {
|
|
@@ -96212,13 +96575,13 @@ registerSchema({
|
|
|
96212
96575
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
96213
96576
|
}
|
|
96214
96577
|
});
|
|
96215
|
-
var draftCommand6 =
|
|
96578
|
+
var draftCommand6 = defineCommand249({
|
|
96216
96579
|
meta: {
|
|
96217
96580
|
name: "draft",
|
|
96218
96581
|
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."
|
|
96219
96582
|
},
|
|
96220
96583
|
subCommands: {
|
|
96221
|
-
list:
|
|
96584
|
+
list: defineCommand249({
|
|
96222
96585
|
meta: {
|
|
96223
96586
|
name: "list",
|
|
96224
96587
|
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
@@ -96231,7 +96594,7 @@ var draftCommand6 = defineCommand243({
|
|
|
96231
96594
|
await draftList2(args8.json === true, args8.chat);
|
|
96232
96595
|
}
|
|
96233
96596
|
}),
|
|
96234
|
-
show:
|
|
96597
|
+
show: defineCommand249({
|
|
96235
96598
|
meta: {
|
|
96236
96599
|
name: "show",
|
|
96237
96600
|
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
@@ -96248,7 +96611,7 @@ var draftCommand6 = defineCommand243({
|
|
|
96248
96611
|
);
|
|
96249
96612
|
}
|
|
96250
96613
|
}),
|
|
96251
|
-
amend:
|
|
96614
|
+
amend: defineCommand249({
|
|
96252
96615
|
meta: {
|
|
96253
96616
|
name: "amend",
|
|
96254
96617
|
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."
|
|
@@ -96265,7 +96628,7 @@ var draftCommand6 = defineCommand243({
|
|
|
96265
96628
|
});
|
|
96266
96629
|
}
|
|
96267
96630
|
}),
|
|
96268
|
-
remove:
|
|
96631
|
+
remove: defineCommand249({
|
|
96269
96632
|
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
96270
96633
|
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
96271
96634
|
run: async ({ args: args8 }) => {
|
|
@@ -96274,7 +96637,7 @@ var draftCommand6 = defineCommand243({
|
|
|
96274
96637
|
});
|
|
96275
96638
|
}
|
|
96276
96639
|
}),
|
|
96277
|
-
clear:
|
|
96640
|
+
clear: defineCommand249({
|
|
96278
96641
|
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
96279
96642
|
run: async () => {
|
|
96280
96643
|
await draftAction3("/api/tag-manager/draft/clear", {});
|
|
@@ -96284,7 +96647,7 @@ var draftCommand6 = defineCommand243({
|
|
|
96284
96647
|
});
|
|
96285
96648
|
|
|
96286
96649
|
// src/commands/tag-manager/read.ts
|
|
96287
|
-
import { defineCommand as
|
|
96650
|
+
import { defineCommand as defineCommand250 } from "citty";
|
|
96288
96651
|
registerSchema({
|
|
96289
96652
|
command: "tagManager.containers",
|
|
96290
96653
|
description: "List the Google Tag Manager containers this company selected. There can be several, and Baker may read and change all of them. Start here to confirm which containers you are managing.",
|
|
@@ -96332,7 +96695,7 @@ function containersHints(containers, unavailableContainers = []) {
|
|
|
96332
96695
|
}
|
|
96333
96696
|
return hints2;
|
|
96334
96697
|
}
|
|
96335
|
-
var containersCommand =
|
|
96698
|
+
var containersCommand = defineCommand250({
|
|
96336
96699
|
meta: {
|
|
96337
96700
|
name: "containers",
|
|
96338
96701
|
description: `List Tag Manager containers selected by this company.
|
|
@@ -96349,7 +96712,7 @@ Start here:
|
|
|
96349
96712
|
}
|
|
96350
96713
|
}
|
|
96351
96714
|
});
|
|
96352
|
-
var readCommand =
|
|
96715
|
+
var readCommand = defineCommand250({
|
|
96353
96716
|
meta: {
|
|
96354
96717
|
name: "read",
|
|
96355
96718
|
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
@@ -96391,7 +96754,7 @@ Examples:
|
|
|
96391
96754
|
});
|
|
96392
96755
|
|
|
96393
96756
|
// src/commands/tag-manager/write-commands.ts
|
|
96394
|
-
import { defineCommand as
|
|
96757
|
+
import { defineCommand as defineCommand251 } from "citty";
|
|
96395
96758
|
var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
|
|
96396
96759
|
var ENTITIES = [
|
|
96397
96760
|
{
|
|
@@ -96447,10 +96810,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
|
|
|
96447
96810
|
});
|
|
96448
96811
|
}
|
|
96449
96812
|
function entityCommand(entity, noun, example) {
|
|
96450
|
-
return
|
|
96813
|
+
return defineCommand251({
|
|
96451
96814
|
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
96452
96815
|
subCommands: {
|
|
96453
|
-
create:
|
|
96816
|
+
create: defineCommand251({
|
|
96454
96817
|
meta: {
|
|
96455
96818
|
name: "create",
|
|
96456
96819
|
description: `Stage a new ${noun}
|
|
@@ -96472,7 +96835,7 @@ Examples:
|
|
|
96472
96835
|
});
|
|
96473
96836
|
}
|
|
96474
96837
|
}),
|
|
96475
|
-
update:
|
|
96838
|
+
update: defineCommand251({
|
|
96476
96839
|
meta: {
|
|
96477
96840
|
name: "update",
|
|
96478
96841
|
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
@@ -96492,7 +96855,7 @@ Examples:
|
|
|
96492
96855
|
});
|
|
96493
96856
|
}
|
|
96494
96857
|
}),
|
|
96495
|
-
delete:
|
|
96858
|
+
delete: defineCommand251({
|
|
96496
96859
|
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
96497
96860
|
args: {
|
|
96498
96861
|
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
@@ -96533,7 +96896,7 @@ function builtinTypes(args8) {
|
|
|
96533
96896
|
}
|
|
96534
96897
|
return raw.split(",").map((entry) => entry.trim());
|
|
96535
96898
|
}
|
|
96536
|
-
var builtinCommand =
|
|
96899
|
+
var builtinCommand = defineCommand251({
|
|
96537
96900
|
meta: {
|
|
96538
96901
|
name: "builtin",
|
|
96539
96902
|
description: `Enable or disable built-in variables
|
|
@@ -96543,7 +96906,7 @@ Examples:
|
|
|
96543
96906
|
baker tag-manager builtin disable --types formId`
|
|
96544
96907
|
},
|
|
96545
96908
|
subCommands: {
|
|
96546
|
-
enable:
|
|
96909
|
+
enable: defineCommand251({
|
|
96547
96910
|
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
96548
96911
|
args: {
|
|
96549
96912
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -96557,7 +96920,7 @@ Examples:
|
|
|
96557
96920
|
});
|
|
96558
96921
|
}
|
|
96559
96922
|
}),
|
|
96560
|
-
disable:
|
|
96923
|
+
disable: defineCommand251({
|
|
96561
96924
|
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
96562
96925
|
args: {
|
|
96563
96926
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -96575,7 +96938,7 @@ Examples:
|
|
|
96575
96938
|
});
|
|
96576
96939
|
|
|
96577
96940
|
// src/commands/tag-manager/index.ts
|
|
96578
|
-
var tagManagerCommand =
|
|
96941
|
+
var tagManagerCommand = defineCommand252({
|
|
96579
96942
|
meta: {
|
|
96580
96943
|
name: "tag-manager",
|
|
96581
96944
|
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
@@ -96612,7 +96975,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
|
96612
96975
|
});
|
|
96613
96976
|
|
|
96614
96977
|
// src/commands/tags/index.ts
|
|
96615
|
-
import { defineCommand as
|
|
96978
|
+
import { defineCommand as defineCommand253 } from "citty";
|
|
96616
96979
|
|
|
96617
96980
|
// src/commands/tags/shared.ts
|
|
96618
96981
|
function failApi3(err) {
|
|
@@ -96692,7 +97055,7 @@ async function listTags(json) {
|
|
|
96692
97055
|
var listArgs12 = {
|
|
96693
97056
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
|
|
96694
97057
|
};
|
|
96695
|
-
var
|
|
97058
|
+
var listCommand21 = defineCommand253({
|
|
96696
97059
|
meta: {
|
|
96697
97060
|
name: "list",
|
|
96698
97061
|
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"
|
|
@@ -96711,7 +97074,7 @@ async function listDraft4(chat) {
|
|
|
96711
97074
|
failApi3(err);
|
|
96712
97075
|
}
|
|
96713
97076
|
}
|
|
96714
|
-
var draftCommand7 =
|
|
97077
|
+
var draftCommand7 = defineCommand253({
|
|
96715
97078
|
meta: {
|
|
96716
97079
|
name: "draft",
|
|
96717
97080
|
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."
|
|
@@ -96721,7 +97084,7 @@ var draftCommand7 = defineCommand247({
|
|
|
96721
97084
|
await listDraft4(args8.chat);
|
|
96722
97085
|
}
|
|
96723
97086
|
});
|
|
96724
|
-
var tagsCommand4 =
|
|
97087
|
+
var tagsCommand4 = defineCommand253({
|
|
96725
97088
|
meta: {
|
|
96726
97089
|
name: "tags",
|
|
96727
97090
|
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.
|
|
@@ -96738,7 +97101,7 @@ Examples:
|
|
|
96738
97101
|
Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
96739
97102
|
},
|
|
96740
97103
|
subCommands: {
|
|
96741
|
-
list:
|
|
97104
|
+
list: listCommand21,
|
|
96742
97105
|
draft: draftCommand7
|
|
96743
97106
|
},
|
|
96744
97107
|
// Bare `baker tags` lists the effective tags. `args` stays so citty knows this
|
|
@@ -96750,10 +97113,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
96750
97113
|
});
|
|
96751
97114
|
|
|
96752
97115
|
// src/commands/testimonials/index.ts
|
|
96753
|
-
import { defineCommand as
|
|
97116
|
+
import { defineCommand as defineCommand257 } from "citty";
|
|
96754
97117
|
|
|
96755
97118
|
// src/commands/testimonials/get.ts
|
|
96756
|
-
import { defineCommand as
|
|
97119
|
+
import { defineCommand as defineCommand254 } from "citty";
|
|
96757
97120
|
registerSchema({
|
|
96758
97121
|
command: "testimonials.get",
|
|
96759
97122
|
description: "Get a single testimonial by ID",
|
|
@@ -96761,7 +97124,7 @@ registerSchema({
|
|
|
96761
97124
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
96762
97125
|
}
|
|
96763
97126
|
});
|
|
96764
|
-
var getCommand6 =
|
|
97127
|
+
var getCommand6 = defineCommand254({
|
|
96765
97128
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
96766
97129
|
args: {
|
|
96767
97130
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -96798,7 +97161,7 @@ var getCommand6 = defineCommand248({
|
|
|
96798
97161
|
});
|
|
96799
97162
|
|
|
96800
97163
|
// src/commands/testimonials/list.ts
|
|
96801
|
-
import { defineCommand as
|
|
97164
|
+
import { defineCommand as defineCommand255 } from "citty";
|
|
96802
97165
|
|
|
96803
97166
|
// src/commands/testimonials/emptyCorpusHints.ts
|
|
96804
97167
|
function resolveEmptyReason({
|
|
@@ -96955,7 +97318,7 @@ function buildListParams(args8) {
|
|
|
96955
97318
|
}
|
|
96956
97319
|
return params;
|
|
96957
97320
|
}
|
|
96958
|
-
var
|
|
97321
|
+
var listCommand22 = defineCommand255({
|
|
96959
97322
|
meta: {
|
|
96960
97323
|
name: "list",
|
|
96961
97324
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -97015,7 +97378,7 @@ var listCommand21 = defineCommand249({
|
|
|
97015
97378
|
});
|
|
97016
97379
|
|
|
97017
97380
|
// src/commands/testimonials/search.ts
|
|
97018
|
-
import { defineCommand as
|
|
97381
|
+
import { defineCommand as defineCommand256 } from "citty";
|
|
97019
97382
|
var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
|
|
97020
97383
|
function languageBiasHint(results, requestedLanguage) {
|
|
97021
97384
|
if (requestedLanguage) {
|
|
@@ -97094,7 +97457,7 @@ function buildSearchRequest(query, args8) {
|
|
|
97094
97457
|
}
|
|
97095
97458
|
return body;
|
|
97096
97459
|
}
|
|
97097
|
-
var searchCommand3 =
|
|
97460
|
+
var searchCommand3 = defineCommand256({
|
|
97098
97461
|
meta: {
|
|
97099
97462
|
name: "search",
|
|
97100
97463
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -97158,7 +97521,7 @@ var searchCommand3 = defineCommand250({
|
|
|
97158
97521
|
var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
97159
97522
|
|
|
97160
97523
|
// src/commands/testimonials/index.ts
|
|
97161
|
-
var testimonialsCommand =
|
|
97524
|
+
var testimonialsCommand = defineCommand257({
|
|
97162
97525
|
meta: {
|
|
97163
97526
|
name: "testimonials",
|
|
97164
97527
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -97174,16 +97537,16 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
97174
97537
|
subCommands: {
|
|
97175
97538
|
get: getCommand6,
|
|
97176
97539
|
search: searchCommand3,
|
|
97177
|
-
list:
|
|
97540
|
+
list: listCommand22,
|
|
97178
97541
|
tags: tagsCommand5
|
|
97179
97542
|
}
|
|
97180
97543
|
});
|
|
97181
97544
|
|
|
97182
97545
|
// src/commands/videos/index.ts
|
|
97183
|
-
import { defineCommand as
|
|
97546
|
+
import { defineCommand as defineCommand266 } from "citty";
|
|
97184
97547
|
|
|
97185
97548
|
// src/commands/videos/delete.ts
|
|
97186
|
-
import { defineCommand as
|
|
97549
|
+
import { defineCommand as defineCommand258 } from "citty";
|
|
97187
97550
|
registerSchema({
|
|
97188
97551
|
command: "videos.delete",
|
|
97189
97552
|
description: "Delete a video by ID",
|
|
@@ -97197,7 +97560,7 @@ registerSchema({
|
|
|
97197
97560
|
}
|
|
97198
97561
|
}
|
|
97199
97562
|
});
|
|
97200
|
-
var deleteCommand4 =
|
|
97563
|
+
var deleteCommand4 = defineCommand258({
|
|
97201
97564
|
meta: {
|
|
97202
97565
|
name: "delete",
|
|
97203
97566
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -97238,7 +97601,7 @@ var deleteCommand4 = defineCommand252({
|
|
|
97238
97601
|
});
|
|
97239
97602
|
|
|
97240
97603
|
// src/commands/videos/describe.ts
|
|
97241
|
-
import { defineCommand as
|
|
97604
|
+
import { defineCommand as defineCommand259 } from "citty";
|
|
97242
97605
|
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.";
|
|
97243
97606
|
registerSchema({
|
|
97244
97607
|
command: "videos.describe",
|
|
@@ -97255,7 +97618,7 @@ registerSchema({
|
|
|
97255
97618
|
full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
|
|
97256
97619
|
}
|
|
97257
97620
|
});
|
|
97258
|
-
var describeCommand2 =
|
|
97621
|
+
var describeCommand2 = defineCommand259({
|
|
97259
97622
|
meta: {
|
|
97260
97623
|
name: "describe",
|
|
97261
97624
|
description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
|
|
@@ -97312,108 +97675,12 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
97312
97675
|
}
|
|
97313
97676
|
});
|
|
97314
97677
|
|
|
97315
|
-
// src/commands/videos/
|
|
97316
|
-
import {
|
|
97317
|
-
|
|
97318
|
-
command: "videos.get",
|
|
97319
|
-
description: "Get a single video by ID",
|
|
97320
|
-
args: {
|
|
97321
|
-
id: { type: "string", description: "Video ID", required: true }
|
|
97322
|
-
}
|
|
97323
|
-
});
|
|
97324
|
-
var getCommand7 = defineCommand254({
|
|
97325
|
-
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
97326
|
-
args: {
|
|
97327
|
-
id: { type: "positional", description: "Video ID", required: false },
|
|
97328
|
-
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
97329
|
-
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
97330
|
-
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
97331
|
-
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
97332
|
-
},
|
|
97333
|
-
run: async ({ args: args8 }) => {
|
|
97334
|
-
try {
|
|
97335
|
-
const id = args8.id || args8["video-id"];
|
|
97336
|
-
if (!id) {
|
|
97337
|
-
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
97338
|
-
process.exit(1);
|
|
97339
|
-
}
|
|
97340
|
-
validateConvexId(id);
|
|
97341
|
-
const data = await apiGet("/api/videos/get", { id });
|
|
97342
|
-
writeOutput(
|
|
97343
|
-
{ ok: true, data },
|
|
97344
|
-
args8.output || "json",
|
|
97345
|
-
args8.fields ? args8.fields.split(",") : void 0,
|
|
97346
|
-
args8.full,
|
|
97347
|
-
videoNormalizer
|
|
97348
|
-
);
|
|
97349
|
-
} catch (err) {
|
|
97350
|
-
if (err instanceof ApiError) {
|
|
97351
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
97352
|
-
process.exit(1);
|
|
97353
|
-
}
|
|
97354
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
97355
|
-
process.exit(1);
|
|
97356
|
-
}
|
|
97357
|
-
}
|
|
97358
|
-
});
|
|
97359
|
-
|
|
97360
|
-
// src/commands/videos/group.ts
|
|
97361
|
-
import { defineCommand as defineCommand255 } from "citty";
|
|
97362
|
-
registerSchema({
|
|
97363
|
-
command: "videos.group",
|
|
97364
|
-
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
97365
|
-
args: {
|
|
97366
|
-
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
97367
|
-
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
97368
|
-
}
|
|
97369
|
-
});
|
|
97370
|
-
var groupCommand2 = defineCommand255({
|
|
97371
|
-
meta: {
|
|
97372
|
-
name: "group",
|
|
97373
|
-
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>"
|
|
97374
|
-
},
|
|
97375
|
-
args: {
|
|
97376
|
-
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
97377
|
-
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
97378
|
-
},
|
|
97379
|
-
run: async ({ args: args8 }) => {
|
|
97380
|
-
await runMediaGroupLookup({
|
|
97381
|
-
id: args8.id,
|
|
97382
|
-
groupKey: args8["group-key"],
|
|
97383
|
-
path: "/api/videos/group",
|
|
97384
|
-
idLabel: "a video or image id"
|
|
97385
|
-
});
|
|
97386
|
-
}
|
|
97387
|
-
});
|
|
97388
|
-
|
|
97389
|
-
// src/commands/videos/ingest.ts
|
|
97390
|
-
import { mkdtemp as mkdtemp3, rm as rm10, stat as stat12 } from "fs/promises";
|
|
97678
|
+
// src/commands/videos/fetch.ts
|
|
97679
|
+
import { constants } from "fs";
|
|
97680
|
+
import { copyFile as copyFile2, mkdir as mkdir17, mkdtemp as mkdtemp3, rm as rm10 } from "fs/promises";
|
|
97391
97681
|
import { tmpdir as tmpdir4 } from "os";
|
|
97392
97682
|
import path56 from "path";
|
|
97393
|
-
import { defineCommand as
|
|
97394
|
-
|
|
97395
|
-
// src/lib/streamUpload.ts
|
|
97396
|
-
import { createHash as createHash3 } from "crypto";
|
|
97397
|
-
import { createReadStream } from "fs";
|
|
97398
|
-
import { Readable } from "stream";
|
|
97399
|
-
import { pipeline } from "stream/promises";
|
|
97400
|
-
async function hashFile(filePath) {
|
|
97401
|
-
const hash = createHash3("sha256");
|
|
97402
|
-
await pipeline(createReadStream(filePath), hash);
|
|
97403
|
-
return hash.digest("hex");
|
|
97404
|
-
}
|
|
97405
|
-
async function putFileStreamed(args8) {
|
|
97406
|
-
const body = Readable.toWeb(createReadStream(args8.filePath));
|
|
97407
|
-
return await fetch(args8.putUrl, {
|
|
97408
|
-
method: "PUT",
|
|
97409
|
-
body,
|
|
97410
|
-
headers: {
|
|
97411
|
-
"Content-Type": args8.contentType,
|
|
97412
|
-
"Content-Length": String(args8.sizeBytes)
|
|
97413
|
-
},
|
|
97414
|
-
duplex: "half"
|
|
97415
|
-
});
|
|
97416
|
-
}
|
|
97683
|
+
import { defineCommand as defineCommand260 } from "citty";
|
|
97417
97684
|
|
|
97418
97685
|
// src/commands/videos/videoPlatforms.ts
|
|
97419
97686
|
var PLATFORM_DOMAINS = {
|
|
@@ -97422,6 +97689,7 @@ var PLATFORM_DOMAINS = {
|
|
|
97422
97689
|
tiktok: ["tiktok.com"],
|
|
97423
97690
|
twitter: ["twitter.com", "x.com", "vxtwitter.com", "fixvx.com"],
|
|
97424
97691
|
facebook: ["facebook.com", "fb.watch", "fb.com"],
|
|
97692
|
+
linkedin: ["linkedin.com", "lnkd.in"],
|
|
97425
97693
|
reddit: ["reddit.com", "redd.it"],
|
|
97426
97694
|
vimeo: ["vimeo.com"],
|
|
97427
97695
|
dailymotion: ["dailymotion.com", "dai.ly"],
|
|
@@ -97526,6 +97794,218 @@ function safePathname(rawUrl) {
|
|
|
97526
97794
|
}
|
|
97527
97795
|
}
|
|
97528
97796
|
|
|
97797
|
+
// src/commands/videos/fetch.ts
|
|
97798
|
+
registerSchema({
|
|
97799
|
+
command: "videos.fetch",
|
|
97800
|
+
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.",
|
|
97801
|
+
args: {
|
|
97802
|
+
url: { type: "string", description: "Video page URL", required: true },
|
|
97803
|
+
out: { type: "string", description: "Directory to write the file into (created if missing)", required: true },
|
|
97804
|
+
"max-seconds": {
|
|
97805
|
+
type: "string",
|
|
97806
|
+
description: `Refuse videos longer than this many seconds (default ${MAX_VIDEO_INGEST_SECONDS})`,
|
|
97807
|
+
required: false
|
|
97808
|
+
},
|
|
97809
|
+
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
97810
|
+
"max-height": {
|
|
97811
|
+
type: "string",
|
|
97812
|
+
description: "Keep a version whose shorter side is at most this many pixels (e.g. 1080 \u2014 a vertical Short keeps 1080\xD71920) when the site offers one",
|
|
97813
|
+
required: false
|
|
97814
|
+
}
|
|
97815
|
+
}
|
|
97816
|
+
});
|
|
97817
|
+
function positiveInt(value2) {
|
|
97818
|
+
const parsed = typeof value2 === "string" ? Number.parseInt(value2, 10) : Number.NaN;
|
|
97819
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
97820
|
+
}
|
|
97821
|
+
var fetchCommand2 = defineCommand260({
|
|
97822
|
+
meta: {
|
|
97823
|
+
name: "fetch",
|
|
97824
|
+
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"
|
|
97825
|
+
},
|
|
97826
|
+
args: {
|
|
97827
|
+
url: { type: "positional", description: "Video page URL", required: true },
|
|
97828
|
+
out: { type: "string", description: "Directory to write the file into", required: true },
|
|
97829
|
+
"max-seconds": { type: "string", description: "Refuse videos longer than this", required: false },
|
|
97830
|
+
"timeout-ms": { type: "string", description: "Download time limit in milliseconds", required: false },
|
|
97831
|
+
"max-height": {
|
|
97832
|
+
type: "string",
|
|
97833
|
+
description: "Cap the shorter side at this many pixels (e.g. 1080)",
|
|
97834
|
+
required: false
|
|
97835
|
+
}
|
|
97836
|
+
},
|
|
97837
|
+
run: async ({ args: args8 }) => {
|
|
97838
|
+
const result = await fetchVideo({
|
|
97839
|
+
url: String(args8.url ?? ""),
|
|
97840
|
+
out: String(args8.out ?? ""),
|
|
97841
|
+
maxSeconds: positiveInt(args8["max-seconds"]),
|
|
97842
|
+
timeoutMs: positiveInt(args8["timeout-ms"]),
|
|
97843
|
+
maxHeight: positiveInt(args8["max-height"])
|
|
97844
|
+
});
|
|
97845
|
+
writeJson(result);
|
|
97846
|
+
if (!result.ok) process.exit(1);
|
|
97847
|
+
}
|
|
97848
|
+
});
|
|
97849
|
+
async function fetchVideo(args8) {
|
|
97850
|
+
const outDir = path56.resolve(args8.out);
|
|
97851
|
+
const workDir = await mkdtemp3(path56.join(tmpdir4(), "videos-fetch-"));
|
|
97852
|
+
try {
|
|
97853
|
+
await mkdir17(outDir, { recursive: true });
|
|
97854
|
+
const vimeoCookie = captureVimeoCookie();
|
|
97855
|
+
const probe = await probeYtDlp({ url: args8.url, vimeoCookie, cookieDir: workDir });
|
|
97856
|
+
if (isAudioOnly(probe.info)) {
|
|
97857
|
+
return { ok: false, error: { code: "VALIDATION_ERROR", message: "That link is audio, not video." } };
|
|
97858
|
+
}
|
|
97859
|
+
const seconds = durationSeconds(probe.info);
|
|
97860
|
+
const tooLong = refuseByDuration(seconds, args8.maxSeconds ?? MAX_VIDEO_INGEST_SECONDS);
|
|
97861
|
+
if (tooLong) {
|
|
97862
|
+
return { ok: false, error: { code: "VALIDATION_ERROR", message: tooLong } };
|
|
97863
|
+
}
|
|
97864
|
+
const { filePath, tier, reducedQuality } = await runYtDlp({
|
|
97865
|
+
url: args8.url,
|
|
97866
|
+
audioOnly: false,
|
|
97867
|
+
workDir,
|
|
97868
|
+
vimeoCookie,
|
|
97869
|
+
timeoutMs: args8.timeoutMs ?? downloadTimeoutMs(seconds),
|
|
97870
|
+
maxHeight: args8.maxHeight
|
|
97871
|
+
});
|
|
97872
|
+
return {
|
|
97873
|
+
ok: true,
|
|
97874
|
+
data: {
|
|
97875
|
+
file: await placeInto(outDir, filePath, fileStem(probe.info)),
|
|
97876
|
+
durationSeconds: seconds,
|
|
97877
|
+
egress: tier,
|
|
97878
|
+
...reducedQuality ? { reducedQuality: true } : {}
|
|
97879
|
+
}
|
|
97880
|
+
};
|
|
97881
|
+
} catch (err) {
|
|
97882
|
+
const message = err instanceof YtDlpError ? `${err.message}: ${err.stderrTail}`.trim() : err instanceof Error ? err.message : String(err);
|
|
97883
|
+
return { ok: false, error: { code: "DOWNLOAD_FAILED", message } };
|
|
97884
|
+
} finally {
|
|
97885
|
+
await rm10(workDir, { recursive: true, force: true }).catch(() => {
|
|
97886
|
+
});
|
|
97887
|
+
}
|
|
97888
|
+
}
|
|
97889
|
+
function fileStem(info) {
|
|
97890
|
+
const parts = [info.extractor_key, info.id].filter((part) => typeof part === "string" && part !== "");
|
|
97891
|
+
const stem = parts.join("-").toLowerCase().replace(/[^a-z0-9._-]+/g, "_").replace(/^[._-]+/, "");
|
|
97892
|
+
return stem === "" ? "video" : stem;
|
|
97893
|
+
}
|
|
97894
|
+
async function placeInto(outDir, source, stem) {
|
|
97895
|
+
for (let n = 1; ; n++) {
|
|
97896
|
+
const target2 = path56.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path56.extname(source)}`);
|
|
97897
|
+
try {
|
|
97898
|
+
await copyFile2(source, target2, constants.COPYFILE_EXCL);
|
|
97899
|
+
return target2;
|
|
97900
|
+
} catch (err) {
|
|
97901
|
+
if (!(err instanceof Error && "code" in err && err.code === "EEXIST")) throw err;
|
|
97902
|
+
}
|
|
97903
|
+
}
|
|
97904
|
+
}
|
|
97905
|
+
|
|
97906
|
+
// src/commands/videos/get.ts
|
|
97907
|
+
import { defineCommand as defineCommand261 } from "citty";
|
|
97908
|
+
registerSchema({
|
|
97909
|
+
command: "videos.get",
|
|
97910
|
+
description: "Get a single video by ID",
|
|
97911
|
+
args: {
|
|
97912
|
+
id: { type: "string", description: "Video ID", required: true }
|
|
97913
|
+
}
|
|
97914
|
+
});
|
|
97915
|
+
var getCommand7 = defineCommand261({
|
|
97916
|
+
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
97917
|
+
args: {
|
|
97918
|
+
id: { type: "positional", description: "Video ID", required: false },
|
|
97919
|
+
"video-id": { type: "string", description: "Video ID (alternative to positional)", required: false },
|
|
97920
|
+
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
97921
|
+
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
97922
|
+
full: { type: "boolean", description: "Include full metadata", required: false, default: false }
|
|
97923
|
+
},
|
|
97924
|
+
run: async ({ args: args8 }) => {
|
|
97925
|
+
try {
|
|
97926
|
+
const id = args8.id || args8["video-id"];
|
|
97927
|
+
if (!id) {
|
|
97928
|
+
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Video ID is required" } });
|
|
97929
|
+
process.exit(1);
|
|
97930
|
+
}
|
|
97931
|
+
validateConvexId(id);
|
|
97932
|
+
const data = await apiGet("/api/videos/get", { id });
|
|
97933
|
+
writeOutput(
|
|
97934
|
+
{ ok: true, data },
|
|
97935
|
+
args8.output || "json",
|
|
97936
|
+
args8.fields ? args8.fields.split(",") : void 0,
|
|
97937
|
+
args8.full,
|
|
97938
|
+
videoNormalizer
|
|
97939
|
+
);
|
|
97940
|
+
} catch (err) {
|
|
97941
|
+
if (err instanceof ApiError) {
|
|
97942
|
+
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
97943
|
+
process.exit(1);
|
|
97944
|
+
}
|
|
97945
|
+
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
97946
|
+
process.exit(1);
|
|
97947
|
+
}
|
|
97948
|
+
}
|
|
97949
|
+
});
|
|
97950
|
+
|
|
97951
|
+
// src/commands/videos/group.ts
|
|
97952
|
+
import { defineCommand as defineCommand262 } from "citty";
|
|
97953
|
+
registerSchema({
|
|
97954
|
+
command: "videos.group",
|
|
97955
|
+
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
97956
|
+
args: {
|
|
97957
|
+
id: { type: "string", description: "A video or image id \u2014 returns that asset's whole set", required: false },
|
|
97958
|
+
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
97959
|
+
}
|
|
97960
|
+
});
|
|
97961
|
+
var groupCommand2 = defineCommand262({
|
|
97962
|
+
meta: {
|
|
97963
|
+
name: "group",
|
|
97964
|
+
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>"
|
|
97965
|
+
},
|
|
97966
|
+
args: {
|
|
97967
|
+
id: { type: "positional", description: "A video or image id from the set", required: false },
|
|
97968
|
+
"group-key": { type: "string", description: "The set key, if you already have it", required: false }
|
|
97969
|
+
},
|
|
97970
|
+
run: async ({ args: args8 }) => {
|
|
97971
|
+
await runMediaGroupLookup({
|
|
97972
|
+
id: args8.id,
|
|
97973
|
+
groupKey: args8["group-key"],
|
|
97974
|
+
path: "/api/videos/group",
|
|
97975
|
+
idLabel: "a video or image id"
|
|
97976
|
+
});
|
|
97977
|
+
}
|
|
97978
|
+
});
|
|
97979
|
+
|
|
97980
|
+
// src/commands/videos/ingest.ts
|
|
97981
|
+
import { mkdtemp as mkdtemp4, rm as rm11, stat as stat12 } from "fs/promises";
|
|
97982
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
97983
|
+
import path57 from "path";
|
|
97984
|
+
import { defineCommand as defineCommand263 } from "citty";
|
|
97985
|
+
|
|
97986
|
+
// src/lib/streamUpload.ts
|
|
97987
|
+
import { createHash as createHash3 } from "crypto";
|
|
97988
|
+
import { createReadStream } from "fs";
|
|
97989
|
+
import { Readable } from "stream";
|
|
97990
|
+
import { pipeline } from "stream/promises";
|
|
97991
|
+
async function hashFile(filePath) {
|
|
97992
|
+
const hash = createHash3("sha256");
|
|
97993
|
+
await pipeline(createReadStream(filePath), hash);
|
|
97994
|
+
return hash.digest("hex");
|
|
97995
|
+
}
|
|
97996
|
+
async function putFileStreamed(args8) {
|
|
97997
|
+
const body = Readable.toWeb(createReadStream(args8.filePath));
|
|
97998
|
+
return await fetch(args8.putUrl, {
|
|
97999
|
+
method: "PUT",
|
|
98000
|
+
body,
|
|
98001
|
+
headers: {
|
|
98002
|
+
"Content-Type": args8.contentType,
|
|
98003
|
+
"Content-Length": String(args8.sizeBytes)
|
|
98004
|
+
},
|
|
98005
|
+
duplex: "half"
|
|
98006
|
+
});
|
|
98007
|
+
}
|
|
98008
|
+
|
|
97529
98009
|
// src/commands/videos/ingest.ts
|
|
97530
98010
|
registerSchema({
|
|
97531
98011
|
command: "videos.ingest",
|
|
@@ -97554,7 +98034,7 @@ registerSchema({
|
|
|
97554
98034
|
"dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
|
|
97555
98035
|
}
|
|
97556
98036
|
});
|
|
97557
|
-
var ingestCommand2 =
|
|
98037
|
+
var ingestCommand2 = defineCommand263({
|
|
97558
98038
|
meta: {
|
|
97559
98039
|
name: "ingest",
|
|
97560
98040
|
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"
|
|
@@ -97740,7 +98220,7 @@ function ingestUrl(args8) {
|
|
|
97740
98220
|
}
|
|
97741
98221
|
async function downloadThenIngest(args8, country) {
|
|
97742
98222
|
const vimeoCookie = captureVimeoCookie();
|
|
97743
|
-
const workDir = await
|
|
98223
|
+
const workDir = await mkdtemp4(path57.join(tmpdir5(), "videos-ingest-"));
|
|
97744
98224
|
try {
|
|
97745
98225
|
const probe = await probeYtDlp({ url: args8.url, country, vimeoCookie, cookieDir: workDir });
|
|
97746
98226
|
if (isAudioOnly(probe.info)) {
|
|
@@ -97797,7 +98277,7 @@ async function downloadThenIngest(args8, country) {
|
|
|
97797
98277
|
...reducedQuality ? { reducedQuality: true } : {}
|
|
97798
98278
|
};
|
|
97799
98279
|
} finally {
|
|
97800
|
-
await
|
|
98280
|
+
await rm11(workDir, { recursive: true, force: true }).catch(() => {
|
|
97801
98281
|
});
|
|
97802
98282
|
}
|
|
97803
98283
|
}
|
|
@@ -97816,7 +98296,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
|
|
|
97816
98296
|
}
|
|
97817
98297
|
|
|
97818
98298
|
// src/commands/videos/search.ts
|
|
97819
|
-
import { defineCommand as
|
|
98299
|
+
import { defineCommand as defineCommand264 } from "citty";
|
|
97820
98300
|
registerSchema({
|
|
97821
98301
|
command: "videos.search",
|
|
97822
98302
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -97826,7 +98306,7 @@ registerSchema({
|
|
|
97826
98306
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
97827
98307
|
}
|
|
97828
98308
|
});
|
|
97829
|
-
var searchCommand4 =
|
|
98309
|
+
var searchCommand4 = defineCommand264({
|
|
97830
98310
|
meta: {
|
|
97831
98311
|
name: "search",
|
|
97832
98312
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -97878,7 +98358,7 @@ var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
|
97878
98358
|
// src/commands/videos/upload.ts
|
|
97879
98359
|
import { stat as stat13 } from "fs/promises";
|
|
97880
98360
|
import { basename as basename4 } from "path";
|
|
97881
|
-
import { defineCommand as
|
|
98361
|
+
import { defineCommand as defineCommand265 } from "citty";
|
|
97882
98362
|
registerSchema({
|
|
97883
98363
|
command: "videos.upload",
|
|
97884
98364
|
description: "Upload a video to Baker \u2014 a local file (via Mux direct upload) or a remote http(s) URL.",
|
|
@@ -97905,7 +98385,7 @@ registerSchema({
|
|
|
97905
98385
|
function isRemoteUrl3(value2) {
|
|
97906
98386
|
return /^https?:\/\//i.test(value2);
|
|
97907
98387
|
}
|
|
97908
|
-
var uploadCommand2 =
|
|
98388
|
+
var uploadCommand2 = defineCommand265({
|
|
97909
98389
|
meta: {
|
|
97910
98390
|
name: "upload",
|
|
97911
98391
|
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"
|
|
@@ -97974,10 +98454,10 @@ var uploadCommand2 = defineCommand258({
|
|
|
97974
98454
|
});
|
|
97975
98455
|
|
|
97976
98456
|
// src/commands/videos/index.ts
|
|
97977
|
-
var videosCommand =
|
|
98457
|
+
var videosCommand = defineCommand266({
|
|
97978
98458
|
meta: {
|
|
97979
98459
|
name: "videos",
|
|
97980
|
-
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, describe, delete, tags.
|
|
98460
|
+
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, fetch, describe, delete, tags.
|
|
97981
98461
|
|
|
97982
98462
|
Examples:
|
|
97983
98463
|
baker videos search "product demo" --limit 5
|
|
@@ -97985,6 +98465,7 @@ Examples:
|
|
|
97985
98465
|
baker videos get <video-id>
|
|
97986
98466
|
baker videos upload ./demo.mp4
|
|
97987
98467
|
baker videos ingest https://www.youtube.com/watch?v=abc123
|
|
98468
|
+
baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips
|
|
97988
98469
|
baker videos describe <video-id> --description "Customer testimonial, 30s"
|
|
97989
98470
|
baker videos delete <video-id> --dry-run
|
|
97990
98471
|
baker videos tags
|
|
@@ -97996,6 +98477,7 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
97996
98477
|
search: searchCommand4,
|
|
97997
98478
|
upload: uploadCommand2,
|
|
97998
98479
|
ingest: ingestCommand2,
|
|
98480
|
+
fetch: fetchCommand2,
|
|
97999
98481
|
describe: describeCommand2,
|
|
98000
98482
|
delete: deleteCommand4,
|
|
98001
98483
|
tags: tagsCommand6
|
|
@@ -98003,10 +98485,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
98003
98485
|
});
|
|
98004
98486
|
|
|
98005
98487
|
// src/commands/winning-ads/index.ts
|
|
98006
|
-
import { defineCommand as
|
|
98488
|
+
import { defineCommand as defineCommand279 } from "citty";
|
|
98007
98489
|
|
|
98008
98490
|
// src/commands/winning-ads/advertisers.ts
|
|
98009
|
-
import { defineCommand as
|
|
98491
|
+
import { defineCommand as defineCommand267 } from "citty";
|
|
98010
98492
|
|
|
98011
98493
|
// src/commands/winning-ads/shared.ts
|
|
98012
98494
|
function splitList4(value2) {
|
|
@@ -98015,7 +98497,7 @@ function splitList4(value2) {
|
|
|
98015
98497
|
}
|
|
98016
98498
|
return value2.split(",").map((v) => v.trim()).filter(Boolean);
|
|
98017
98499
|
}
|
|
98018
|
-
function
|
|
98500
|
+
function reportError3(err) {
|
|
98019
98501
|
if (err instanceof ApiError) {
|
|
98020
98502
|
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
98021
98503
|
process.exit(1);
|
|
@@ -98059,7 +98541,7 @@ function advertiserNormalizer(record, full) {
|
|
|
98059
98541
|
last_synced_at: record.last_synced_at ?? null
|
|
98060
98542
|
};
|
|
98061
98543
|
}
|
|
98062
|
-
var advertisersCommand2 =
|
|
98544
|
+
var advertisersCommand2 = defineCommand267({
|
|
98063
98545
|
meta: {
|
|
98064
98546
|
name: "advertisers",
|
|
98065
98547
|
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'
|
|
@@ -98111,13 +98593,13 @@ var advertisersCommand2 = defineCommand260({
|
|
|
98111
98593
|
advertiserNormalizer
|
|
98112
98594
|
);
|
|
98113
98595
|
} catch (err) {
|
|
98114
|
-
|
|
98596
|
+
reportError3(err);
|
|
98115
98597
|
}
|
|
98116
98598
|
}
|
|
98117
98599
|
});
|
|
98118
98600
|
|
|
98119
98601
|
// src/commands/winning-ads/brief.ts
|
|
98120
|
-
import { defineCommand as
|
|
98602
|
+
import { defineCommand as defineCommand268 } from "citty";
|
|
98121
98603
|
registerSchema({
|
|
98122
98604
|
command: "winning-ads.brief",
|
|
98123
98605
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -98163,7 +98645,7 @@ function parseDna(raw) {
|
|
|
98163
98645
|
}
|
|
98164
98646
|
return parsed;
|
|
98165
98647
|
}
|
|
98166
|
-
var briefCommand =
|
|
98648
|
+
var briefCommand = defineCommand268({
|
|
98167
98649
|
meta: {
|
|
98168
98650
|
name: "brief",
|
|
98169
98651
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -98193,13 +98675,13 @@ var briefCommand = defineCommand261({
|
|
|
98193
98675
|
const data = await apiPost("/api/ad-library/brief", body);
|
|
98194
98676
|
writeJson({ ok: true, data });
|
|
98195
98677
|
} catch (err) {
|
|
98196
|
-
|
|
98678
|
+
reportError3(err);
|
|
98197
98679
|
}
|
|
98198
98680
|
}
|
|
98199
98681
|
});
|
|
98200
98682
|
|
|
98201
98683
|
// src/commands/winning-ads/content.ts
|
|
98202
|
-
import { defineCommand as
|
|
98684
|
+
import { defineCommand as defineCommand269 } from "citty";
|
|
98203
98685
|
registerSchema({
|
|
98204
98686
|
command: "winning-ads.content",
|
|
98205
98687
|
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. Static and carousel ads return the text drawn into the image with the job each piece does (headline, benefit, cta\u2026), the card it sits on, and their format_pattern. Add --full for how it is built (composition, colours, CTA, markers), how it persuades (awareness, mechanism, pains, desires, proof, objections), what it offers (offer type, price, guarantee, urgency), plus speech, pacing and soundtrack for video.",
|
|
@@ -98212,7 +98694,7 @@ registerSchema({
|
|
|
98212
98694
|
}
|
|
98213
98695
|
}
|
|
98214
98696
|
});
|
|
98215
|
-
var contentCommand =
|
|
98697
|
+
var contentCommand = defineCommand269({
|
|
98216
98698
|
meta: {
|
|
98217
98699
|
name: "content",
|
|
98218
98700
|
description: "Read the transcript + on-screen text + copy of one winning ad; --full adds its build, persuasion and offer. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
@@ -98255,13 +98737,13 @@ var contentCommand = defineCommand262({
|
|
|
98255
98737
|
adContentNormalizer
|
|
98256
98738
|
);
|
|
98257
98739
|
} catch (err) {
|
|
98258
|
-
|
|
98740
|
+
reportError3(err);
|
|
98259
98741
|
}
|
|
98260
98742
|
}
|
|
98261
98743
|
});
|
|
98262
98744
|
|
|
98263
98745
|
// src/commands/winning-ads/feed.ts
|
|
98264
|
-
import { defineCommand as
|
|
98746
|
+
import { defineCommand as defineCommand270 } from "citty";
|
|
98265
98747
|
function buildFeedParams(input) {
|
|
98266
98748
|
const params = {};
|
|
98267
98749
|
const advertiser = splitList4(input.advertiser);
|
|
@@ -98313,7 +98795,7 @@ registerSchema({
|
|
|
98313
98795
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
98314
98796
|
}
|
|
98315
98797
|
});
|
|
98316
|
-
var feedCommand2 =
|
|
98798
|
+
var feedCommand2 = defineCommand270({
|
|
98317
98799
|
meta: {
|
|
98318
98800
|
name: "feed",
|
|
98319
98801
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -98392,13 +98874,13 @@ var feedCommand2 = defineCommand263({
|
|
|
98392
98874
|
`);
|
|
98393
98875
|
}
|
|
98394
98876
|
} catch (err) {
|
|
98395
|
-
|
|
98877
|
+
reportError3(err);
|
|
98396
98878
|
}
|
|
98397
98879
|
}
|
|
98398
98880
|
});
|
|
98399
98881
|
|
|
98400
98882
|
// src/commands/winning-ads/follow.ts
|
|
98401
|
-
import { defineCommand as
|
|
98883
|
+
import { defineCommand as defineCommand271 } from "citty";
|
|
98402
98884
|
var PLATFORMS = adLibraryPlatformSchema.options;
|
|
98403
98885
|
registerSchema({
|
|
98404
98886
|
command: "winning-ads.follow",
|
|
@@ -98413,7 +98895,7 @@ registerSchema({
|
|
|
98413
98895
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
98414
98896
|
}
|
|
98415
98897
|
});
|
|
98416
|
-
var followCommand =
|
|
98898
|
+
var followCommand = defineCommand271({
|
|
98417
98899
|
meta: {
|
|
98418
98900
|
name: "follow",
|
|
98419
98901
|
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'
|
|
@@ -98454,13 +98936,13 @@ var followCommand = defineCommand264({
|
|
|
98454
98936
|
}
|
|
98455
98937
|
writeJson({ ok: true, data, hints: hints2 });
|
|
98456
98938
|
} catch (err) {
|
|
98457
|
-
|
|
98939
|
+
reportError3(err);
|
|
98458
98940
|
}
|
|
98459
98941
|
}
|
|
98460
98942
|
});
|
|
98461
98943
|
|
|
98462
98944
|
// src/commands/winning-ads/follow-competitors.ts
|
|
98463
|
-
import { defineCommand as
|
|
98945
|
+
import { defineCommand as defineCommand272 } from "citty";
|
|
98464
98946
|
var PLATFORMS2 = adLibraryPlatformSchema.options;
|
|
98465
98947
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
98466
98948
|
function buildFollowBatchBody(input) {
|
|
@@ -98493,7 +98975,7 @@ registerSchema({
|
|
|
98493
98975
|
}
|
|
98494
98976
|
}
|
|
98495
98977
|
});
|
|
98496
|
-
var followCompetitorsCommand =
|
|
98978
|
+
var followCompetitorsCommand = defineCommand272({
|
|
98497
98979
|
meta: {
|
|
98498
98980
|
name: "follow-competitors",
|
|
98499
98981
|
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"'
|
|
@@ -98562,13 +99044,13 @@ var followCompetitorsCommand = defineCommand265({
|
|
|
98562
99044
|
}
|
|
98563
99045
|
writeJson({ ok: true, data, hints: hints2.length > 0 ? hints2 : void 0 });
|
|
98564
99046
|
} catch (err) {
|
|
98565
|
-
|
|
99047
|
+
reportError3(err);
|
|
98566
99048
|
}
|
|
98567
99049
|
}
|
|
98568
99050
|
});
|
|
98569
99051
|
|
|
98570
99052
|
// src/commands/winning-ads/following.ts
|
|
98571
|
-
import { defineCommand as
|
|
99053
|
+
import { defineCommand as defineCommand273 } from "citty";
|
|
98572
99054
|
registerSchema({
|
|
98573
99055
|
command: "winning-ads.following",
|
|
98574
99056
|
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.",
|
|
@@ -98622,7 +99104,7 @@ function followingNormalizer(record, full) {
|
|
|
98622
99104
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
98623
99105
|
};
|
|
98624
99106
|
}
|
|
98625
|
-
var followingCommand =
|
|
99107
|
+
var followingCommand = defineCommand273({
|
|
98626
99108
|
meta: {
|
|
98627
99109
|
name: "following",
|
|
98628
99110
|
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"
|
|
@@ -98652,13 +99134,13 @@ var followingCommand = defineCommand266({
|
|
|
98652
99134
|
followingNormalizer
|
|
98653
99135
|
);
|
|
98654
99136
|
} catch (err) {
|
|
98655
|
-
|
|
99137
|
+
reportError3(err);
|
|
98656
99138
|
}
|
|
98657
99139
|
}
|
|
98658
99140
|
});
|
|
98659
99141
|
|
|
98660
99142
|
// src/commands/winning-ads/patterns.ts
|
|
98661
|
-
import { defineCommand as
|
|
99143
|
+
import { defineCommand as defineCommand274 } from "citty";
|
|
98662
99144
|
registerSchema({
|
|
98663
99145
|
command: "winning-ads.patterns",
|
|
98664
99146
|
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.",
|
|
@@ -98697,7 +99179,7 @@ function discriminatorRow(record) {
|
|
|
98697
99179
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
98698
99180
|
};
|
|
98699
99181
|
}
|
|
98700
|
-
var patternsCommand =
|
|
99182
|
+
var patternsCommand = defineCommand274({
|
|
98701
99183
|
meta: {
|
|
98702
99184
|
name: "patterns",
|
|
98703
99185
|
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"
|
|
@@ -98747,13 +99229,13 @@ var patternsCommand = defineCommand267({
|
|
|
98747
99229
|
(record) => discriminatorRow(record)
|
|
98748
99230
|
);
|
|
98749
99231
|
} catch (err) {
|
|
98750
|
-
|
|
99232
|
+
reportError3(err);
|
|
98751
99233
|
}
|
|
98752
99234
|
}
|
|
98753
99235
|
});
|
|
98754
99236
|
|
|
98755
99237
|
// src/commands/winning-ads/search.ts
|
|
98756
|
-
import { defineCommand as
|
|
99238
|
+
import { defineCommand as defineCommand275 } from "citty";
|
|
98757
99239
|
registerSchema({
|
|
98758
99240
|
command: "winning-ads.search",
|
|
98759
99241
|
description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url, and visual/container/mechanism when known) to pick a reference to reproduce. A value outside a closed list (--platform, --format, --winner-category, --awareness, --format-pattern) is refused with error.fix.validValues.",
|
|
@@ -98932,7 +99414,7 @@ function reportSearchError(err) {
|
|
|
98932
99414
|
writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
|
|
98933
99415
|
process.exit(1);
|
|
98934
99416
|
}
|
|
98935
|
-
|
|
99417
|
+
reportError3(err);
|
|
98936
99418
|
}
|
|
98937
99419
|
var FLAG_FOR_FIELD = {
|
|
98938
99420
|
limit: "--limit",
|
|
@@ -98946,8 +99428,8 @@ var FLAG_FOR_FIELD = {
|
|
|
98946
99428
|
first_seen_after: "--first-seen-after",
|
|
98947
99429
|
first_seen_before: "--first-seen-before"
|
|
98948
99430
|
};
|
|
98949
|
-
function flagFor(
|
|
98950
|
-
const field = String(
|
|
99431
|
+
function flagFor(path58) {
|
|
99432
|
+
const field = String(path58[0] === "hard_filters" ? path58[1] : path58[0]);
|
|
98951
99433
|
return FLAG_FOR_FIELD[field] ?? field;
|
|
98952
99434
|
}
|
|
98953
99435
|
function schemaRejection(body) {
|
|
@@ -99021,7 +99503,7 @@ function writeSearchResult(data, opts) {
|
|
|
99021
99503
|
writeOutput({ ok: true, data: rawResults, ...withHints2 }, opts.output, opts.fields, opts.full, winningAdNormalizer);
|
|
99022
99504
|
}
|
|
99023
99505
|
var SEARCH_TIMEOUT_MS = 12e4;
|
|
99024
|
-
var searchCommand5 =
|
|
99506
|
+
var searchCommand5 = defineCommand275({
|
|
99025
99507
|
meta: {
|
|
99026
99508
|
name: "search",
|
|
99027
99509
|
description: "Search winning reference ads. Start here: baker winning-ads search 'B2B SaaS before/after AI automation' --scope followed-first --platform meta --format static --exclude-advertiser adv_123 --output md. A set of references for N concepts in one call: add --diverse --limit N. The best proven ad in one container from any category: --format-pattern comparison_table (no query needed)."
|
|
@@ -99141,7 +99623,7 @@ var searchCommand5 = defineCommand268({
|
|
|
99141
99623
|
});
|
|
99142
99624
|
|
|
99143
99625
|
// src/commands/winning-ads/seeds.ts
|
|
99144
|
-
import { defineCommand as
|
|
99626
|
+
import { defineCommand as defineCommand276 } from "citty";
|
|
99145
99627
|
function leanRow(r) {
|
|
99146
99628
|
return {
|
|
99147
99629
|
key: r.key,
|
|
@@ -99169,7 +99651,7 @@ function makeSeedCommand(opts) {
|
|
|
99169
99651
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
99170
99652
|
}
|
|
99171
99653
|
});
|
|
99172
|
-
return
|
|
99654
|
+
return defineCommand276({
|
|
99173
99655
|
meta: { name: opts.name, description: opts.description },
|
|
99174
99656
|
args: {
|
|
99175
99657
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -99196,7 +99678,7 @@ function makeSeedCommand(opts) {
|
|
|
99196
99678
|
}
|
|
99197
99679
|
writeOutput({ ok: true, data: projected }, output);
|
|
99198
99680
|
} catch (err) {
|
|
99199
|
-
|
|
99681
|
+
reportError3(err);
|
|
99200
99682
|
}
|
|
99201
99683
|
}
|
|
99202
99684
|
});
|
|
@@ -99218,7 +99700,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
99218
99700
|
});
|
|
99219
99701
|
|
|
99220
99702
|
// src/commands/winning-ads/unfollow.ts
|
|
99221
|
-
import { defineCommand as
|
|
99703
|
+
import { defineCommand as defineCommand277 } from "citty";
|
|
99222
99704
|
registerSchema({
|
|
99223
99705
|
command: "winning-ads.unfollow",
|
|
99224
99706
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -99226,7 +99708,7 @@ registerSchema({
|
|
|
99226
99708
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
99227
99709
|
}
|
|
99228
99710
|
});
|
|
99229
|
-
var unfollowCommand =
|
|
99711
|
+
var unfollowCommand = defineCommand277({
|
|
99230
99712
|
meta: {
|
|
99231
99713
|
name: "unfollow",
|
|
99232
99714
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -99241,13 +99723,13 @@ var unfollowCommand = defineCommand270({
|
|
|
99241
99723
|
});
|
|
99242
99724
|
writeJson({ ok: true, data });
|
|
99243
99725
|
} catch (err) {
|
|
99244
|
-
|
|
99726
|
+
reportError3(err);
|
|
99245
99727
|
}
|
|
99246
99728
|
}
|
|
99247
99729
|
});
|
|
99248
99730
|
|
|
99249
99731
|
// src/commands/winning-ads/winners.ts
|
|
99250
|
-
import { defineCommand as
|
|
99732
|
+
import { defineCommand as defineCommand278 } from "citty";
|
|
99251
99733
|
registerSchema({
|
|
99252
99734
|
command: "winning-ads.winners",
|
|
99253
99735
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -99257,7 +99739,7 @@ registerSchema({
|
|
|
99257
99739
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
|
|
99258
99740
|
}
|
|
99259
99741
|
});
|
|
99260
|
-
var winnersCommand =
|
|
99742
|
+
var winnersCommand = defineCommand278({
|
|
99261
99743
|
meta: {
|
|
99262
99744
|
name: "winners",
|
|
99263
99745
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -99301,13 +99783,13 @@ var winnersCommand = defineCommand271({
|
|
|
99301
99783
|
winningAdNormalizer
|
|
99302
99784
|
);
|
|
99303
99785
|
} catch (err) {
|
|
99304
|
-
|
|
99786
|
+
reportError3(err);
|
|
99305
99787
|
}
|
|
99306
99788
|
}
|
|
99307
99789
|
});
|
|
99308
99790
|
|
|
99309
99791
|
// src/commands/winning-ads/index.ts
|
|
99310
|
-
var winningAdsCommand =
|
|
99792
|
+
var winningAdsCommand = defineCommand279({
|
|
99311
99793
|
meta: {
|
|
99312
99794
|
name: "winning-ads",
|
|
99313
99795
|
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.
|
|
@@ -99379,7 +99861,7 @@ function getCliVersion() {
|
|
|
99379
99861
|
}
|
|
99380
99862
|
|
|
99381
99863
|
// src/cli.ts
|
|
99382
|
-
var main =
|
|
99864
|
+
var main = defineCommand280({
|
|
99383
99865
|
meta: {
|
|
99384
99866
|
name: "baker",
|
|
99385
99867
|
version: getCliVersion(),
|
|
@@ -99419,6 +99901,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
99419
99901
|
history: historyCommand3,
|
|
99420
99902
|
hubspot: hubspotCommand,
|
|
99421
99903
|
"winning-ads": winningAdsCommand,
|
|
99904
|
+
"media-sources": mediaSourcesCommand,
|
|
99422
99905
|
mcp: mcpCommand,
|
|
99423
99906
|
schema: schemaCommand2
|
|
99424
99907
|
}
|