@koda-sl/baker-cli 0.375.0-dev.8dac6def3 → 0.376.0-dev.2f68e83cd
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 +7 -1
- package/dist/cli.js +656 -237
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -133,7 +133,7 @@ import {
|
|
|
133
133
|
} from "./chunk-7YNOGIWQ.js";
|
|
134
134
|
|
|
135
135
|
// src/cli.ts
|
|
136
|
-
import { defineCommand as
|
|
136
|
+
import { defineCommand as defineCommand251, runMain } from "citty";
|
|
137
137
|
|
|
138
138
|
// src/cache-flag.ts
|
|
139
139
|
var NO_CACHE_ARG = {
|
|
@@ -6949,6 +6949,152 @@ var researchKeywordMetricsResponseSchema = z22.object({
|
|
|
6949
6949
|
|
|
6950
6950
|
// ../api/src/scheduledAgentRules.ts
|
|
6951
6951
|
import { z as z23 } from "zod";
|
|
6952
|
+
|
|
6953
|
+
// ../api/src/shopify/storeEvents.ts
|
|
6954
|
+
var PRODUCT_FIELDS = [
|
|
6955
|
+
"title",
|
|
6956
|
+
"handle",
|
|
6957
|
+
"status",
|
|
6958
|
+
"published",
|
|
6959
|
+
"price",
|
|
6960
|
+
"price_max",
|
|
6961
|
+
"currency",
|
|
6962
|
+
"collections",
|
|
6963
|
+
"tags",
|
|
6964
|
+
"product_type",
|
|
6965
|
+
"vendor",
|
|
6966
|
+
"product_url",
|
|
6967
|
+
"store"
|
|
6968
|
+
];
|
|
6969
|
+
var STORE_EVENTS = {
|
|
6970
|
+
product_out_of_stock: {
|
|
6971
|
+
label: "A product runs out of stock",
|
|
6972
|
+
sentence: "When a product in your Shopify store runs out of stock",
|
|
6973
|
+
description: "One or more of its options can no longer be bought; whole_product says whether nothing at all can be.",
|
|
6974
|
+
payload: [
|
|
6975
|
+
"title",
|
|
6976
|
+
"handle",
|
|
6977
|
+
"whole_product",
|
|
6978
|
+
"options_out",
|
|
6979
|
+
"options_out_count",
|
|
6980
|
+
"options_count",
|
|
6981
|
+
"promoted_by",
|
|
6982
|
+
"promotions_checked",
|
|
6983
|
+
...PRODUCT_FIELDS.slice(2)
|
|
6984
|
+
],
|
|
6985
|
+
namesProduct: true
|
|
6986
|
+
},
|
|
6987
|
+
product_back_in_stock: {
|
|
6988
|
+
label: "A product is back in stock",
|
|
6989
|
+
sentence: "When a product in your Shopify store is back in stock",
|
|
6990
|
+
description: "Options that ran out can be bought again, or ads were paused for it after it came back.",
|
|
6991
|
+
payload: [
|
|
6992
|
+
"title",
|
|
6993
|
+
"handle",
|
|
6994
|
+
"whole_product_was_out",
|
|
6995
|
+
"options_back",
|
|
6996
|
+
"still_out_count",
|
|
6997
|
+
"stock_holds",
|
|
6998
|
+
"reason",
|
|
6999
|
+
"promoted_by",
|
|
7000
|
+
...PRODUCT_FIELDS.slice(2)
|
|
7001
|
+
],
|
|
7002
|
+
namesProduct: true
|
|
7003
|
+
},
|
|
7004
|
+
product_created: {
|
|
7005
|
+
label: "A new product is added",
|
|
7006
|
+
sentence: "When a new product is added to your Shopify store",
|
|
7007
|
+
description: "A product appears in the store (never during Baker's first import).",
|
|
7008
|
+
payload: [...PRODUCT_FIELDS],
|
|
7009
|
+
namesProduct: true
|
|
7010
|
+
},
|
|
7011
|
+
product_updated: {
|
|
7012
|
+
label: "A product is changed",
|
|
7013
|
+
sentence: "When a product in your Shopify store is changed",
|
|
7014
|
+
description: "Its price, title, status, publication, handle, tags, type, vendor or description changed; stock changes and changes Baker made do not count.",
|
|
7015
|
+
payload: [
|
|
7016
|
+
"title",
|
|
7017
|
+
"handle",
|
|
7018
|
+
"changed",
|
|
7019
|
+
"before_title",
|
|
7020
|
+
"before_price",
|
|
7021
|
+
"before_status",
|
|
7022
|
+
"before_published",
|
|
7023
|
+
"price_changes",
|
|
7024
|
+
...PRODUCT_FIELDS.slice(2)
|
|
7025
|
+
],
|
|
7026
|
+
namesProduct: true
|
|
7027
|
+
},
|
|
7028
|
+
collection_updated: {
|
|
7029
|
+
label: "A collection changes",
|
|
7030
|
+
sentence: "When a collection in your Shopify store changes",
|
|
7031
|
+
description: "A collection is created, renamed, published or unpublished, or gains or loses products.",
|
|
7032
|
+
payload: ["title", "collection", "changed", "product_count", "before_product_count", "published", "store"],
|
|
7033
|
+
namesProduct: false
|
|
7034
|
+
},
|
|
7035
|
+
purchase: {
|
|
7036
|
+
label: "An order is paid",
|
|
7037
|
+
sentence: "When an order is paid",
|
|
7038
|
+
description: "The store's sale; value is the order's total in the store's currency.",
|
|
7039
|
+
payload: ["order_name", "ordered_at", "shopify_source", "visitor_from", "campaign_from", "store"],
|
|
7040
|
+
namesProduct: false
|
|
7041
|
+
},
|
|
7042
|
+
refund: {
|
|
7043
|
+
label: "Money is refunded on an order",
|
|
7044
|
+
sentence: "When money is refunded on an order",
|
|
7045
|
+
description: "Money given back on an order; value is the amount refunded.",
|
|
7046
|
+
payload: ["order_name", "store"],
|
|
7047
|
+
namesProduct: false
|
|
7048
|
+
},
|
|
7049
|
+
customer_created: {
|
|
7050
|
+
label: "A new customer signs up",
|
|
7051
|
+
sentence: "When a new customer account is created in your Shopify store",
|
|
7052
|
+
description: "A new customer account, with their country and whether they accept email \u2014 never a name or address.",
|
|
7053
|
+
payload: ["customer", "country", "accepts_email", "orders", "tags", "account_state", "store"],
|
|
7054
|
+
namesProduct: false
|
|
7055
|
+
},
|
|
7056
|
+
checkout_abandoned: {
|
|
7057
|
+
label: "A checkout is abandoned",
|
|
7058
|
+
sentence: "When a shopper leaves a checkout in your Shopify store without buying",
|
|
7059
|
+
description: "A checkout with contact details was not completed after an hour.",
|
|
7060
|
+
payload: [
|
|
7061
|
+
"total",
|
|
7062
|
+
"currency",
|
|
7063
|
+
"items_count",
|
|
7064
|
+
"products",
|
|
7065
|
+
"product_handles",
|
|
7066
|
+
"known_customer",
|
|
7067
|
+
"customer",
|
|
7068
|
+
"discount_codes_count",
|
|
7069
|
+
"started_at",
|
|
7070
|
+
"last_activity_at",
|
|
7071
|
+
"store"
|
|
7072
|
+
],
|
|
7073
|
+
namesProduct: false
|
|
7074
|
+
},
|
|
7075
|
+
sales_drop: {
|
|
7076
|
+
label: "Sales drop",
|
|
7077
|
+
sentence: "When your Shopify store's sales drop well below usual",
|
|
7078
|
+
description: "The last 6 hours brought far fewer orders than the same hours usually do.",
|
|
7079
|
+
payload: [
|
|
7080
|
+
"window_hours",
|
|
7081
|
+
"window_start",
|
|
7082
|
+
"window_end",
|
|
7083
|
+
"orders",
|
|
7084
|
+
"expected_orders",
|
|
7085
|
+
"revenue",
|
|
7086
|
+
"expected_revenue",
|
|
7087
|
+
"currency",
|
|
7088
|
+
"drop_percent",
|
|
7089
|
+
"baseline_days",
|
|
7090
|
+
"store"
|
|
7091
|
+
],
|
|
7092
|
+
namesProduct: false
|
|
7093
|
+
}
|
|
7094
|
+
};
|
|
7095
|
+
var STORE_EVENT_NAMES = Object.keys(STORE_EVENTS);
|
|
7096
|
+
|
|
7097
|
+
// ../api/src/scheduledAgentRules.ts
|
|
6952
7098
|
var CONDITION_OPERATORS = {
|
|
6953
7099
|
equals: { label: "is", takesValue: true },
|
|
6954
7100
|
not_equals: { label: "is not", takesValue: true },
|
|
@@ -9802,7 +9948,7 @@ import { defineCommand as defineCommand19 } from "citty";
|
|
|
9802
9948
|
function listed(resources) {
|
|
9803
9949
|
return resources.map((resource) => resource.label ? `${resource.id} (${resource.label})` : resource.id).join("; ");
|
|
9804
9950
|
}
|
|
9805
|
-
function connectedResourceHints({ plural, singular, flag: flag3, resources }) {
|
|
9951
|
+
function connectedResourceHints({ plural: plural2, singular, flag: flag3, resources }) {
|
|
9806
9952
|
if (resources.length === 0) {
|
|
9807
9953
|
return [];
|
|
9808
9954
|
}
|
|
@@ -9810,7 +9956,7 @@ function connectedResourceHints({ plural, singular, flag: flag3, resources }) {
|
|
|
9810
9956
|
return [`This company connected one ${singular}: ${listed(resources)}. Commands use it unless you pass ${flag3}.`];
|
|
9811
9957
|
}
|
|
9812
9958
|
return [
|
|
9813
|
-
`This company connected ${resources.length} ${
|
|
9959
|
+
`This company connected ${resources.length} ${plural2}: ${listed(resources)}. Each command works on one, so pass ${flag3} \u2014 nothing is picked for you. A question about the whole business covers all ${resources.length}: answering from one and reporting it as the total is wrong.`
|
|
9814
9960
|
];
|
|
9815
9961
|
}
|
|
9816
9962
|
|
|
@@ -12102,11 +12248,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
12102
12248
|
function rawTextEntries(value, rawArgs) {
|
|
12103
12249
|
return repeatedValues(rawArgs, "text", value).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
12104
12250
|
}
|
|
12105
|
-
function rawFileEntries(
|
|
12106
|
-
if (typeof
|
|
12251
|
+
function rawFileEntries(path49) {
|
|
12252
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12107
12253
|
return [];
|
|
12108
12254
|
}
|
|
12109
|
-
return readFileSync2(
|
|
12255
|
+
return readFileSync2(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12110
12256
|
}
|
|
12111
12257
|
function keywordEntries(args5, rawArgs) {
|
|
12112
12258
|
const defaultMatch = typeof args5["match-type"] === "string" ? args5["match-type"].toUpperCase() : void 0;
|
|
@@ -12129,14 +12275,14 @@ function keywordEntries(args5, rawArgs) {
|
|
|
12129
12275
|
}
|
|
12130
12276
|
return entries;
|
|
12131
12277
|
}
|
|
12132
|
-
function loadJsonFileArg(
|
|
12133
|
-
if (typeof
|
|
12278
|
+
function loadJsonFileArg(path49) {
|
|
12279
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
12134
12280
|
return {};
|
|
12135
12281
|
}
|
|
12136
|
-
const inline =
|
|
12137
|
-
const source = inline ? "inline JSON" :
|
|
12282
|
+
const inline = path49.trimStart().startsWith("{");
|
|
12283
|
+
const source = inline ? "inline JSON" : path49;
|
|
12138
12284
|
try {
|
|
12139
|
-
const parsed = JSON.parse(inline ?
|
|
12285
|
+
const parsed = JSON.parse(inline ? path49 : readFileSync2(path49, "utf8"));
|
|
12140
12286
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12141
12287
|
failWriteValidation(`${source} must contain a JSON object`);
|
|
12142
12288
|
}
|
|
@@ -12273,10 +12419,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
12273
12419
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
12274
12420
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
12275
12421
|
}
|
|
12276
|
-
async function draftAction(
|
|
12422
|
+
async function draftAction(path49, body, chat) {
|
|
12277
12423
|
try {
|
|
12278
12424
|
const chatId = resolveChatId(chat);
|
|
12279
|
-
const response = await apiPost(
|
|
12425
|
+
const response = await apiPost(path49, { chatId, ...body });
|
|
12280
12426
|
writeJsonEnvelope(response);
|
|
12281
12427
|
} catch (err) {
|
|
12282
12428
|
handleGoogleError(err);
|
|
@@ -14694,14 +14840,14 @@ function mappingRowProblem(row) {
|
|
|
14694
14840
|
|
|
14695
14841
|
// ../api/src/event-sources/template.ts
|
|
14696
14842
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
14697
|
-
function mentionOf(
|
|
14698
|
-
return `{{${
|
|
14843
|
+
function mentionOf(path49) {
|
|
14844
|
+
return `{{${path49}}}`;
|
|
14699
14845
|
}
|
|
14700
14846
|
function templateMentions(template) {
|
|
14701
14847
|
const seen = [];
|
|
14702
14848
|
for (const match of template.matchAll(MENTION)) {
|
|
14703
|
-
const
|
|
14704
|
-
if (
|
|
14849
|
+
const path49 = (match[1] ?? "").trim();
|
|
14850
|
+
if (path49 !== "" && !seen.includes(path49)) seen.push(path49);
|
|
14705
14851
|
}
|
|
14706
14852
|
return seen;
|
|
14707
14853
|
}
|
|
@@ -18071,17 +18217,17 @@ function ignoredColumnHints(columns) {
|
|
|
18071
18217
|
`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.`
|
|
18072
18218
|
];
|
|
18073
18219
|
}
|
|
18074
|
-
function readRowsFile(
|
|
18075
|
-
const inline =
|
|
18220
|
+
function readRowsFile(path49) {
|
|
18221
|
+
const inline = path49.trimStart().startsWith("[") || path49.trimStart().startsWith("{");
|
|
18076
18222
|
let text2;
|
|
18077
18223
|
try {
|
|
18078
|
-
text2 = inline ?
|
|
18224
|
+
text2 = inline ? path49 : readFileSync4(path49, "utf8");
|
|
18079
18225
|
} catch (err) {
|
|
18080
|
-
failWriteValidation(`could not read ${
|
|
18226
|
+
failWriteValidation(`could not read ${path49}: ${err instanceof Error ? err.message : String(err)}`);
|
|
18081
18227
|
}
|
|
18082
18228
|
const parsed = parseConversionRowsText(text2);
|
|
18083
18229
|
if (!parsed.ok) {
|
|
18084
|
-
failWriteValidation(`${inline ? "the conversions passed inline" :
|
|
18230
|
+
failWriteValidation(`${inline ? "the conversions passed inline" : path49}: ${parsed.error}`);
|
|
18085
18231
|
}
|
|
18086
18232
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
18087
18233
|
}
|
|
@@ -19956,19 +20102,19 @@ function failWriteValidation2(message) {
|
|
|
19956
20102
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
19957
20103
|
process.exit(1);
|
|
19958
20104
|
}
|
|
19959
|
-
function loadJsonFileArg2(
|
|
19960
|
-
if (typeof
|
|
20105
|
+
function loadJsonFileArg2(path49) {
|
|
20106
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
19961
20107
|
return {};
|
|
19962
20108
|
}
|
|
19963
20109
|
try {
|
|
19964
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20110
|
+
const parsed = JSON.parse(readFileSync5(path49, "utf8"));
|
|
19965
20111
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
19966
|
-
failWriteValidation2(`${
|
|
20112
|
+
failWriteValidation2(`${path49} must contain a JSON object`);
|
|
19967
20113
|
}
|
|
19968
20114
|
return parsed;
|
|
19969
20115
|
} catch (err) {
|
|
19970
20116
|
if (err instanceof SyntaxError) {
|
|
19971
|
-
failWriteValidation2(`${
|
|
20117
|
+
failWriteValidation2(`${path49} is not valid JSON: ${err.message}`);
|
|
19972
20118
|
}
|
|
19973
20119
|
throw err;
|
|
19974
20120
|
}
|
|
@@ -20053,15 +20199,15 @@ function parseLocaleFlag(value) {
|
|
|
20053
20199
|
}
|
|
20054
20200
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
20055
20201
|
}
|
|
20056
|
-
function loadTargetingFileArg(
|
|
20057
|
-
if (typeof
|
|
20202
|
+
function loadTargetingFileArg(path49) {
|
|
20203
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20058
20204
|
return void 0;
|
|
20059
20205
|
}
|
|
20060
|
-
const parsed = loadJsonFileArg2(
|
|
20206
|
+
const parsed = loadJsonFileArg2(path49);
|
|
20061
20207
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
20062
20208
|
if (!criteria.include) {
|
|
20063
20209
|
failWriteValidation2(
|
|
20064
|
-
`${
|
|
20210
|
+
`${path49} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
20065
20211
|
);
|
|
20066
20212
|
}
|
|
20067
20213
|
return criteria;
|
|
@@ -20096,14 +20242,14 @@ function parseCsvLine(line) {
|
|
|
20096
20242
|
cells.push(current);
|
|
20097
20243
|
return cells.map((cell3) => cell3.trim());
|
|
20098
20244
|
}
|
|
20099
|
-
function parseListFileArg(
|
|
20100
|
-
if (typeof
|
|
20245
|
+
function parseListFileArg(path49, maxRows) {
|
|
20246
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20101
20247
|
return void 0;
|
|
20102
20248
|
}
|
|
20103
|
-
const raw = readFileSync5(
|
|
20249
|
+
const raw = readFileSync5(path49, "utf8");
|
|
20104
20250
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
20105
20251
|
if (lines.length < 2) {
|
|
20106
|
-
failWriteValidation2(`${
|
|
20252
|
+
failWriteValidation2(`${path49} needs a header row and at least one data row`);
|
|
20107
20253
|
}
|
|
20108
20254
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
20109
20255
|
const rows = [];
|
|
@@ -20122,7 +20268,7 @@ function parseListFileArg(path48, maxRows) {
|
|
|
20122
20268
|
}
|
|
20123
20269
|
}
|
|
20124
20270
|
if (rows.length > maxRows) {
|
|
20125
|
-
failWriteValidation2(`${
|
|
20271
|
+
failWriteValidation2(`${path49} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
20126
20272
|
}
|
|
20127
20273
|
return { columns, rows };
|
|
20128
20274
|
}
|
|
@@ -20218,11 +20364,11 @@ function readPositionals(args5) {
|
|
|
20218
20364
|
function splitIdList(raw) {
|
|
20219
20365
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
20220
20366
|
}
|
|
20221
|
-
function idsFileEntries(
|
|
20222
|
-
if (typeof
|
|
20367
|
+
function idsFileEntries(path49) {
|
|
20368
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
20223
20369
|
return [];
|
|
20224
20370
|
}
|
|
20225
|
-
return readFileSync5(
|
|
20371
|
+
return readFileSync5(path49, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
20226
20372
|
}
|
|
20227
20373
|
function requireTargets(args5, entity) {
|
|
20228
20374
|
const positionals = readPositionals(args5);
|
|
@@ -23022,9 +23168,9 @@ function compactRow(row) {
|
|
|
23022
23168
|
...destination.postUrn ? { postUrn: destination.postUrn } : {}
|
|
23023
23169
|
};
|
|
23024
23170
|
}
|
|
23025
|
-
function readPath2(row,
|
|
23171
|
+
function readPath2(row, path49) {
|
|
23026
23172
|
let current = row;
|
|
23027
|
-
for (const segment of
|
|
23173
|
+
for (const segment of path49.split(".")) {
|
|
23028
23174
|
const record = asRecord(current);
|
|
23029
23175
|
if (!record) return void 0;
|
|
23030
23176
|
current = record[segment];
|
|
@@ -23034,10 +23180,10 @@ function readPath2(row, path48) {
|
|
|
23034
23180
|
function projectFields(rows, paths) {
|
|
23035
23181
|
return rows.map((row) => {
|
|
23036
23182
|
const projected = {};
|
|
23037
|
-
for (const
|
|
23038
|
-
const value = readPath2(row,
|
|
23183
|
+
for (const path49 of paths) {
|
|
23184
|
+
const value = readPath2(row, path49);
|
|
23039
23185
|
if (value !== void 0) {
|
|
23040
|
-
projected[
|
|
23186
|
+
projected[path49] = value;
|
|
23041
23187
|
}
|
|
23042
23188
|
}
|
|
23043
23189
|
return projected;
|
|
@@ -24188,54 +24334,54 @@ function buildCustomConversionRule(input) {
|
|
|
24188
24334
|
function customConversionRuleRefusal(rule) {
|
|
24189
24335
|
return ruleNodeRefusal(rule, "rule");
|
|
24190
24336
|
}
|
|
24191
|
-
function branchRefusal(key, value,
|
|
24337
|
+
function branchRefusal(key, value, path49) {
|
|
24192
24338
|
if (!Array.isArray(value) || value.length === 0) {
|
|
24193
|
-
return `${
|
|
24339
|
+
return `${path49}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
24194
24340
|
}
|
|
24195
24341
|
for (const [index, child] of value.entries()) {
|
|
24196
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
24342
|
+
const refusal = ruleNodeRefusal(child, `${path49}.${key}[${index}]`);
|
|
24197
24343
|
if (refusal) {
|
|
24198
24344
|
return refusal;
|
|
24199
24345
|
}
|
|
24200
24346
|
}
|
|
24201
24347
|
return void 0;
|
|
24202
24348
|
}
|
|
24203
|
-
function conditionRefusal(key, value,
|
|
24204
|
-
return key === "and" || key === "or" ? branchRefusal(key, value,
|
|
24349
|
+
function conditionRefusal(key, value, path49) {
|
|
24350
|
+
return key === "and" || key === "or" ? branchRefusal(key, value, path49) : leafRefusal(key, value, path49);
|
|
24205
24351
|
}
|
|
24206
|
-
function ruleNodeRefusal(node,
|
|
24352
|
+
function ruleNodeRefusal(node, path49) {
|
|
24207
24353
|
if (!isRecord2(node)) {
|
|
24208
|
-
return `${
|
|
24354
|
+
return `${path49} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
24209
24355
|
}
|
|
24210
24356
|
const entries = Object.entries(node);
|
|
24211
24357
|
if (entries.length === 0) {
|
|
24212
|
-
return `${
|
|
24358
|
+
return `${path49} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
24213
24359
|
}
|
|
24214
24360
|
if (entries.length > 1) {
|
|
24215
|
-
return `${
|
|
24361
|
+
return `${path49} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
|
|
24216
24362
|
}
|
|
24217
24363
|
for (const [key, value] of entries) {
|
|
24218
|
-
const refusal = conditionRefusal(key, value,
|
|
24364
|
+
const refusal = conditionRefusal(key, value, path49);
|
|
24219
24365
|
if (refusal) {
|
|
24220
24366
|
return refusal;
|
|
24221
24367
|
}
|
|
24222
24368
|
}
|
|
24223
24369
|
return void 0;
|
|
24224
24370
|
}
|
|
24225
|
-
function leafRefusal(field, condition,
|
|
24371
|
+
function leafRefusal(field, condition, path49) {
|
|
24226
24372
|
if (!isRecord2(condition)) {
|
|
24227
|
-
return `${
|
|
24373
|
+
return `${path49}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
24228
24374
|
}
|
|
24229
24375
|
const tests = Object.entries(condition);
|
|
24230
24376
|
if (tests.length === 0) {
|
|
24231
|
-
return `${
|
|
24377
|
+
return `${path49}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
24232
24378
|
}
|
|
24233
24379
|
if (tests.length > 1) {
|
|
24234
|
-
return `${
|
|
24380
|
+
return `${path49}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
|
|
24235
24381
|
}
|
|
24236
24382
|
for (const [operator] of tests) {
|
|
24237
24383
|
if (!RULE_OPERATORS[operator]) {
|
|
24238
|
-
return `${
|
|
24384
|
+
return `${path49}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
|
|
24239
24385
|
}
|
|
24240
24386
|
}
|
|
24241
24387
|
return void 0;
|
|
@@ -24950,11 +25096,11 @@ var updateStatusSchema = z36.enum(UPDATE_STATUSES);
|
|
|
24950
25096
|
function currencyMinimums2(currencyCode) {
|
|
24951
25097
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
24952
25098
|
}
|
|
24953
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
25099
|
+
function validateDailyBudgetFloor(money, ctx, path49) {
|
|
24954
25100
|
if (money?.currencyCode) {
|
|
24955
25101
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
24956
25102
|
if (Number(money.amount) < min) {
|
|
24957
|
-
ctx.addIssue({ code: "custom", path:
|
|
25103
|
+
ctx.addIssue({ code: "custom", path: path49, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
24958
25104
|
}
|
|
24959
25105
|
}
|
|
24960
25106
|
}
|
|
@@ -25816,19 +25962,19 @@ function failWriteValidation3(message) {
|
|
|
25816
25962
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
25817
25963
|
process.exit(1);
|
|
25818
25964
|
}
|
|
25819
|
-
function loadJsonFileArg3(
|
|
25820
|
-
if (typeof
|
|
25965
|
+
function loadJsonFileArg3(path49) {
|
|
25966
|
+
if (typeof path49 !== "string" || path49.length === 0) {
|
|
25821
25967
|
return {};
|
|
25822
25968
|
}
|
|
25823
25969
|
try {
|
|
25824
|
-
const parsed = JSON.parse(readFileSync9(
|
|
25970
|
+
const parsed = JSON.parse(readFileSync9(path49, "utf8"));
|
|
25825
25971
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
25826
|
-
failWriteValidation3(`${
|
|
25972
|
+
failWriteValidation3(`${path49} must contain a JSON object`);
|
|
25827
25973
|
}
|
|
25828
25974
|
return parsed;
|
|
25829
25975
|
} catch (err) {
|
|
25830
25976
|
if (err instanceof SyntaxError) {
|
|
25831
|
-
failWriteValidation3(`${
|
|
25977
|
+
failWriteValidation3(`${path49} is not valid JSON: ${err.message}`);
|
|
25832
25978
|
}
|
|
25833
25979
|
throw err;
|
|
25834
25980
|
}
|
|
@@ -31429,12 +31575,12 @@ function flowExists(slug) {
|
|
|
31429
31575
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
31430
31576
|
}
|
|
31431
31577
|
function readFlowTree(slug) {
|
|
31432
|
-
const
|
|
31433
|
-
if (!existsSync3(
|
|
31578
|
+
const path49 = join2(flowsDir(), slug, "_data.json");
|
|
31579
|
+
if (!existsSync3(path49)) {
|
|
31434
31580
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
31435
31581
|
}
|
|
31436
31582
|
try {
|
|
31437
|
-
return JSON.parse(readFileSync11(
|
|
31583
|
+
return JSON.parse(readFileSync11(path49, "utf-8"));
|
|
31438
31584
|
} catch (error) {
|
|
31439
31585
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
31440
31586
|
}
|
|
@@ -32327,12 +32473,12 @@ function readPeopleFile(args5) {
|
|
|
32327
32473
|
}
|
|
32328
32474
|
function unreadablePeopleFile(args5) {
|
|
32329
32475
|
if (!args5["people-file"]) return void 0;
|
|
32330
|
-
const
|
|
32476
|
+
const path49 = String(args5["people-file"]);
|
|
32331
32477
|
try {
|
|
32332
|
-
readFileSync12(
|
|
32478
|
+
readFileSync12(path49, "utf8");
|
|
32333
32479
|
return void 0;
|
|
32334
32480
|
} catch {
|
|
32335
|
-
return `Couldn't read --people-file ${
|
|
32481
|
+
return `Couldn't read --people-file ${path49}. Check the path, or pass the people inline with --person.`;
|
|
32336
32482
|
}
|
|
32337
32483
|
}
|
|
32338
32484
|
function peopleLimitError(args5) {
|
|
@@ -33304,11 +33450,11 @@ function parseFieldArgs(argv) {
|
|
|
33304
33450
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
33305
33451
|
const eq = pair.indexOf("=");
|
|
33306
33452
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
33307
|
-
const
|
|
33453
|
+
const path49 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
33308
33454
|
const problem = mappingRowProblem(field);
|
|
33309
33455
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
33310
|
-
if (
|
|
33311
|
-
mapping[field] =
|
|
33456
|
+
if (path49 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
33457
|
+
mapping[field] = path49;
|
|
33312
33458
|
}
|
|
33313
33459
|
return mapping;
|
|
33314
33460
|
}
|
|
@@ -34905,11 +35051,11 @@ function unwrap(response) {
|
|
|
34905
35051
|
}
|
|
34906
35052
|
return response.data;
|
|
34907
35053
|
}
|
|
34908
|
-
async function readAvatars(
|
|
34909
|
-
return unwrap(await apiGet(
|
|
35054
|
+
async function readAvatars(path49, params2) {
|
|
35055
|
+
return unwrap(await apiGet(path49, params2));
|
|
34910
35056
|
}
|
|
34911
|
-
async function writeAvatars(
|
|
34912
|
-
return unwrap(await apiPost(
|
|
35057
|
+
async function writeAvatars(path49, body) {
|
|
35058
|
+
return unwrap(await apiPost(path49, body));
|
|
34913
35059
|
}
|
|
34914
35060
|
|
|
34915
35061
|
// src/commands/avatars/create.ts
|
|
@@ -35818,12 +35964,12 @@ function missingFontFiles(urls, available) {
|
|
|
35818
35964
|
function planFontAdoption(sources, families) {
|
|
35819
35965
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
35820
35966
|
const byFamily = /* @__PURE__ */ new Map();
|
|
35821
|
-
for (const { path:
|
|
35822
|
-
const dir = posix.dirname(
|
|
35967
|
+
for (const { path: path49, source } of sources) {
|
|
35968
|
+
const dir = posix.dirname(path49);
|
|
35823
35969
|
for (const face of declaredFontFaces(source)) {
|
|
35824
35970
|
if (!wanted.has(face.family)) continue;
|
|
35825
35971
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
35826
|
-
perFile.set(
|
|
35972
|
+
perFile.set(path49, [...perFile.get(path49) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
35827
35973
|
byFamily.set(face.family, perFile);
|
|
35828
35974
|
}
|
|
35829
35975
|
}
|
|
@@ -36023,9 +36169,9 @@ function fontsourceFamilies(css) {
|
|
|
36023
36169
|
return out;
|
|
36024
36170
|
}
|
|
36025
36171
|
function asAuthored(css, normalized) {
|
|
36026
|
-
const
|
|
36172
|
+
const escaped2 = normalized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
36027
36173
|
const text2 = stripCssComments(css);
|
|
36028
|
-
return text2.match(new RegExp(`["']${
|
|
36174
|
+
return text2.match(new RegExp(`["']${escaped2}["']`, "i"))?.[0]?.slice(1, -1) ?? text2.match(new RegExp(`(?<![\\w-])${escaped2}(?![\\w-])`, "i"))?.[0] ?? normalized;
|
|
36029
36175
|
}
|
|
36030
36176
|
function unresolvedBrandFamilies(css) {
|
|
36031
36177
|
const declared = [...parseBrandTokens(css, "").fonts].filter((family) => !GENERIC_FAMILIES.has(family));
|
|
@@ -41015,10 +41161,10 @@ function runDirsToPrune(entries, keep, currentRunId) {
|
|
|
41015
41161
|
return runs.slice(0, Math.max(0, runs.length - keep));
|
|
41016
41162
|
}
|
|
41017
41163
|
async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
41018
|
-
const { readdir:
|
|
41164
|
+
const { readdir: readdir17 } = await import("fs/promises");
|
|
41019
41165
|
let entries;
|
|
41020
41166
|
try {
|
|
41021
|
-
entries = await
|
|
41167
|
+
entries = await readdir17(outputsDir);
|
|
41022
41168
|
} catch {
|
|
41023
41169
|
return;
|
|
41024
41170
|
}
|
|
@@ -48607,10 +48753,10 @@ function parseValueExpression(raw) {
|
|
|
48607
48753
|
return parts.map(parsePart);
|
|
48608
48754
|
}
|
|
48609
48755
|
function trackingFieldIds() {
|
|
48610
|
-
const
|
|
48611
|
-
if (!existsSync6(
|
|
48756
|
+
const path49 = join4(flowsDir(), "..", "tracking.ts");
|
|
48757
|
+
if (!existsSync6(path49)) return null;
|
|
48612
48758
|
try {
|
|
48613
|
-
const source = readFileSync14(
|
|
48759
|
+
const source = readFileSync14(path49, "utf-8");
|
|
48614
48760
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
48615
48761
|
if (!block2) return null;
|
|
48616
48762
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -49184,13 +49330,13 @@ function specsFromFile(parsed) {
|
|
|
49184
49330
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
49185
49331
|
});
|
|
49186
49332
|
}
|
|
49187
|
-
function readSpecFile(
|
|
49333
|
+
function readSpecFile(path49) {
|
|
49188
49334
|
let raw;
|
|
49189
49335
|
try {
|
|
49190
|
-
raw =
|
|
49336
|
+
raw = path49 === "-" ? readFileSync15(0, "utf-8") : readFileSync15(path49, "utf-8");
|
|
49191
49337
|
} catch (error) {
|
|
49192
49338
|
refuse(
|
|
49193
|
-
`Could not read ${
|
|
49339
|
+
`Could not read ${path49 === "-" ? "the mapping from stdin" : `"${path49}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
49194
49340
|
);
|
|
49195
49341
|
}
|
|
49196
49342
|
let parsed;
|
|
@@ -49198,7 +49344,7 @@ function readSpecFile(path48) {
|
|
|
49198
49344
|
parsed = JSON.parse(raw);
|
|
49199
49345
|
} catch (error) {
|
|
49200
49346
|
refuse(
|
|
49201
|
-
`${
|
|
49347
|
+
`${path49 === "-" ? "stdin" : `"${path49}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
49202
49348
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
49203
49349
|
);
|
|
49204
49350
|
}
|
|
@@ -49497,21 +49643,21 @@ var ARRAY_FIELDS = [
|
|
|
49497
49643
|
"tagIds"
|
|
49498
49644
|
];
|
|
49499
49645
|
var ARRAY_OWNERS = ["", "body"];
|
|
49500
|
-
function dropUnsetOptionals(sideEffect,
|
|
49646
|
+
function dropUnsetOptionals(sideEffect, path49) {
|
|
49501
49647
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
49502
49648
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
49503
49649
|
delete sideEffect[key];
|
|
49504
|
-
return [{ path:
|
|
49650
|
+
return [{ path: path49, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
49505
49651
|
});
|
|
49506
49652
|
}
|
|
49507
|
-
function fillNulledArrays(target2, prefix,
|
|
49653
|
+
function fillNulledArrays(target2, prefix, path49) {
|
|
49508
49654
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
49509
49655
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
49510
49656
|
target2[key] = [];
|
|
49511
|
-
return [{ path:
|
|
49657
|
+
return [{ path: path49, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
49512
49658
|
});
|
|
49513
49659
|
}
|
|
49514
|
-
function tidyEmailRecipients(sideEffect,
|
|
49660
|
+
function tidyEmailRecipients(sideEffect, path49) {
|
|
49515
49661
|
if (sideEffect.type !== "email") return [];
|
|
49516
49662
|
const config = sideEffect.encryptedConfig;
|
|
49517
49663
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -49522,7 +49668,7 @@ function tidyEmailRecipients(sideEffect, path48) {
|
|
|
49522
49668
|
const tidied = to.join(", ");
|
|
49523
49669
|
if (tidied === raw) return [];
|
|
49524
49670
|
config.email = tidied;
|
|
49525
|
-
return [{ path:
|
|
49671
|
+
return [{ path: path49, change: "tidied the recipient list's spacing and separators" }];
|
|
49526
49672
|
}
|
|
49527
49673
|
function sideEffectsOf(node) {
|
|
49528
49674
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -49531,13 +49677,13 @@ function sideEffectsOf(node) {
|
|
|
49531
49677
|
);
|
|
49532
49678
|
}
|
|
49533
49679
|
function normalizeSideEffect(sideEffect, where) {
|
|
49534
|
-
const
|
|
49680
|
+
const path49 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
49535
49681
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
49536
49682
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
49537
49683
|
if (!target2 || typeof target2 !== "object") return [];
|
|
49538
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
49684
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path49);
|
|
49539
49685
|
});
|
|
49540
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
49686
|
+
return [...dropUnsetOptionals(sideEffect, path49), ...arrays, ...tidyEmailRecipients(sideEffect, path49)];
|
|
49541
49687
|
}
|
|
49542
49688
|
function normalizeFlowTree(tree) {
|
|
49543
49689
|
const changes = [];
|
|
@@ -50927,10 +51073,10 @@ async function stageOps(ops) {
|
|
|
50927
51073
|
handleError5(err);
|
|
50928
51074
|
}
|
|
50929
51075
|
}
|
|
50930
|
-
async function draftAction2(
|
|
51076
|
+
async function draftAction2(path49, body, chat) {
|
|
50931
51077
|
const chatId = resolveChatId(chat);
|
|
50932
51078
|
try {
|
|
50933
|
-
const data = await apiPost(
|
|
51079
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
50934
51080
|
writeJsonEnvelope({ ok: true, data });
|
|
50935
51081
|
return data;
|
|
50936
51082
|
} catch (err) {
|
|
@@ -53459,9 +53605,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
53459
53605
|
}
|
|
53460
53606
|
return readFile28(pathOrUrl);
|
|
53461
53607
|
}
|
|
53462
|
-
async function isDirectory(
|
|
53608
|
+
async function isDirectory(path49) {
|
|
53463
53609
|
try {
|
|
53464
|
-
const s = await stat7(
|
|
53610
|
+
const s = await stat7(path49);
|
|
53465
53611
|
return s.isDirectory();
|
|
53466
53612
|
} catch {
|
|
53467
53613
|
return false;
|
|
@@ -53889,13 +54035,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
53889
54035
|
}
|
|
53890
54036
|
function disambiguate(paths) {
|
|
53891
54037
|
const taken = /* @__PURE__ */ new Set();
|
|
53892
|
-
return paths.map((
|
|
53893
|
-
if (!taken.has(
|
|
53894
|
-
taken.add(
|
|
53895
|
-
return
|
|
54038
|
+
return paths.map((path49) => {
|
|
54039
|
+
if (!taken.has(path49)) {
|
|
54040
|
+
taken.add(path49);
|
|
54041
|
+
return path49;
|
|
53896
54042
|
}
|
|
53897
|
-
const ext = extname3(
|
|
53898
|
-
const stem =
|
|
54043
|
+
const ext = extname3(path49);
|
|
54044
|
+
const stem = path49.slice(0, path49.length - ext.length);
|
|
53899
54045
|
let n = 2;
|
|
53900
54046
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
53901
54047
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -54021,10 +54167,10 @@ async function runDownloads(plan) {
|
|
|
54021
54167
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
54022
54168
|
const downloaded = [];
|
|
54023
54169
|
for (const [index, item] of fetched.entries()) {
|
|
54024
|
-
const
|
|
54170
|
+
const path49 = paths[index] ?? item.path;
|
|
54025
54171
|
try {
|
|
54026
|
-
await atomicWrite(
|
|
54027
|
-
downloaded.push({ input: item.input, output:
|
|
54172
|
+
await atomicWrite(path49, item.buffer);
|
|
54173
|
+
downloaded.push({ input: item.input, output: path49, bytes: item.buffer.length, contentType: item.contentType });
|
|
54028
54174
|
} catch (err) {
|
|
54029
54175
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
54030
54176
|
}
|
|
@@ -63938,7 +64084,7 @@ var createCommand3 = defineCommand197({
|
|
|
63938
64084
|
if (template.length === 0 && (!prompt || prompt.trim().length === 0)) {
|
|
63939
64085
|
failValidation4("--prompt is required: it is the whole of what a run does. Or pass --template to copy a brief.");
|
|
63940
64086
|
}
|
|
63941
|
-
const trigger = buildTriggerBody(args5, { required:
|
|
64087
|
+
const trigger = buildTriggerBody(args5, { required: template.length === 0 });
|
|
63942
64088
|
const reaction = reactionBody(args5);
|
|
63943
64089
|
const body = {
|
|
63944
64090
|
chatId: requireChatId(),
|
|
@@ -64623,7 +64769,7 @@ var schemaCommand2 = defineCommand208({
|
|
|
64623
64769
|
});
|
|
64624
64770
|
|
|
64625
64771
|
// src/commands/shopify/index.ts
|
|
64626
|
-
import { defineCommand as
|
|
64772
|
+
import { defineCommand as defineCommand211 } from "citty";
|
|
64627
64773
|
|
|
64628
64774
|
// src/commands/shopify/buyers.ts
|
|
64629
64775
|
import { defineCommand as defineCommand209 } from "citty";
|
|
@@ -65931,7 +66077,8 @@ function timingHints(answer) {
|
|
|
65931
66077
|
const peak = [...answer.rows].sort((a, b) => b.orders - a.orders)[0];
|
|
65932
66078
|
if (!peak || peak.orders === 0) return [];
|
|
65933
66079
|
const zone = answer.window.timezone ? `, ${answer.window.timezone}` : "";
|
|
65934
|
-
|
|
66080
|
+
const when = answer.by === "hour" ? `at ${peak.label}` : answer.by === "month_of_year" ? `in ${peak.label}` : `on ${peak.label}`;
|
|
66081
|
+
return [`Most orders are placed ${when} (store time${zone}): weight budgets and sends towards it.`];
|
|
65935
66082
|
}
|
|
65936
66083
|
function salesHints(answer) {
|
|
65937
66084
|
const hints2 = [];
|
|
@@ -66270,6 +66417,273 @@ var segmentsCommand = defineCommand209({
|
|
|
66270
66417
|
}
|
|
66271
66418
|
});
|
|
66272
66419
|
|
|
66420
|
+
// src/commands/shopify/promotions.ts
|
|
66421
|
+
import { defineCommand as defineCommand210 } from "citty";
|
|
66422
|
+
|
|
66423
|
+
// src/commands/shopify/landingLinks.ts
|
|
66424
|
+
import { readdir as readdir16, readFile as readFile33, stat as stat11 } from "fs/promises";
|
|
66425
|
+
import path47 from "path";
|
|
66426
|
+
var PAGES_MAX = 300;
|
|
66427
|
+
var FILE_BYTES_MAX = 256 * 1024;
|
|
66428
|
+
function escaped(text2) {
|
|
66429
|
+
return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
66430
|
+
}
|
|
66431
|
+
function evidenceIn(text2, keys) {
|
|
66432
|
+
const evidence = [];
|
|
66433
|
+
if (keys.buyUrls.some((url) => url && text2.includes(url))) evidence.push("buy_link");
|
|
66434
|
+
const page = new RegExp(`/products/${escaped(keys.handle)}(?![A-Za-z0-9_-])`, "i");
|
|
66435
|
+
if (keys.handle && page.test(text2)) evidence.push("product_page");
|
|
66436
|
+
const option = keys.variantIds.some(
|
|
66437
|
+
(id) => new RegExp(`(?:/cart/(?:\\d+:\\d+,)*${id}:|variant=${id}(?!\\d))`).test(text2)
|
|
66438
|
+
);
|
|
66439
|
+
if (option) evidence.push("variant_id");
|
|
66440
|
+
return evidence;
|
|
66441
|
+
}
|
|
66442
|
+
function landingLinksOf(pages, keys) {
|
|
66443
|
+
const bySlug = /* @__PURE__ */ new Map();
|
|
66444
|
+
for (const page of pages) {
|
|
66445
|
+
const found = new Set(page.files.flatMap((file) => evidenceIn(file.text, keys)));
|
|
66446
|
+
if (found.size === 0) continue;
|
|
66447
|
+
const slug = page.slug.replace(/--\d+$/, "");
|
|
66448
|
+
const held = bySlug.get(slug) ?? /* @__PURE__ */ new Set();
|
|
66449
|
+
for (const evidence of found) held.add(evidence);
|
|
66450
|
+
bySlug.set(slug, held);
|
|
66451
|
+
}
|
|
66452
|
+
const order = ["buy_link", "product_page", "variant_id"];
|
|
66453
|
+
return [...bySlug].map(([slug, evidence]) => ({ slug, evidence: order.filter((entry) => evidence.has(entry)) }));
|
|
66454
|
+
}
|
|
66455
|
+
async function isDir4(target2) {
|
|
66456
|
+
try {
|
|
66457
|
+
return (await stat11(target2)).isDirectory();
|
|
66458
|
+
} catch {
|
|
66459
|
+
return false;
|
|
66460
|
+
}
|
|
66461
|
+
}
|
|
66462
|
+
async function readWorkspacePages(root) {
|
|
66463
|
+
const dir = path47.join(root, "src/pages");
|
|
66464
|
+
if (!await isDir4(dir)) return null;
|
|
66465
|
+
let entries;
|
|
66466
|
+
try {
|
|
66467
|
+
entries = await readdir16(dir, { withFileTypes: true });
|
|
66468
|
+
} catch {
|
|
66469
|
+
return null;
|
|
66470
|
+
}
|
|
66471
|
+
const slugs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("_")).map((entry) => entry.name);
|
|
66472
|
+
const pages = [];
|
|
66473
|
+
for (const slug of slugs.slice(0, PAGES_MAX)) {
|
|
66474
|
+
const files = [];
|
|
66475
|
+
for (const file of await landingGraphFiles(root, slug)) {
|
|
66476
|
+
try {
|
|
66477
|
+
const absolute = path47.join(root, file);
|
|
66478
|
+
if ((await stat11(absolute)).size > FILE_BYTES_MAX) continue;
|
|
66479
|
+
files.push({ path: file, text: await readFile33(absolute, "utf8") });
|
|
66480
|
+
} catch {
|
|
66481
|
+
}
|
|
66482
|
+
}
|
|
66483
|
+
pages.push({ slug, files });
|
|
66484
|
+
}
|
|
66485
|
+
return { pages, skipped: Math.max(0, slugs.length - PAGES_MAX) };
|
|
66486
|
+
}
|
|
66487
|
+
|
|
66488
|
+
// src/commands/shopify/promotionHints.ts
|
|
66489
|
+
var PLATFORM = { "google-ads": "Google Ads", meta: "Meta" };
|
|
66490
|
+
function plural(count2, one, many = `${one}s`) {
|
|
66491
|
+
return `${count2} ${count2 === 1 ? one : many}`;
|
|
66492
|
+
}
|
|
66493
|
+
function pauseCommand2(ad) {
|
|
66494
|
+
if (ad.platform === "meta") return `\`baker ads meta ads pause ${ad.id ?? "<id>"}\``;
|
|
66495
|
+
const target2 = `${ad.resource ?? "<resource>"} --customer-id ${ad.account_id ?? "<account_id>"}`;
|
|
66496
|
+
return ad.level === "asset_group" ? `\`baker ads google asset-groups update ${target2} --status PAUSED\`` : `\`baker ads google ads pause ${target2}\``;
|
|
66497
|
+
}
|
|
66498
|
+
function pauseHint(answer) {
|
|
66499
|
+
const active = answer.ads.filter((ad) => ad.status === "active");
|
|
66500
|
+
if (answer.product.stock === "in_stock" || active.length === 0) return null;
|
|
66501
|
+
const one = active.length === 1;
|
|
66502
|
+
const remembered = answer.remembered ? " A pause is remembered for this product only because you read its promotions here." : "";
|
|
66503
|
+
return `${plural(active.length, "active ad")} still ${one ? "sends" : "send"} people to \u201C${answer.product.title}\u201D, which is out of stock. Stage pausing ${one ? "it" : "them"}: ${active.map(pauseCommand2).join("; ")}.${remembered}`;
|
|
66504
|
+
}
|
|
66505
|
+
function promotionHints(answer, scan) {
|
|
66506
|
+
const hints2 = [];
|
|
66507
|
+
const pause = pauseHint(answer);
|
|
66508
|
+
if (pause) hints2.push(pause);
|
|
66509
|
+
if (answer.shopping.length > 0 || answer.catalog_ads > 0) {
|
|
66510
|
+
hints2.push(
|
|
66511
|
+
"Shopping campaigns and catalog ads stop showing a product nobody can buy by themselves \u2014 never pause them for one product."
|
|
66512
|
+
);
|
|
66513
|
+
}
|
|
66514
|
+
for (const missed of answer.checked.not_checked) {
|
|
66515
|
+
hints2.push(
|
|
66516
|
+
`${PLATFORM[missed.platform] ?? missed.platform} could not be checked (${missed.reason}); say so rather than that nothing runs there.`
|
|
66517
|
+
);
|
|
66518
|
+
}
|
|
66519
|
+
for (const landing of answer.landings.filter((entry) => !entry.published)) {
|
|
66520
|
+
hints2.push(`/${landing.slug} links to this product but is not live; no ad can send people to it yet.`);
|
|
66521
|
+
}
|
|
66522
|
+
if (answer.ads.length === 0 && answer.landings.length === 0 && answer.shopping.length === 0) {
|
|
66523
|
+
hints2.push(`Nothing advertises \u201C${answer.product.title}\u201D that Baker can see: nothing to pause.`);
|
|
66524
|
+
}
|
|
66525
|
+
if (!scan.scanned) {
|
|
66526
|
+
hints2.push(
|
|
66527
|
+
"This workspace's pages were not read (no src/pages here), so landings are from Baker's last scan and measured visits only."
|
|
66528
|
+
);
|
|
66529
|
+
} else if (scan.skippedPages > 0) {
|
|
66530
|
+
hints2.push(`${plural(scan.skippedPages, "page")} not checked for links to this product (past the 300-page bound).`);
|
|
66531
|
+
}
|
|
66532
|
+
if (!answer.remembered) {
|
|
66533
|
+
hints2.push(
|
|
66534
|
+
"This read was not remembered for a Session (no chat): a pause staged from it will not be undone when the product is back."
|
|
66535
|
+
);
|
|
66536
|
+
}
|
|
66537
|
+
return hints2;
|
|
66538
|
+
}
|
|
66539
|
+
function holdName(hold) {
|
|
66540
|
+
return `${PLATFORM[hold.platform]} ${hold.level.replace("_", " ")} ${hold.name ? `\u201C${hold.name}\u201D` : hold.entity_id}`;
|
|
66541
|
+
}
|
|
66542
|
+
var GOOGLE_GROUP = {
|
|
66543
|
+
campaign: "campaigns",
|
|
66544
|
+
ad_group: "ad-groups",
|
|
66545
|
+
ad: "ads",
|
|
66546
|
+
asset_group: "asset-groups",
|
|
66547
|
+
adset: "ads"
|
|
66548
|
+
};
|
|
66549
|
+
function googleResume(hold) {
|
|
66550
|
+
const target2 = `${hold.entity_id} --customer-id ${hold.account_id}`;
|
|
66551
|
+
return hold.level === "asset_group" ? `baker ads google asset-groups update ${target2} --status ENABLED` : `baker ads google ${GOOGLE_GROUP[hold.level]} resume ${target2}`;
|
|
66552
|
+
}
|
|
66553
|
+
var META_GROUP = {
|
|
66554
|
+
campaign: "campaigns",
|
|
66555
|
+
ad_group: "adsets",
|
|
66556
|
+
ad: "ads",
|
|
66557
|
+
asset_group: "ads",
|
|
66558
|
+
adset: "adsets"
|
|
66559
|
+
};
|
|
66560
|
+
function resumeCommand2(hold) {
|
|
66561
|
+
return hold.platform === "meta" ? `\`baker ads meta ${META_GROUP[hold.level]} resume ${hold.entity_id}\`` : `\`${googleResume(hold)}\``;
|
|
66562
|
+
}
|
|
66563
|
+
function stockHoldHints(answer) {
|
|
66564
|
+
const hints2 = [];
|
|
66565
|
+
const held = answer.holds.filter((hold) => hold.state === "held");
|
|
66566
|
+
if (answer.holds.length === 0)
|
|
66567
|
+
hints2.push("Nothing was paused because this product ran out: there is nothing to resume.");
|
|
66568
|
+
const resumable = held.filter((hold) => hold.verdict === "resumable");
|
|
66569
|
+
if (resumable.length > 0) {
|
|
66570
|
+
hints2.push(
|
|
66571
|
+
`${resumable.length} can be resumed: stage ${resumable.map(resumeCommand2).join("; ")}. Resume nothing else.`
|
|
66572
|
+
);
|
|
66573
|
+
}
|
|
66574
|
+
for (const hold of held) {
|
|
66575
|
+
if (hold.verdict === "changed_since") {
|
|
66576
|
+
hints2.push(`${holdName(hold)} was changed by someone after Baker paused it: leave it, and tell the user.`);
|
|
66577
|
+
} else if (hold.verdict === "still_promotes_out_of_stock") {
|
|
66578
|
+
hints2.push(
|
|
66579
|
+
`${holdName(hold)} still sends people to \u201C${hold.verdict_detail ?? "another product"}\u201D, which is out: leave it until that is back.`
|
|
66580
|
+
);
|
|
66581
|
+
} else if (hold.verdict === "cannot_confirm") {
|
|
66582
|
+
hints2.push(
|
|
66583
|
+
`${holdName(hold)} could not be confirmed as untouched since Baker paused it: leave it, and tell the user to check it.`
|
|
66584
|
+
);
|
|
66585
|
+
} else if (hold.verdict === "already_active") {
|
|
66586
|
+
hints2.push(`${holdName(hold)} is already running again: nothing to do.`);
|
|
66587
|
+
}
|
|
66588
|
+
}
|
|
66589
|
+
for (const session of answer.pending_sessions) {
|
|
66590
|
+
hints2.push(
|
|
66591
|
+
`The out-of-stock work \u201C${session.title}\u201D is still waiting for review and would pause ${plural(session.staged_pauses, "ad")} for this product: tell the user to discard it.`
|
|
66592
|
+
);
|
|
66593
|
+
}
|
|
66594
|
+
return hints2;
|
|
66595
|
+
}
|
|
66596
|
+
|
|
66597
|
+
// src/commands/shopify/promotions.ts
|
|
66598
|
+
registerSchema({
|
|
66599
|
+
command: "shopify.promotions",
|
|
66600
|
+
description: "Start here when a product runs out of stock or comes back: what is advertising it \u2014 ads on Google Ads and Meta that lead to its store page, its buy link or a landing that links to it (`via`), the landings themselves (from this workspace's pages, and from measured visits), and the Shopping campaigns and catalog ads that show it (they stop by themselves when it runs out \u2014 never pause them). Read it in the Session that pauses: a pause is remembered \u2014 and undone when the product is back in stock \u2014 only for a product whose promotions that Session read. `checked.not_checked` names a platform Baker could not read.",
|
|
66601
|
+
args: {
|
|
66602
|
+
product: { type: "positional", description: "Product id, handle, or a link to the product", required: true },
|
|
66603
|
+
full: {
|
|
66604
|
+
...fullArg,
|
|
66605
|
+
description: "Add each ad's campaign and ad group or ad set ids and its URL (its id, account and Google resource name are always there)"
|
|
66606
|
+
}
|
|
66607
|
+
}
|
|
66608
|
+
});
|
|
66609
|
+
registerSchema({
|
|
66610
|
+
command: "shopify.stock-holds",
|
|
66611
|
+
description: "Start here when a product is back in stock: the ads Baker paused because it ran out, each with a `verdict` \u2014 `resumable` (resume it), `still_out_of_stock`, `changed_since` (someone changed it after Baker paused it: leave it), `already_active`, `still_promotes_out_of_stock` (it also sends people to another product that is still out: `verdict_detail` names it), `cannot_confirm`. Resume only what is resumable. `pending_sessions` lists out-of-stock work still waiting for review that would pause this product's ads: tell the user to discard it.",
|
|
66612
|
+
args: {
|
|
66613
|
+
product: { type: "string", description: "Only one product's holds: its id, handle or link", required: false },
|
|
66614
|
+
all: { type: "boolean", description: "Resolved holds too (resumed or released)", required: false, default: false },
|
|
66615
|
+
full: fullArg
|
|
66616
|
+
}
|
|
66617
|
+
});
|
|
66618
|
+
var promotionsCommand = defineCommand210({
|
|
66619
|
+
meta: {
|
|
66620
|
+
name: "promotions",
|
|
66621
|
+
description: "What advertises one product: ads that lead to it, landings that link to it, Shopping that shows it. Example: baker shopify promotions 10310413942969"
|
|
66622
|
+
},
|
|
66623
|
+
args: {
|
|
66624
|
+
product: { type: "positional", description: "Product id, handle, or a link to the product", required: true },
|
|
66625
|
+
full: {
|
|
66626
|
+
type: "boolean",
|
|
66627
|
+
description: "Add campaign and ad group or ad set ids and URLs",
|
|
66628
|
+
required: false,
|
|
66629
|
+
default: false
|
|
66630
|
+
}
|
|
66631
|
+
},
|
|
66632
|
+
run: async ({ args: args5 }) => {
|
|
66633
|
+
try {
|
|
66634
|
+
const positionals = Array.isArray(args5._) ? args5._ : [];
|
|
66635
|
+
if (positionals.length > 1) {
|
|
66636
|
+
throw new ApiError("VALIDATION_ERROR", "product: Pass one product id, handle or product link.");
|
|
66637
|
+
}
|
|
66638
|
+
const { product, store } = await apiGet(
|
|
66639
|
+
"/api/shopify/product",
|
|
66640
|
+
params({ ref: args5.product })
|
|
66641
|
+
);
|
|
66642
|
+
const scan = await readWorkspacePages(process.cwd());
|
|
66643
|
+
const linked = scan ? landingLinksOf(scan.pages, {
|
|
66644
|
+
handle: product.handle,
|
|
66645
|
+
variantIds: product.variants.map((variant) => variant.variantId),
|
|
66646
|
+
buyUrls: product.variants.flatMap((variant) => variant.buyUrl ? [variant.buyUrl] : [])
|
|
66647
|
+
}) : void 0;
|
|
66648
|
+
const answer = await apiPost("/api/shopify/promotions", {
|
|
66649
|
+
product: product.productId,
|
|
66650
|
+
...linked ? { linked_landings: linked.slice(0, 50) } : {},
|
|
66651
|
+
scanned: scan !== null,
|
|
66652
|
+
...args5.full ? { full: true } : {}
|
|
66653
|
+
});
|
|
66654
|
+
emit2(answer, { store }, [
|
|
66655
|
+
...storeStateHints(store),
|
|
66656
|
+
...promotionHints(answer, { scanned: scan !== null, skippedPages: scan?.skipped ?? 0 })
|
|
66657
|
+
]);
|
|
66658
|
+
} catch (err) {
|
|
66659
|
+
fail9(err);
|
|
66660
|
+
}
|
|
66661
|
+
}
|
|
66662
|
+
});
|
|
66663
|
+
var stockHoldsCommand = defineCommand210({
|
|
66664
|
+
meta: {
|
|
66665
|
+
name: "stock-holds",
|
|
66666
|
+
description: "The ads Baker paused because a product ran out, and whether each may be resumed now. Example: baker shopify stock-holds --product 10310413942969"
|
|
66667
|
+
},
|
|
66668
|
+
args: {
|
|
66669
|
+
product: { type: "string", description: "Only one product: its id, handle or link", required: false },
|
|
66670
|
+
all: { type: "boolean", description: "Resolved holds too", required: false, default: false },
|
|
66671
|
+
full: { type: "boolean", description: "Everything Baker keeps", required: false, default: false }
|
|
66672
|
+
},
|
|
66673
|
+
run: async ({ args: args5 }) => {
|
|
66674
|
+
try {
|
|
66675
|
+
const answer = await apiGet(
|
|
66676
|
+
"/api/shopify/stock-holds",
|
|
66677
|
+
params({ product: args5.product, all: args5.all, full: args5.full })
|
|
66678
|
+
);
|
|
66679
|
+
const { store, ...data } = answer;
|
|
66680
|
+
emit2(data, { store, count: answer.holds.length }, [...storeStateHints(store), ...stockHoldHints(answer)]);
|
|
66681
|
+
} catch (err) {
|
|
66682
|
+
fail9(err);
|
|
66683
|
+
}
|
|
66684
|
+
}
|
|
66685
|
+
});
|
|
66686
|
+
|
|
66273
66687
|
// src/commands/shopify/index.ts
|
|
66274
66688
|
registerSchema({
|
|
66275
66689
|
command: "shopify.store",
|
|
@@ -66398,7 +66812,7 @@ registerSchema({
|
|
|
66398
66812
|
}
|
|
66399
66813
|
}
|
|
66400
66814
|
});
|
|
66401
|
-
var salesCommand =
|
|
66815
|
+
var salesCommand = defineCommand211({
|
|
66402
66816
|
meta: {
|
|
66403
66817
|
name: "sales",
|
|
66404
66818
|
description: "What the store sold: orders, sales, refunds and net, by day, product, campaign or landing \u2014 or when buyers order (weekday, hour, month). Example: baker shopify sales --days 7 --by campaign"
|
|
@@ -66436,7 +66850,7 @@ var salesCommand = defineCommand210({
|
|
|
66436
66850
|
}
|
|
66437
66851
|
}
|
|
66438
66852
|
});
|
|
66439
|
-
var storeCommand =
|
|
66853
|
+
var storeCommand = defineCommand211({
|
|
66440
66854
|
meta: {
|
|
66441
66855
|
name: "store",
|
|
66442
66856
|
description: "The connected Shopify store: currency, countries, how many products, what is out of stock. Example: baker shopify store"
|
|
@@ -66453,7 +66867,7 @@ var storeCommand = defineCommand210({
|
|
|
66453
66867
|
}
|
|
66454
66868
|
}
|
|
66455
66869
|
});
|
|
66456
|
-
var productsCommand =
|
|
66870
|
+
var productsCommand = defineCommand211({
|
|
66457
66871
|
meta: {
|
|
66458
66872
|
name: "products",
|
|
66459
66873
|
description: 'What the store sells, with price and stock. Example: baker shopify products --search "snowboard" --stock out_of_stock'
|
|
@@ -66499,7 +66913,7 @@ var productsCommand = defineCommand210({
|
|
|
66499
66913
|
}
|
|
66500
66914
|
}
|
|
66501
66915
|
});
|
|
66502
|
-
var productCommand =
|
|
66916
|
+
var productCommand = defineCommand211({
|
|
66503
66917
|
meta: {
|
|
66504
66918
|
name: "product",
|
|
66505
66919
|
description: "One product: options with buy links, prices by country, stock, photo imageIds, video playbackIds. Accepts an id, handle or link. Example: baker shopify product the-complete-snowboard --content"
|
|
@@ -66562,7 +66976,7 @@ var productCommand = defineCommand210({
|
|
|
66562
66976
|
}
|
|
66563
66977
|
}
|
|
66564
66978
|
});
|
|
66565
|
-
var collectionsCommand =
|
|
66979
|
+
var collectionsCommand = defineCommand211({
|
|
66566
66980
|
meta: {
|
|
66567
66981
|
name: "collections",
|
|
66568
66982
|
description: "The store's collections, with the handles --collection takes. Example: baker shopify collections --full"
|
|
@@ -66587,7 +67001,7 @@ var collectionsCommand = defineCommand210({
|
|
|
66587
67001
|
}
|
|
66588
67002
|
}
|
|
66589
67003
|
});
|
|
66590
|
-
var stockCommand2 =
|
|
67004
|
+
var stockCommand2 = defineCommand211({
|
|
66591
67005
|
meta: {
|
|
66592
67006
|
name: "stock",
|
|
66593
67007
|
description: "Every product with options out of stock, naming them. Example: baker shopify stock"
|
|
@@ -66611,11 +67025,12 @@ var stockCommand2 = defineCommand210({
|
|
|
66611
67025
|
}
|
|
66612
67026
|
}
|
|
66613
67027
|
});
|
|
66614
|
-
var shopifyCommand =
|
|
67028
|
+
var shopifyCommand = defineCommand211({
|
|
66615
67029
|
meta: {
|
|
66616
67030
|
name: "shopify",
|
|
66617
67031
|
description: `Read the connected Shopify store as Baker keeps it \u2014 products, prices by country, stock, collections,
|
|
66618
|
-
product photos, what it sold,
|
|
67032
|
+
product photos, what it sold, who buys, where and what, and what advertises each product. Read-only:
|
|
67033
|
+
nothing here changes the store.
|
|
66619
67034
|
|
|
66620
67035
|
Examples:
|
|
66621
67036
|
baker shopify store # currency, countries, how many products, what is out of stock
|
|
@@ -66637,6 +67052,8 @@ Examples:
|
|
|
66637
67052
|
baker shopify buyer 1042 # one numbered customer's orders
|
|
66638
67053
|
baker shopify segments # best, loyal, at risk, new, one-time \u2014 and who to find more of
|
|
66639
67054
|
baker shopify cohorts --months 12 # buyers by first-order month: who came back
|
|
67055
|
+
baker shopify promotions <product> # what advertises it: ads, landings, Shopping (read before pausing)
|
|
67056
|
+
baker shopify stock-holds --product <product> # what Baker paused because it ran out, and what may be resumed
|
|
66640
67057
|
|
|
66641
67058
|
Product photos are already in the image library: place them by imageId
|
|
66642
67059
|
(baker images download <imageIds> --out src/pages/<page>/_images/), never by a cdn.shopify.com link.
|
|
@@ -66659,15 +67076,17 @@ Full guide: __tooling__/docs/tools/baker/shopify.md`
|
|
|
66659
67076
|
countries: countriesCommand2,
|
|
66660
67077
|
"best-sellers": bestSellersCommand,
|
|
66661
67078
|
cohorts: cohortsCommand,
|
|
66662
|
-
segments: segmentsCommand
|
|
67079
|
+
segments: segmentsCommand,
|
|
67080
|
+
promotions: promotionsCommand,
|
|
67081
|
+
"stock-holds": stockHoldsCommand
|
|
66663
67082
|
}
|
|
66664
67083
|
});
|
|
66665
67084
|
|
|
66666
67085
|
// src/commands/studio/index.ts
|
|
66667
|
-
import { defineCommand as
|
|
67086
|
+
import { defineCommand as defineCommand220 } from "citty";
|
|
66668
67087
|
|
|
66669
67088
|
// src/commands/studio/animate.ts
|
|
66670
|
-
import { defineCommand as
|
|
67089
|
+
import { defineCommand as defineCommand212 } from "citty";
|
|
66671
67090
|
|
|
66672
67091
|
// src/commands/studio/spokenPace.ts
|
|
66673
67092
|
var WORDS_PER_SECOND3 = SPOKEN_WORDS_PER_SECOND;
|
|
@@ -66893,7 +67312,7 @@ function parseImageRefs(spec) {
|
|
|
66893
67312
|
}
|
|
66894
67313
|
var defaultDeps = {
|
|
66895
67314
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
66896
|
-
upload: (
|
|
67315
|
+
upload: (path49) => uploadLocalImage({ file: path49, contentType: detectImageContentType(path49), source: "uploaded" })
|
|
66897
67316
|
};
|
|
66898
67317
|
async function resolveLibraryImageIds(spec, limit2, deps = defaultDeps) {
|
|
66899
67318
|
const refs = parseImageRefs(spec);
|
|
@@ -66913,10 +67332,10 @@ async function resolveLibraryImageIds(spec, limit2, deps = defaultDeps) {
|
|
|
66913
67332
|
}
|
|
66914
67333
|
return { imageIds, added };
|
|
66915
67334
|
}
|
|
66916
|
-
function uploadFailure(
|
|
67335
|
+
function uploadFailure(path49) {
|
|
66917
67336
|
return (error) => {
|
|
66918
67337
|
if (error instanceof ApiError) throw error;
|
|
66919
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
67338
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path49}" as an image.`);
|
|
66920
67339
|
};
|
|
66921
67340
|
}
|
|
66922
67341
|
|
|
@@ -67180,7 +67599,7 @@ async function adByHandHintFor(body) {
|
|
|
67180
67599
|
return null;
|
|
67181
67600
|
}
|
|
67182
67601
|
}
|
|
67183
|
-
var animateCommand =
|
|
67602
|
+
var animateCommand = defineCommand212({
|
|
67184
67603
|
meta: {
|
|
67185
67604
|
name: "animate",
|
|
67186
67605
|
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"
|
|
@@ -67305,7 +67724,7 @@ var animateCommand = defineCommand211({
|
|
|
67305
67724
|
});
|
|
67306
67725
|
|
|
67307
67726
|
// src/commands/studio/generate.ts
|
|
67308
|
-
import { defineCommand as
|
|
67727
|
+
import { defineCommand as defineCommand213 } from "citty";
|
|
67309
67728
|
var MODEL_LIST2 = IMAGE_MODEL_IDS;
|
|
67310
67729
|
var DEFAULT_MAX_WAIT_MS2 = 24e4;
|
|
67311
67730
|
registerSchema({
|
|
@@ -67441,7 +67860,7 @@ function buildGenerateBody(args5, prompt) {
|
|
|
67441
67860
|
}
|
|
67442
67861
|
return body;
|
|
67443
67862
|
}
|
|
67444
|
-
var generateCommand =
|
|
67863
|
+
var generateCommand = defineCommand213({
|
|
67445
67864
|
meta: {
|
|
67446
67865
|
name: "generate",
|
|
67447
67866
|
description: "Start here to make an image. Renders 1-8 takes of one brief, ingests each into the media library as it lands, and shows the batch in the dashboard Studio next to the ones the client ran.\n\nModel choice: google/gemini-3.1-flash-image-preview (default \u2014 fast, best at editing a reference and at extreme ratios), google/gemini-3-pro-image-preview (highest fidelity, slower), openai/gpt-image-2 (photoreal and the cleanest in-image text \u2014 no --image-size, no 4:5 / 5:4), recraft/recraft-v4.1-pro-vector (vector/flat marks with palette control).\n\n--reference is the biggest quality lever there is: a real logo, product shot, Pinterest pin or sandbox screenshot beats any amount of adjectives.\n\nExamples:\n baker studio generate 'matte black bottle on wet marble, hard studio light, 35mm' --aspect-ratio 3:2 --count 3\n baker studio generate 'this bottle on a sunlit kitchen counter' --reference './src/brand/product.png,https://\u2026/kitchen.jpg'\n baker studio generate 'founder-style selfie, kitchen background, natural light' --skill ugc-selfie-hook\n baker studio generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
|
|
@@ -67524,7 +67943,7 @@ var generateCommand = defineCommand212({
|
|
|
67524
67943
|
});
|
|
67525
67944
|
|
|
67526
67945
|
// src/commands/studio/get.ts
|
|
67527
|
-
import { defineCommand as
|
|
67946
|
+
import { defineCommand as defineCommand214 } from "citty";
|
|
67528
67947
|
registerSchema({
|
|
67529
67948
|
command: "studio.get",
|
|
67530
67949
|
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.",
|
|
@@ -67533,7 +67952,7 @@ registerSchema({
|
|
|
67533
67952
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
67534
67953
|
}
|
|
67535
67954
|
});
|
|
67536
|
-
var getCommand5 =
|
|
67955
|
+
var getCommand5 = defineCommand214({
|
|
67537
67956
|
meta: {
|
|
67538
67957
|
name: "get",
|
|
67539
67958
|
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"
|
|
@@ -67562,7 +67981,7 @@ var getCommand5 = defineCommand213({
|
|
|
67562
67981
|
});
|
|
67563
67982
|
|
|
67564
67983
|
// src/commands/studio/improve.ts
|
|
67565
|
-
import { defineCommand as
|
|
67984
|
+
import { defineCommand as defineCommand215 } from "citty";
|
|
67566
67985
|
var DESCRIPTION2 = "Sharpen a rough brief into directed art direction \u2014 the same rewrite the client gets from the wand in the Studio prompt bar. Reach for it when you are relaying the CLIENT's own words and want them shaped without substituting your voice; when you are writing the art direction yourself, just write it, because you will do a better job than this does.";
|
|
67567
67986
|
registerSchema({
|
|
67568
67987
|
command: "studio.improve",
|
|
@@ -67587,7 +68006,7 @@ registerSchema({
|
|
|
67587
68006
|
}
|
|
67588
68007
|
}
|
|
67589
68008
|
});
|
|
67590
|
-
var improveCommand =
|
|
68009
|
+
var improveCommand = defineCommand215({
|
|
67591
68010
|
meta: {
|
|
67592
68011
|
name: "improve",
|
|
67593
68012
|
description: `${DESCRIPTION2}
|
|
@@ -67631,7 +68050,7 @@ Examples:
|
|
|
67631
68050
|
});
|
|
67632
68051
|
|
|
67633
68052
|
// src/commands/studio/keep.ts
|
|
67634
|
-
import { defineCommand as
|
|
68053
|
+
import { defineCommand as defineCommand216 } from "citty";
|
|
67635
68054
|
registerSchema({
|
|
67636
68055
|
command: "studio.keep",
|
|
67637
68056
|
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.",
|
|
@@ -67641,7 +68060,7 @@ registerSchema({
|
|
|
67641
68060
|
undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
|
|
67642
68061
|
}
|
|
67643
68062
|
});
|
|
67644
|
-
var keepCommand =
|
|
68063
|
+
var keepCommand = defineCommand216({
|
|
67645
68064
|
meta: {
|
|
67646
68065
|
name: "keep",
|
|
67647
68066
|
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"
|
|
@@ -67692,7 +68111,7 @@ var keepCommand = defineCommand215({
|
|
|
67692
68111
|
});
|
|
67693
68112
|
|
|
67694
68113
|
// src/commands/studio/list.ts
|
|
67695
|
-
import { defineCommand as
|
|
68114
|
+
import { defineCommand as defineCommand217 } from "citty";
|
|
67696
68115
|
registerSchema({
|
|
67697
68116
|
command: "studio.list",
|
|
67698
68117
|
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.",
|
|
@@ -67703,7 +68122,7 @@ registerSchema({
|
|
|
67703
68122
|
full: { type: "boolean", description: "Include settings, references and attribution", required: false }
|
|
67704
68123
|
}
|
|
67705
68124
|
});
|
|
67706
|
-
var listCommand18 =
|
|
68125
|
+
var listCommand18 = defineCommand217({
|
|
67707
68126
|
meta: {
|
|
67708
68127
|
name: "list",
|
|
67709
68128
|
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"
|
|
@@ -67737,7 +68156,7 @@ var listCommand18 = defineCommand216({
|
|
|
67737
68156
|
});
|
|
67738
68157
|
|
|
67739
68158
|
// src/commands/studio/models.ts
|
|
67740
|
-
import { defineCommand as
|
|
68159
|
+
import { defineCommand as defineCommand218 } from "citty";
|
|
67741
68160
|
var DESCRIPTION3 = "What each Studio model actually accepts: its shapes, resolutions, clip lengths, prompt character cap, how many reference images it takes, and which knobs it has. Read this before a batch you care about \u2014 the models disagree far more than they look like they do, and a setting the chosen model does not have is REFUSED, not ignored.";
|
|
67742
68161
|
registerSchema({
|
|
67743
68162
|
command: "studio.models",
|
|
@@ -67824,7 +68243,7 @@ function buildModelCards(kind, model) {
|
|
|
67824
68243
|
const selected = model ? ids.filter((id) => id === model) : ids;
|
|
67825
68244
|
return selected.map((id) => build(id));
|
|
67826
68245
|
}
|
|
67827
|
-
var modelsCommand =
|
|
68246
|
+
var modelsCommand = defineCommand218({
|
|
67828
68247
|
meta: {
|
|
67829
68248
|
name: "models",
|
|
67830
68249
|
description: `${DESCRIPTION3}
|
|
@@ -67871,13 +68290,13 @@ Examples:
|
|
|
67871
68290
|
});
|
|
67872
68291
|
|
|
67873
68292
|
// src/commands/studio/skills.ts
|
|
67874
|
-
import { defineCommand as
|
|
68293
|
+
import { defineCommand as defineCommand219 } from "citty";
|
|
67875
68294
|
registerSchema({
|
|
67876
68295
|
command: "studio.skills",
|
|
67877
68296
|
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.",
|
|
67878
68297
|
args: {}
|
|
67879
68298
|
});
|
|
67880
|
-
var skillsCommand =
|
|
68299
|
+
var skillsCommand = defineCommand219({
|
|
67881
68300
|
meta: {
|
|
67882
68301
|
name: "skills",
|
|
67883
68302
|
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"
|
|
@@ -67901,7 +68320,7 @@ var skillsCommand = defineCommand218({
|
|
|
67901
68320
|
});
|
|
67902
68321
|
|
|
67903
68322
|
// src/commands/studio/index.ts
|
|
67904
|
-
var studioCommand =
|
|
68323
|
+
var studioCommand = defineCommand220({
|
|
67905
68324
|
meta: {
|
|
67906
68325
|
name: "studio",
|
|
67907
68326
|
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.
|
|
@@ -67944,10 +68363,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
|
|
|
67944
68363
|
});
|
|
67945
68364
|
|
|
67946
68365
|
// src/commands/tag-manager/index.ts
|
|
67947
|
-
import { defineCommand as
|
|
68366
|
+
import { defineCommand as defineCommand224 } from "citty";
|
|
67948
68367
|
|
|
67949
68368
|
// src/commands/tag-manager/draft.ts
|
|
67950
|
-
import { defineCommand as
|
|
68369
|
+
import { defineCommand as defineCommand221 } from "citty";
|
|
67951
68370
|
|
|
67952
68371
|
// src/commands/tag-manager/shared.ts
|
|
67953
68372
|
import { readFileSync as readFileSync20 } from "fs";
|
|
@@ -68014,10 +68433,10 @@ async function stageOp4(op) {
|
|
|
68014
68433
|
handleError8(err);
|
|
68015
68434
|
}
|
|
68016
68435
|
}
|
|
68017
|
-
async function draftAction3(
|
|
68436
|
+
async function draftAction3(path49, body, chat) {
|
|
68018
68437
|
const chatId = resolveChatId(chat);
|
|
68019
68438
|
try {
|
|
68020
|
-
const data = await apiPost(
|
|
68439
|
+
const data = await apiPost(path49, { chatId, ...body });
|
|
68021
68440
|
writeJsonEnvelope({ ok: true, data });
|
|
68022
68441
|
return data;
|
|
68023
68442
|
} catch (err) {
|
|
@@ -68070,13 +68489,13 @@ registerSchema({
|
|
|
68070
68489
|
chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
|
|
68071
68490
|
}
|
|
68072
68491
|
});
|
|
68073
|
-
var draftCommand5 =
|
|
68492
|
+
var draftCommand5 = defineCommand221({
|
|
68074
68493
|
meta: {
|
|
68075
68494
|
name: "draft",
|
|
68076
68495
|
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."
|
|
68077
68496
|
},
|
|
68078
68497
|
subCommands: {
|
|
68079
|
-
list:
|
|
68498
|
+
list: defineCommand221({
|
|
68080
68499
|
meta: {
|
|
68081
68500
|
name: "list",
|
|
68082
68501
|
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
@@ -68089,7 +68508,7 @@ var draftCommand5 = defineCommand220({
|
|
|
68089
68508
|
await draftList2(args5.json === true, args5.chat);
|
|
68090
68509
|
}
|
|
68091
68510
|
}),
|
|
68092
|
-
show:
|
|
68511
|
+
show: defineCommand221({
|
|
68093
68512
|
meta: {
|
|
68094
68513
|
name: "show",
|
|
68095
68514
|
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
@@ -68106,7 +68525,7 @@ var draftCommand5 = defineCommand220({
|
|
|
68106
68525
|
);
|
|
68107
68526
|
}
|
|
68108
68527
|
}),
|
|
68109
|
-
amend:
|
|
68528
|
+
amend: defineCommand221({
|
|
68110
68529
|
meta: {
|
|
68111
68530
|
name: "amend",
|
|
68112
68531
|
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."
|
|
@@ -68123,7 +68542,7 @@ var draftCommand5 = defineCommand220({
|
|
|
68123
68542
|
});
|
|
68124
68543
|
}
|
|
68125
68544
|
}),
|
|
68126
|
-
remove:
|
|
68545
|
+
remove: defineCommand221({
|
|
68127
68546
|
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
68128
68547
|
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
68129
68548
|
run: async ({ args: args5 }) => {
|
|
@@ -68132,7 +68551,7 @@ var draftCommand5 = defineCommand220({
|
|
|
68132
68551
|
});
|
|
68133
68552
|
}
|
|
68134
68553
|
}),
|
|
68135
|
-
clear:
|
|
68554
|
+
clear: defineCommand221({
|
|
68136
68555
|
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
68137
68556
|
run: async () => {
|
|
68138
68557
|
await draftAction3("/api/tag-manager/draft/clear", {});
|
|
@@ -68142,7 +68561,7 @@ var draftCommand5 = defineCommand220({
|
|
|
68142
68561
|
});
|
|
68143
68562
|
|
|
68144
68563
|
// src/commands/tag-manager/read.ts
|
|
68145
|
-
import { defineCommand as
|
|
68564
|
+
import { defineCommand as defineCommand222 } from "citty";
|
|
68146
68565
|
registerSchema({
|
|
68147
68566
|
command: "tagManager.containers",
|
|
68148
68567
|
description: "List the Google Tag Manager containers this company's connection can reach. Every container the company connected is flagged `connected: true` \u2014 there can be several, and Baker may read and change all of them. Start here to confirm which containers you are managing.",
|
|
@@ -68183,7 +68602,7 @@ function containersHints(containers) {
|
|
|
68183
68602
|
}))
|
|
68184
68603
|
});
|
|
68185
68604
|
}
|
|
68186
|
-
var containersCommand =
|
|
68605
|
+
var containersCommand = defineCommand222({
|
|
68187
68606
|
meta: {
|
|
68188
68607
|
name: "containers",
|
|
68189
68608
|
description: `List Tag Manager containers reachable by this company's connection.
|
|
@@ -68200,7 +68619,7 @@ Start here:
|
|
|
68200
68619
|
}
|
|
68201
68620
|
}
|
|
68202
68621
|
});
|
|
68203
|
-
var readCommand =
|
|
68622
|
+
var readCommand = defineCommand222({
|
|
68204
68623
|
meta: {
|
|
68205
68624
|
name: "read",
|
|
68206
68625
|
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
@@ -68242,7 +68661,7 @@ Examples:
|
|
|
68242
68661
|
});
|
|
68243
68662
|
|
|
68244
68663
|
// src/commands/tag-manager/write-commands.ts
|
|
68245
|
-
import { defineCommand as
|
|
68664
|
+
import { defineCommand as defineCommand223 } from "citty";
|
|
68246
68665
|
var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
|
|
68247
68666
|
var ENTITIES = [
|
|
68248
68667
|
{
|
|
@@ -68298,10 +68717,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
|
|
|
68298
68717
|
});
|
|
68299
68718
|
}
|
|
68300
68719
|
function entityCommand(entity, noun, example) {
|
|
68301
|
-
return
|
|
68720
|
+
return defineCommand223({
|
|
68302
68721
|
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
68303
68722
|
subCommands: {
|
|
68304
|
-
create:
|
|
68723
|
+
create: defineCommand223({
|
|
68305
68724
|
meta: {
|
|
68306
68725
|
name: "create",
|
|
68307
68726
|
description: `Stage a new ${noun}
|
|
@@ -68323,7 +68742,7 @@ Examples:
|
|
|
68323
68742
|
});
|
|
68324
68743
|
}
|
|
68325
68744
|
}),
|
|
68326
|
-
update:
|
|
68745
|
+
update: defineCommand223({
|
|
68327
68746
|
meta: {
|
|
68328
68747
|
name: "update",
|
|
68329
68748
|
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
@@ -68343,7 +68762,7 @@ Examples:
|
|
|
68343
68762
|
});
|
|
68344
68763
|
}
|
|
68345
68764
|
}),
|
|
68346
|
-
delete:
|
|
68765
|
+
delete: defineCommand223({
|
|
68347
68766
|
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
68348
68767
|
args: {
|
|
68349
68768
|
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
@@ -68384,7 +68803,7 @@ function builtinTypes(args5) {
|
|
|
68384
68803
|
}
|
|
68385
68804
|
return raw.split(",").map((entry) => entry.trim());
|
|
68386
68805
|
}
|
|
68387
|
-
var builtinCommand =
|
|
68806
|
+
var builtinCommand = defineCommand223({
|
|
68388
68807
|
meta: {
|
|
68389
68808
|
name: "builtin",
|
|
68390
68809
|
description: `Enable or disable built-in variables
|
|
@@ -68394,7 +68813,7 @@ Examples:
|
|
|
68394
68813
|
baker tag-manager builtin disable --types formId`
|
|
68395
68814
|
},
|
|
68396
68815
|
subCommands: {
|
|
68397
|
-
enable:
|
|
68816
|
+
enable: defineCommand223({
|
|
68398
68817
|
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
68399
68818
|
args: {
|
|
68400
68819
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -68408,7 +68827,7 @@ Examples:
|
|
|
68408
68827
|
});
|
|
68409
68828
|
}
|
|
68410
68829
|
}),
|
|
68411
|
-
disable:
|
|
68830
|
+
disable: defineCommand223({
|
|
68412
68831
|
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
68413
68832
|
args: {
|
|
68414
68833
|
types: { type: "string", description: "Comma-separated types", required: false },
|
|
@@ -68426,7 +68845,7 @@ Examples:
|
|
|
68426
68845
|
});
|
|
68427
68846
|
|
|
68428
68847
|
// src/commands/tag-manager/index.ts
|
|
68429
|
-
var tagManagerCommand =
|
|
68848
|
+
var tagManagerCommand = defineCommand224({
|
|
68430
68849
|
meta: {
|
|
68431
68850
|
name: "tag-manager",
|
|
68432
68851
|
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
@@ -68463,7 +68882,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
|
68463
68882
|
});
|
|
68464
68883
|
|
|
68465
68884
|
// src/commands/tags/index.ts
|
|
68466
|
-
import { defineCommand as
|
|
68885
|
+
import { defineCommand as defineCommand225 } from "citty";
|
|
68467
68886
|
|
|
68468
68887
|
// src/commands/tags/shared.ts
|
|
68469
68888
|
function failApi3(err) {
|
|
@@ -68543,7 +68962,7 @@ async function listTags(json) {
|
|
|
68543
68962
|
var listArgs11 = {
|
|
68544
68963
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
|
|
68545
68964
|
};
|
|
68546
|
-
var listCommand19 =
|
|
68965
|
+
var listCommand19 = defineCommand225({
|
|
68547
68966
|
meta: {
|
|
68548
68967
|
name: "list",
|
|
68549
68968
|
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"
|
|
@@ -68562,7 +68981,7 @@ async function listDraft4(chat) {
|
|
|
68562
68981
|
failApi3(err);
|
|
68563
68982
|
}
|
|
68564
68983
|
}
|
|
68565
|
-
var draftCommand6 =
|
|
68984
|
+
var draftCommand6 = defineCommand225({
|
|
68566
68985
|
meta: {
|
|
68567
68986
|
name: "draft",
|
|
68568
68987
|
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."
|
|
@@ -68572,7 +68991,7 @@ var draftCommand6 = defineCommand224({
|
|
|
68572
68991
|
await listDraft4(args5.chat);
|
|
68573
68992
|
}
|
|
68574
68993
|
});
|
|
68575
|
-
var tagsCommand4 =
|
|
68994
|
+
var tagsCommand4 = defineCommand225({
|
|
68576
68995
|
meta: {
|
|
68577
68996
|
name: "tags",
|
|
68578
68997
|
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.
|
|
@@ -68601,10 +69020,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
68601
69020
|
});
|
|
68602
69021
|
|
|
68603
69022
|
// src/commands/testimonials/index.ts
|
|
68604
|
-
import { defineCommand as
|
|
69023
|
+
import { defineCommand as defineCommand229 } from "citty";
|
|
68605
69024
|
|
|
68606
69025
|
// src/commands/testimonials/get.ts
|
|
68607
|
-
import { defineCommand as
|
|
69026
|
+
import { defineCommand as defineCommand226 } from "citty";
|
|
68608
69027
|
registerSchema({
|
|
68609
69028
|
command: "testimonials.get",
|
|
68610
69029
|
description: "Get a single testimonial by ID",
|
|
@@ -68612,7 +69031,7 @@ registerSchema({
|
|
|
68612
69031
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
68613
69032
|
}
|
|
68614
69033
|
});
|
|
68615
|
-
var getCommand6 =
|
|
69034
|
+
var getCommand6 = defineCommand226({
|
|
68616
69035
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
68617
69036
|
args: {
|
|
68618
69037
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -68649,7 +69068,7 @@ var getCommand6 = defineCommand225({
|
|
|
68649
69068
|
});
|
|
68650
69069
|
|
|
68651
69070
|
// src/commands/testimonials/list.ts
|
|
68652
|
-
import { defineCommand as
|
|
69071
|
+
import { defineCommand as defineCommand227 } from "citty";
|
|
68653
69072
|
|
|
68654
69073
|
// src/commands/testimonials/emptyCorpusHints.ts
|
|
68655
69074
|
function resolveEmptyReason({
|
|
@@ -68806,7 +69225,7 @@ function buildListParams(args5) {
|
|
|
68806
69225
|
}
|
|
68807
69226
|
return params2;
|
|
68808
69227
|
}
|
|
68809
|
-
var listCommand20 =
|
|
69228
|
+
var listCommand20 = defineCommand227({
|
|
68810
69229
|
meta: {
|
|
68811
69230
|
name: "list",
|
|
68812
69231
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -68866,7 +69285,7 @@ var listCommand20 = defineCommand226({
|
|
|
68866
69285
|
});
|
|
68867
69286
|
|
|
68868
69287
|
// src/commands/testimonials/search.ts
|
|
68869
|
-
import { defineCommand as
|
|
69288
|
+
import { defineCommand as defineCommand228 } from "citty";
|
|
68870
69289
|
var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
|
|
68871
69290
|
function languageBiasHint(results, requestedLanguage) {
|
|
68872
69291
|
if (requestedLanguage) {
|
|
@@ -68945,7 +69364,7 @@ function buildSearchRequest(query, args5) {
|
|
|
68945
69364
|
}
|
|
68946
69365
|
return body;
|
|
68947
69366
|
}
|
|
68948
|
-
var searchCommand3 =
|
|
69367
|
+
var searchCommand3 = defineCommand228({
|
|
68949
69368
|
meta: {
|
|
68950
69369
|
name: "search",
|
|
68951
69370
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -69009,7 +69428,7 @@ var searchCommand3 = defineCommand227({
|
|
|
69009
69428
|
var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
69010
69429
|
|
|
69011
69430
|
// src/commands/testimonials/index.ts
|
|
69012
|
-
var testimonialsCommand =
|
|
69431
|
+
var testimonialsCommand = defineCommand229({
|
|
69013
69432
|
meta: {
|
|
69014
69433
|
name: "testimonials",
|
|
69015
69434
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -69031,10 +69450,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
69031
69450
|
});
|
|
69032
69451
|
|
|
69033
69452
|
// src/commands/videos/index.ts
|
|
69034
|
-
import { defineCommand as
|
|
69453
|
+
import { defineCommand as defineCommand237 } from "citty";
|
|
69035
69454
|
|
|
69036
69455
|
// src/commands/videos/delete.ts
|
|
69037
|
-
import { defineCommand as
|
|
69456
|
+
import { defineCommand as defineCommand230 } from "citty";
|
|
69038
69457
|
registerSchema({
|
|
69039
69458
|
command: "videos.delete",
|
|
69040
69459
|
description: "Delete a video by ID",
|
|
@@ -69048,7 +69467,7 @@ registerSchema({
|
|
|
69048
69467
|
}
|
|
69049
69468
|
}
|
|
69050
69469
|
});
|
|
69051
|
-
var deleteCommand4 =
|
|
69470
|
+
var deleteCommand4 = defineCommand230({
|
|
69052
69471
|
meta: {
|
|
69053
69472
|
name: "delete",
|
|
69054
69473
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -69089,7 +69508,7 @@ var deleteCommand4 = defineCommand229({
|
|
|
69089
69508
|
});
|
|
69090
69509
|
|
|
69091
69510
|
// src/commands/videos/describe.ts
|
|
69092
|
-
import { defineCommand as
|
|
69511
|
+
import { defineCommand as defineCommand231 } from "citty";
|
|
69093
69512
|
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.";
|
|
69094
69513
|
registerSchema({
|
|
69095
69514
|
command: "videos.describe",
|
|
@@ -69106,7 +69525,7 @@ registerSchema({
|
|
|
69106
69525
|
full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
|
|
69107
69526
|
}
|
|
69108
69527
|
});
|
|
69109
|
-
var describeCommand2 =
|
|
69528
|
+
var describeCommand2 = defineCommand231({
|
|
69110
69529
|
meta: {
|
|
69111
69530
|
name: "describe",
|
|
69112
69531
|
description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
|
|
@@ -69164,7 +69583,7 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
69164
69583
|
});
|
|
69165
69584
|
|
|
69166
69585
|
// src/commands/videos/get.ts
|
|
69167
|
-
import { defineCommand as
|
|
69586
|
+
import { defineCommand as defineCommand232 } from "citty";
|
|
69168
69587
|
registerSchema({
|
|
69169
69588
|
command: "videos.get",
|
|
69170
69589
|
description: "Get a single video by ID",
|
|
@@ -69172,7 +69591,7 @@ registerSchema({
|
|
|
69172
69591
|
id: { type: "string", description: "Video ID", required: true }
|
|
69173
69592
|
}
|
|
69174
69593
|
});
|
|
69175
|
-
var getCommand7 =
|
|
69594
|
+
var getCommand7 = defineCommand232({
|
|
69176
69595
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
69177
69596
|
args: {
|
|
69178
69597
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -69209,7 +69628,7 @@ var getCommand7 = defineCommand231({
|
|
|
69209
69628
|
});
|
|
69210
69629
|
|
|
69211
69630
|
// src/commands/videos/group.ts
|
|
69212
|
-
import { defineCommand as
|
|
69631
|
+
import { defineCommand as defineCommand233 } from "citty";
|
|
69213
69632
|
registerSchema({
|
|
69214
69633
|
command: "videos.group",
|
|
69215
69634
|
description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
|
|
@@ -69218,7 +69637,7 @@ registerSchema({
|
|
|
69218
69637
|
"group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
|
|
69219
69638
|
}
|
|
69220
69639
|
});
|
|
69221
|
-
var groupCommand2 =
|
|
69640
|
+
var groupCommand2 = defineCommand233({
|
|
69222
69641
|
meta: {
|
|
69223
69642
|
name: "group",
|
|
69224
69643
|
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>"
|
|
@@ -69238,10 +69657,10 @@ var groupCommand2 = defineCommand232({
|
|
|
69238
69657
|
});
|
|
69239
69658
|
|
|
69240
69659
|
// src/commands/videos/ingest.ts
|
|
69241
|
-
import { mkdtemp as mkdtemp3, rm as rm9, stat as
|
|
69660
|
+
import { mkdtemp as mkdtemp3, rm as rm9, stat as stat12 } from "fs/promises";
|
|
69242
69661
|
import { tmpdir as tmpdir4 } from "os";
|
|
69243
|
-
import
|
|
69244
|
-
import { defineCommand as
|
|
69662
|
+
import path48 from "path";
|
|
69663
|
+
import { defineCommand as defineCommand234 } from "citty";
|
|
69245
69664
|
|
|
69246
69665
|
// src/lib/streamUpload.ts
|
|
69247
69666
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -69405,7 +69824,7 @@ registerSchema({
|
|
|
69405
69824
|
"dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
|
|
69406
69825
|
}
|
|
69407
69826
|
});
|
|
69408
|
-
var ingestCommand2 =
|
|
69827
|
+
var ingestCommand2 = defineCommand234({
|
|
69409
69828
|
meta: {
|
|
69410
69829
|
name: "ingest",
|
|
69411
69830
|
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"
|
|
@@ -69591,7 +70010,7 @@ function ingestUrl(args5) {
|
|
|
69591
70010
|
}
|
|
69592
70011
|
async function downloadThenIngest(args5, country) {
|
|
69593
70012
|
const vimeoCookie = captureVimeoCookie();
|
|
69594
|
-
const workDir = await mkdtemp3(
|
|
70013
|
+
const workDir = await mkdtemp3(path48.join(tmpdir4(), "videos-ingest-"));
|
|
69595
70014
|
try {
|
|
69596
70015
|
const probe = await probeYtDlp({ url: args5.url, country, vimeoCookie, cookieDir: workDir });
|
|
69597
70016
|
if (isAudioOnly(probe.info)) {
|
|
@@ -69622,7 +70041,7 @@ async function downloadThenIngest(args5, country) {
|
|
|
69622
70041
|
// we allow to fetch it cannot drift apart.
|
|
69623
70042
|
timeoutMs: downloadTimeoutMs(durationSeconds(probe.info))
|
|
69624
70043
|
});
|
|
69625
|
-
const stats = await
|
|
70044
|
+
const stats = await stat12(filePath);
|
|
69626
70045
|
if (stats.size > MAX_VIDEO_INGEST_BYTES) {
|
|
69627
70046
|
throw new ApiError(
|
|
69628
70047
|
"VALIDATION_ERROR",
|
|
@@ -69667,7 +70086,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
|
|
|
69667
70086
|
}
|
|
69668
70087
|
|
|
69669
70088
|
// src/commands/videos/search.ts
|
|
69670
|
-
import { defineCommand as
|
|
70089
|
+
import { defineCommand as defineCommand235 } from "citty";
|
|
69671
70090
|
registerSchema({
|
|
69672
70091
|
command: "videos.search",
|
|
69673
70092
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -69677,7 +70096,7 @@ registerSchema({
|
|
|
69677
70096
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
69678
70097
|
}
|
|
69679
70098
|
});
|
|
69680
|
-
var searchCommand4 =
|
|
70099
|
+
var searchCommand4 = defineCommand235({
|
|
69681
70100
|
meta: {
|
|
69682
70101
|
name: "search",
|
|
69683
70102
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -69727,9 +70146,9 @@ var searchCommand4 = defineCommand234({
|
|
|
69727
70146
|
var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
69728
70147
|
|
|
69729
70148
|
// src/commands/videos/upload.ts
|
|
69730
|
-
import { readFile as
|
|
70149
|
+
import { readFile as readFile34, stat as stat13 } from "fs/promises";
|
|
69731
70150
|
import { basename as basename3, extname as extname4 } from "path";
|
|
69732
|
-
import { defineCommand as
|
|
70151
|
+
import { defineCommand as defineCommand236 } from "citty";
|
|
69733
70152
|
var MIME_MAP = {
|
|
69734
70153
|
".mp4": "video/mp4",
|
|
69735
70154
|
".mov": "video/quicktime",
|
|
@@ -69771,7 +70190,7 @@ function detectContentType(filePath) {
|
|
|
69771
70190
|
function isRemoteUrl3(value) {
|
|
69772
70191
|
return /^https?:\/\//i.test(value);
|
|
69773
70192
|
}
|
|
69774
|
-
var uploadCommand2 =
|
|
70193
|
+
var uploadCommand2 = defineCommand236({
|
|
69775
70194
|
meta: {
|
|
69776
70195
|
name: "upload",
|
|
69777
70196
|
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"
|
|
@@ -69811,7 +70230,7 @@ var uploadCommand2 = defineCommand235({
|
|
|
69811
70230
|
const originalFilename = basename3(filePath);
|
|
69812
70231
|
const descriptionContext = args5.context;
|
|
69813
70232
|
if (args5["dry-run"]) {
|
|
69814
|
-
const fileStats = await
|
|
70233
|
+
const fileStats = await stat13(filePath);
|
|
69815
70234
|
writeJson({
|
|
69816
70235
|
ok: true,
|
|
69817
70236
|
dryRun: true,
|
|
@@ -69824,7 +70243,7 @@ var uploadCommand2 = defineCommand235({
|
|
|
69824
70243
|
originalFilename,
|
|
69825
70244
|
descriptionContext
|
|
69826
70245
|
});
|
|
69827
|
-
const fileBuffer = await
|
|
70246
|
+
const fileBuffer = await readFile34(filePath);
|
|
69828
70247
|
const uploadResponse = await fetch(uploadUrl, {
|
|
69829
70248
|
method: "PUT",
|
|
69830
70249
|
headers: { "Content-Type": contentType },
|
|
@@ -69855,7 +70274,7 @@ var uploadCommand2 = defineCommand235({
|
|
|
69855
70274
|
});
|
|
69856
70275
|
|
|
69857
70276
|
// src/commands/videos/index.ts
|
|
69858
|
-
var videosCommand =
|
|
70277
|
+
var videosCommand = defineCommand237({
|
|
69859
70278
|
meta: {
|
|
69860
70279
|
name: "videos",
|
|
69861
70280
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, describe, delete, tags.
|
|
@@ -69884,10 +70303,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
69884
70303
|
});
|
|
69885
70304
|
|
|
69886
70305
|
// src/commands/winning-ads/index.ts
|
|
69887
|
-
import { defineCommand as
|
|
70306
|
+
import { defineCommand as defineCommand250 } from "citty";
|
|
69888
70307
|
|
|
69889
70308
|
// src/commands/winning-ads/advertisers.ts
|
|
69890
|
-
import { defineCommand as
|
|
70309
|
+
import { defineCommand as defineCommand238 } from "citty";
|
|
69891
70310
|
|
|
69892
70311
|
// src/commands/winning-ads/shared.ts
|
|
69893
70312
|
function splitList3(value) {
|
|
@@ -69940,7 +70359,7 @@ function advertiserNormalizer(record, full) {
|
|
|
69940
70359
|
last_synced_at: record.last_synced_at ?? null
|
|
69941
70360
|
};
|
|
69942
70361
|
}
|
|
69943
|
-
var advertisersCommand2 =
|
|
70362
|
+
var advertisersCommand2 = defineCommand238({
|
|
69944
70363
|
meta: {
|
|
69945
70364
|
name: "advertisers",
|
|
69946
70365
|
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'
|
|
@@ -69998,7 +70417,7 @@ var advertisersCommand2 = defineCommand237({
|
|
|
69998
70417
|
});
|
|
69999
70418
|
|
|
70000
70419
|
// src/commands/winning-ads/brief.ts
|
|
70001
|
-
import { defineCommand as
|
|
70420
|
+
import { defineCommand as defineCommand239 } from "citty";
|
|
70002
70421
|
registerSchema({
|
|
70003
70422
|
command: "winning-ads.brief",
|
|
70004
70423
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -70044,7 +70463,7 @@ function parseDna(raw) {
|
|
|
70044
70463
|
}
|
|
70045
70464
|
return parsed;
|
|
70046
70465
|
}
|
|
70047
|
-
var briefCommand =
|
|
70466
|
+
var briefCommand = defineCommand239({
|
|
70048
70467
|
meta: {
|
|
70049
70468
|
name: "brief",
|
|
70050
70469
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -70080,7 +70499,7 @@ var briefCommand = defineCommand238({
|
|
|
70080
70499
|
});
|
|
70081
70500
|
|
|
70082
70501
|
// src/commands/winning-ads/content.ts
|
|
70083
|
-
import { defineCommand as
|
|
70502
|
+
import { defineCommand as defineCommand240 } from "citty";
|
|
70084
70503
|
registerSchema({
|
|
70085
70504
|
command: "winning-ads.content",
|
|
70086
70505
|
description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Add --full for speech, pacing, and soundtrack detail. Video ads carry the transcript/on-screen text; static ads carry only the copy.",
|
|
@@ -70093,7 +70512,7 @@ registerSchema({
|
|
|
70093
70512
|
}
|
|
70094
70513
|
}
|
|
70095
70514
|
});
|
|
70096
|
-
var contentCommand =
|
|
70515
|
+
var contentCommand = defineCommand240({
|
|
70097
70516
|
meta: {
|
|
70098
70517
|
name: "content",
|
|
70099
70518
|
description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
@@ -70142,7 +70561,7 @@ var contentCommand = defineCommand239({
|
|
|
70142
70561
|
});
|
|
70143
70562
|
|
|
70144
70563
|
// src/commands/winning-ads/feed.ts
|
|
70145
|
-
import { defineCommand as
|
|
70564
|
+
import { defineCommand as defineCommand241 } from "citty";
|
|
70146
70565
|
function buildFeedParams(input) {
|
|
70147
70566
|
const params2 = {};
|
|
70148
70567
|
const advertiser = splitList3(input.advertiser);
|
|
@@ -70194,7 +70613,7 @@ registerSchema({
|
|
|
70194
70613
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
70195
70614
|
}
|
|
70196
70615
|
});
|
|
70197
|
-
var feedCommand2 =
|
|
70616
|
+
var feedCommand2 = defineCommand241({
|
|
70198
70617
|
meta: {
|
|
70199
70618
|
name: "feed",
|
|
70200
70619
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -70279,7 +70698,7 @@ var feedCommand2 = defineCommand240({
|
|
|
70279
70698
|
});
|
|
70280
70699
|
|
|
70281
70700
|
// src/commands/winning-ads/follow.ts
|
|
70282
|
-
import { defineCommand as
|
|
70701
|
+
import { defineCommand as defineCommand242 } from "citty";
|
|
70283
70702
|
var PLATFORMS = adLibraryPlatformSchema.options;
|
|
70284
70703
|
registerSchema({
|
|
70285
70704
|
command: "winning-ads.follow",
|
|
@@ -70294,7 +70713,7 @@ registerSchema({
|
|
|
70294
70713
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
70295
70714
|
}
|
|
70296
70715
|
});
|
|
70297
|
-
var followCommand =
|
|
70716
|
+
var followCommand = defineCommand242({
|
|
70298
70717
|
meta: {
|
|
70299
70718
|
name: "follow",
|
|
70300
70719
|
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'
|
|
@@ -70341,7 +70760,7 @@ var followCommand = defineCommand241({
|
|
|
70341
70760
|
});
|
|
70342
70761
|
|
|
70343
70762
|
// src/commands/winning-ads/follow-competitors.ts
|
|
70344
|
-
import { defineCommand as
|
|
70763
|
+
import { defineCommand as defineCommand243 } from "citty";
|
|
70345
70764
|
var PLATFORMS2 = adLibraryPlatformSchema.options;
|
|
70346
70765
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
70347
70766
|
function buildFollowBatchBody(input) {
|
|
@@ -70374,7 +70793,7 @@ registerSchema({
|
|
|
70374
70793
|
}
|
|
70375
70794
|
}
|
|
70376
70795
|
});
|
|
70377
|
-
var followCompetitorsCommand =
|
|
70796
|
+
var followCompetitorsCommand = defineCommand243({
|
|
70378
70797
|
meta: {
|
|
70379
70798
|
name: "follow-competitors",
|
|
70380
70799
|
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"'
|
|
@@ -70449,7 +70868,7 @@ var followCompetitorsCommand = defineCommand242({
|
|
|
70449
70868
|
});
|
|
70450
70869
|
|
|
70451
70870
|
// src/commands/winning-ads/following.ts
|
|
70452
|
-
import { defineCommand as
|
|
70871
|
+
import { defineCommand as defineCommand244 } from "citty";
|
|
70453
70872
|
registerSchema({
|
|
70454
70873
|
command: "winning-ads.following",
|
|
70455
70874
|
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.",
|
|
@@ -70503,7 +70922,7 @@ function followingNormalizer(record, full) {
|
|
|
70503
70922
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
70504
70923
|
};
|
|
70505
70924
|
}
|
|
70506
|
-
var followingCommand =
|
|
70925
|
+
var followingCommand = defineCommand244({
|
|
70507
70926
|
meta: {
|
|
70508
70927
|
name: "following",
|
|
70509
70928
|
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"
|
|
@@ -70539,7 +70958,7 @@ var followingCommand = defineCommand243({
|
|
|
70539
70958
|
});
|
|
70540
70959
|
|
|
70541
70960
|
// src/commands/winning-ads/patterns.ts
|
|
70542
|
-
import { defineCommand as
|
|
70961
|
+
import { defineCommand as defineCommand245 } from "citty";
|
|
70543
70962
|
registerSchema({
|
|
70544
70963
|
command: "winning-ads.patterns",
|
|
70545
70964
|
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.",
|
|
@@ -70578,7 +70997,7 @@ function discriminatorRow(record) {
|
|
|
70578
70997
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
70579
70998
|
};
|
|
70580
70999
|
}
|
|
70581
|
-
var patternsCommand =
|
|
71000
|
+
var patternsCommand = defineCommand245({
|
|
70582
71001
|
meta: {
|
|
70583
71002
|
name: "patterns",
|
|
70584
71003
|
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"
|
|
@@ -70634,7 +71053,7 @@ var patternsCommand = defineCommand244({
|
|
|
70634
71053
|
});
|
|
70635
71054
|
|
|
70636
71055
|
// src/commands/winning-ads/search.ts
|
|
70637
|
-
import { defineCommand as
|
|
71056
|
+
import { defineCommand as defineCommand246 } from "citty";
|
|
70638
71057
|
registerSchema({
|
|
70639
71058
|
command: "winning-ads.search",
|
|
70640
71059
|
description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
|
|
@@ -70772,7 +71191,7 @@ function reportSearchError(err) {
|
|
|
70772
71191
|
}
|
|
70773
71192
|
reportError2(err);
|
|
70774
71193
|
}
|
|
70775
|
-
var searchCommand5 =
|
|
71194
|
+
var searchCommand5 = defineCommand246({
|
|
70776
71195
|
meta: {
|
|
70777
71196
|
name: "search",
|
|
70778
71197
|
description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
|
|
@@ -70892,7 +71311,7 @@ var searchCommand5 = defineCommand245({
|
|
|
70892
71311
|
});
|
|
70893
71312
|
|
|
70894
71313
|
// src/commands/winning-ads/seeds.ts
|
|
70895
|
-
import { defineCommand as
|
|
71314
|
+
import { defineCommand as defineCommand247 } from "citty";
|
|
70896
71315
|
function leanRow(r) {
|
|
70897
71316
|
return {
|
|
70898
71317
|
key: r.key,
|
|
@@ -70920,7 +71339,7 @@ function makeSeedCommand(opts) {
|
|
|
70920
71339
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
70921
71340
|
}
|
|
70922
71341
|
});
|
|
70923
|
-
return
|
|
71342
|
+
return defineCommand247({
|
|
70924
71343
|
meta: { name: opts.name, description: opts.description },
|
|
70925
71344
|
args: {
|
|
70926
71345
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -70969,7 +71388,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
70969
71388
|
});
|
|
70970
71389
|
|
|
70971
71390
|
// src/commands/winning-ads/unfollow.ts
|
|
70972
|
-
import { defineCommand as
|
|
71391
|
+
import { defineCommand as defineCommand248 } from "citty";
|
|
70973
71392
|
registerSchema({
|
|
70974
71393
|
command: "winning-ads.unfollow",
|
|
70975
71394
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -70977,7 +71396,7 @@ registerSchema({
|
|
|
70977
71396
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
70978
71397
|
}
|
|
70979
71398
|
});
|
|
70980
|
-
var unfollowCommand =
|
|
71399
|
+
var unfollowCommand = defineCommand248({
|
|
70981
71400
|
meta: {
|
|
70982
71401
|
name: "unfollow",
|
|
70983
71402
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -70998,7 +71417,7 @@ var unfollowCommand = defineCommand247({
|
|
|
70998
71417
|
});
|
|
70999
71418
|
|
|
71000
71419
|
// src/commands/winning-ads/winners.ts
|
|
71001
|
-
import { defineCommand as
|
|
71420
|
+
import { defineCommand as defineCommand249 } from "citty";
|
|
71002
71421
|
registerSchema({
|
|
71003
71422
|
command: "winning-ads.winners",
|
|
71004
71423
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -71008,7 +71427,7 @@ registerSchema({
|
|
|
71008
71427
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
|
|
71009
71428
|
}
|
|
71010
71429
|
});
|
|
71011
|
-
var winnersCommand =
|
|
71430
|
+
var winnersCommand = defineCommand249({
|
|
71012
71431
|
meta: {
|
|
71013
71432
|
name: "winners",
|
|
71014
71433
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -71058,7 +71477,7 @@ var winnersCommand = defineCommand248({
|
|
|
71058
71477
|
});
|
|
71059
71478
|
|
|
71060
71479
|
// src/commands/winning-ads/index.ts
|
|
71061
|
-
var winningAdsCommand =
|
|
71480
|
+
var winningAdsCommand = defineCommand250({
|
|
71062
71481
|
meta: {
|
|
71063
71482
|
name: "winning-ads",
|
|
71064
71483
|
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.
|
|
@@ -71284,7 +71703,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion, hasSchema) {
|
|
|
71284
71703
|
};
|
|
71285
71704
|
}
|
|
71286
71705
|
function commandPathOf(root, argv) {
|
|
71287
|
-
const
|
|
71706
|
+
const path49 = [];
|
|
71288
71707
|
let command = root;
|
|
71289
71708
|
for (const token of argv) {
|
|
71290
71709
|
if (token === "--" || token.startsWith("-")) {
|
|
@@ -71295,10 +71714,10 @@ function commandPathOf(root, argv) {
|
|
|
71295
71714
|
if (next === void 0 || typeof next !== "object") {
|
|
71296
71715
|
break;
|
|
71297
71716
|
}
|
|
71298
|
-
|
|
71717
|
+
path49.push(token);
|
|
71299
71718
|
command = next;
|
|
71300
71719
|
}
|
|
71301
|
-
return
|
|
71720
|
+
return path49.join(" ");
|
|
71302
71721
|
}
|
|
71303
71722
|
function refuseUnknownFlags(root, argv) {
|
|
71304
71723
|
const unknown = findUnknownFlags(root, argv);
|
|
@@ -71308,9 +71727,9 @@ function refuseUnknownFlags(root, argv) {
|
|
|
71308
71727
|
const command = commandFor(root, argv);
|
|
71309
71728
|
const first = unknown[0];
|
|
71310
71729
|
const suggestion = command && first ? suggestFlag(first, command) : null;
|
|
71311
|
-
const
|
|
71730
|
+
const path49 = commandPathOf(root, argv);
|
|
71312
71731
|
process.stdout.write(
|
|
71313
|
-
`${JSON.stringify(unknownFlagEnvelope(unknown,
|
|
71732
|
+
`${JSON.stringify(unknownFlagEnvelope(unknown, path49, suggestion, findSchema(path49.split(" ")) !== void 0), null, 2)}
|
|
71314
71733
|
`
|
|
71315
71734
|
);
|
|
71316
71735
|
process.exit(1);
|
|
@@ -71385,7 +71804,7 @@ function getCliVersion() {
|
|
|
71385
71804
|
}
|
|
71386
71805
|
|
|
71387
71806
|
// src/cli.ts
|
|
71388
|
-
var main =
|
|
71807
|
+
var main = defineCommand251({
|
|
71389
71808
|
meta: {
|
|
71390
71809
|
name: "baker",
|
|
71391
71810
|
version: getCliVersion(),
|