@koda-sl/baker-cli 0.147.0 → 0.149.0-dev.183ac88ea
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 +25 -25
- package/dist/{chunk-2F5SCTNS.js → chunk-JBDSJZBZ.js} +64 -21
- package/dist/chunk-JBDSJZBZ.js.map +1 -0
- package/dist/cli.js +689 -95
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2F5SCTNS.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
imageProfileFor,
|
|
25
25
|
isPersistedAssetRef,
|
|
26
26
|
looksLikeHttpUrl,
|
|
27
|
+
nearestSupportedAspectRatio,
|
|
27
28
|
parseRefExpr,
|
|
28
29
|
platformFormats,
|
|
29
30
|
requireCredentialsFromEnv,
|
|
@@ -31,10 +32,11 @@ import {
|
|
|
31
32
|
sha256Hex,
|
|
32
33
|
spineInputFlags,
|
|
33
34
|
spineInputOps,
|
|
35
|
+
supportsParam,
|
|
34
36
|
toModelSafeImage,
|
|
35
37
|
ulid,
|
|
36
38
|
validateCanvasDeep
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-JBDSJZBZ.js";
|
|
38
40
|
import {
|
|
39
41
|
csvOrJson,
|
|
40
42
|
daysAgoIso,
|
|
@@ -73,7 +75,7 @@ import {
|
|
|
73
75
|
} from "./chunk-RK67WL4O.js";
|
|
74
76
|
|
|
75
77
|
// src/cli.ts
|
|
76
|
-
import { defineCommand as
|
|
78
|
+
import { defineCommand as defineCommand182, runMain } from "citty";
|
|
77
79
|
|
|
78
80
|
// src/commands/actions/index.ts
|
|
79
81
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -2131,6 +2133,7 @@ var chatChangeTypeSchema = z5.enum([
|
|
|
2131
2133
|
"linkedin-ads",
|
|
2132
2134
|
"google-ads",
|
|
2133
2135
|
"meta-ads",
|
|
2136
|
+
"tag-manager",
|
|
2134
2137
|
// Immediate (already-applied) library effects — see lib/chatChanges.ts.
|
|
2135
2138
|
"image",
|
|
2136
2139
|
"video",
|
|
@@ -2707,8 +2710,9 @@ var rgbTriple = z8.tuple([
|
|
|
2707
2710
|
z8.number().int().min(0).max(255)
|
|
2708
2711
|
]);
|
|
2709
2712
|
var imageGenerateModelSchema = z8.enum([
|
|
2713
|
+
"openai/gpt-image-2",
|
|
2714
|
+
// Legacy — see the registry entry; kept so pre-switch canvases still run.
|
|
2710
2715
|
"openai/gpt-5.4-image-2",
|
|
2711
|
-
"google/gemini-3.5-flash",
|
|
2712
2716
|
"google/gemini-3.1-flash-image-preview",
|
|
2713
2717
|
"google/gemini-3-pro-image-preview",
|
|
2714
2718
|
"recraft/recraft-v4.1-pro-vector"
|
|
@@ -5395,17 +5399,27 @@ var googleDraftStageRequestSchema = z13.object({
|
|
|
5395
5399
|
chatId: z13.string(),
|
|
5396
5400
|
op: googleDraftOpInputSchema
|
|
5397
5401
|
});
|
|
5398
|
-
var googleDraftStageResponseSchema = z13.
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5402
|
+
var googleDraftStageResponseSchema = z13.discriminatedUnion("staged", [
|
|
5403
|
+
z13.object({
|
|
5404
|
+
staged: z13.literal(true),
|
|
5405
|
+
ref: z13.string(),
|
|
5406
|
+
kind: googleDraftOpKindSchema,
|
|
5407
|
+
mode: googleWriteModeSchema,
|
|
5408
|
+
dependsOn: z13.array(z13.string()),
|
|
5409
|
+
summary: z13.string(),
|
|
5410
|
+
warnings: z13.array(z13.string()),
|
|
5411
|
+
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
5412
|
+
amended: z13.boolean().optional()
|
|
5413
|
+
}),
|
|
5414
|
+
z13.object({
|
|
5415
|
+
staged: z13.literal(false),
|
|
5416
|
+
noop: z13.literal(true),
|
|
5417
|
+
kind: googleDraftOpKindSchema,
|
|
5418
|
+
mode: googleWriteModeSchema,
|
|
5419
|
+
summary: z13.string(),
|
|
5420
|
+
reason: z13.string()
|
|
5421
|
+
})
|
|
5422
|
+
]);
|
|
5409
5423
|
var googleDraftAmendRequestSchema = z13.object({
|
|
5410
5424
|
chatId: z13.string(),
|
|
5411
5425
|
ref: z13.string(),
|
|
@@ -5432,7 +5446,8 @@ var googleDraftStageBatchResponseSchema = z13.object({
|
|
|
5432
5446
|
summary: z13.string(),
|
|
5433
5447
|
warnings: z13.array(z13.string())
|
|
5434
5448
|
})
|
|
5435
|
-
)
|
|
5449
|
+
),
|
|
5450
|
+
skipped: z13.array(z13.object({ kind: googleDraftOpKindSchema, summary: z13.string(), reason: z13.string() })).optional()
|
|
5436
5451
|
});
|
|
5437
5452
|
var googleDraftOpViewSchema = z13.object({
|
|
5438
5453
|
ref: z13.string(),
|
|
@@ -5691,7 +5706,7 @@ function keywordEntries(args) {
|
|
|
5691
5706
|
const seen = /* @__PURE__ */ new Set();
|
|
5692
5707
|
for (const item of raw) {
|
|
5693
5708
|
const entry = parseKeywordEntry(item, defaultMatch);
|
|
5694
|
-
const key =
|
|
5709
|
+
const key = JSON.stringify([entry.text, entry.matchType]);
|
|
5695
5710
|
if (!seen.has(key)) {
|
|
5696
5711
|
seen.add(key);
|
|
5697
5712
|
entries.push(entry);
|
|
@@ -5758,6 +5773,9 @@ function handleGoogleError(err) {
|
|
|
5758
5773
|
});
|
|
5759
5774
|
process.exit(1);
|
|
5760
5775
|
}
|
|
5776
|
+
function noopHints(data) {
|
|
5777
|
+
return data.staged ? [] : [`NOT STAGED \u2014 ${data.reason}. Nothing to publish for this change; say so rather than reporting it as done.`];
|
|
5778
|
+
}
|
|
5761
5779
|
async function stageGoogleOp(raw, hints) {
|
|
5762
5780
|
const preflight = googleDraftOpInputSchema.safeParse(raw);
|
|
5763
5781
|
if (!preflight.success) {
|
|
@@ -5775,7 +5793,8 @@ async function stageGoogleOp(raw, hints) {
|
|
|
5775
5793
|
try {
|
|
5776
5794
|
const chatId = requireChatId();
|
|
5777
5795
|
const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
|
|
5778
|
-
|
|
5796
|
+
const allHints = [...noopHints(response.data), ...hints ?? []];
|
|
5797
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
5779
5798
|
} catch (err) {
|
|
5780
5799
|
handleGoogleError(err);
|
|
5781
5800
|
}
|
|
@@ -5811,7 +5830,14 @@ async function stageGoogleOps(rawOps, hints) {
|
|
|
5811
5830
|
try {
|
|
5812
5831
|
const chatId = requireChatId();
|
|
5813
5832
|
const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
|
|
5814
|
-
|
|
5833
|
+
const skipped = response.data.skipped ?? [];
|
|
5834
|
+
const allHints = [
|
|
5835
|
+
...skipped.length > 0 ? [
|
|
5836
|
+
`${skipped.length} of ${ops.length} op(s) NOT STAGED \u2014 already in the requested state: ${skipped.map((s) => s.reason).join("; ")}`
|
|
5837
|
+
] : [],
|
|
5838
|
+
...hints ?? []
|
|
5839
|
+
];
|
|
5840
|
+
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
5815
5841
|
} catch (err) {
|
|
5816
5842
|
handleGoogleError(err);
|
|
5817
5843
|
}
|
|
@@ -16631,7 +16657,9 @@ function buildFrameRef(edge, url, framePrompt, present2, ctx, nodes) {
|
|
|
16631
16657
|
const imageProfile = imageProfileFor(ctx.imageModel);
|
|
16632
16658
|
const genParams = {
|
|
16633
16659
|
model: ctx.imageModel,
|
|
16634
|
-
|
|
16660
|
+
// gpt-image-2 derives pixel dimensions from the ratio and has no size knob,
|
|
16661
|
+
// so asking for 2K there is an `unknown_param` at validate.
|
|
16662
|
+
...supportsParam("image_generate", ctx.imageModel, "image_size") ? { image_size: "2K" } : {},
|
|
16635
16663
|
// Per-model image defaults (gpt-image: quality=high — OpenRouter forwards it; we do
|
|
16636
16664
|
// NOT send input_fidelity, which gpt-image-2 forces high automatically).
|
|
16637
16665
|
...imageProfile?.paramDefaults ?? {},
|
|
@@ -16646,7 +16674,7 @@ function buildFrameRef(edge, url, framePrompt, present2, ctx, nodes) {
|
|
|
16646
16674
|
ctx.imageModel
|
|
16647
16675
|
)
|
|
16648
16676
|
};
|
|
16649
|
-
if (ctx.genAr) genParams.aspect_ratio = ctx.genAr;
|
|
16677
|
+
if (ctx.genAr) genParams.aspect_ratio = nearestSupportedAspectRatio("image_generate", ctx.imageModel, ctx.genAr);
|
|
16650
16678
|
const genId = `s${ctx.sceneIndex}${tag}_${edge}`;
|
|
16651
16679
|
nodes.push({
|
|
16652
16680
|
id: genId,
|
|
@@ -20373,8 +20401,13 @@ function scaffoldStaticAd(input, elementsInput, opts) {
|
|
|
20373
20401
|
inputs: { reference, target_blueprint: "$ref:prompt.asset" },
|
|
20374
20402
|
params: {
|
|
20375
20403
|
model: opts.genModel,
|
|
20376
|
-
|
|
20377
|
-
|
|
20404
|
+
// The hero renders at the closest ratio its model actually accepts; the
|
|
20405
|
+
// placement fan-out below adapts it to the exact platform formats, which
|
|
20406
|
+
// is also how a 4:5 Meta feed ad gets made on a model that has no 4:5.
|
|
20407
|
+
aspect_ratio: nearestSupportedAspectRatio("image_generate", opts.genModel, baseAspectRatio(blueprint, opts)),
|
|
20408
|
+
...supportsParam("image_generate", opts.genModel, "image_size") ? { image_size: "2K" } : {},
|
|
20409
|
+
// Per-model image defaults (gpt-image: quality=high).
|
|
20410
|
+
...imageProfileFor(opts.genModel)?.paramDefaults ?? {},
|
|
20378
20411
|
prompt
|
|
20379
20412
|
}
|
|
20380
20413
|
});
|
|
@@ -20741,7 +20774,7 @@ function resolveModels(args) {
|
|
|
20741
20774
|
describeModel: pick("describe-model", "image_describe", "~google/gemini-pro-latest"),
|
|
20742
20775
|
selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
|
|
20743
20776
|
layoutModel: pick("layout-model", "text_generate", "~google/gemini-flash-latest"),
|
|
20744
|
-
genModel: pick("gen-model", "image_generate", "openai/gpt-
|
|
20777
|
+
genModel: pick("gen-model", "image_generate", "openai/gpt-image-2")
|
|
20745
20778
|
};
|
|
20746
20779
|
}
|
|
20747
20780
|
var PLATFORM_PLACEMENTS = {
|
|
@@ -21383,7 +21416,7 @@ function resolveModels2(args) {
|
|
|
21383
21416
|
// Default to the strongest image model (matches the static-ad scaffold); the
|
|
21384
21417
|
// frame generators need the most faithful text/identity reproduction. Override
|
|
21385
21418
|
// with --image-model for a cheaper/faster pass.
|
|
21386
|
-
imageModel: pick("image-model", "image_generate", "openai/gpt-
|
|
21419
|
+
imageModel: pick("image-model", "image_generate", "openai/gpt-image-2")
|
|
21387
21420
|
};
|
|
21388
21421
|
}
|
|
21389
21422
|
function hasPhotorealCast(elements) {
|
|
@@ -24093,7 +24126,7 @@ async function resolveReferences(spec) {
|
|
|
24093
24126
|
var generateCommand = defineCommand114({
|
|
24094
24127
|
meta: {
|
|
24095
24128
|
name: "generate",
|
|
24096
|
-
description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: google/gemini-3.1-flash-image-preview (Nano Banana flash \u2014 default, fast, extreme aspect ratios)
|
|
24129
|
+
description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: google/gemini-3.1-flash-image-preview (Nano Banana flash \u2014 default, fast, extreme aspect ratios), google/gemini-3-pro-image-preview (Nano Banana Pro \u2014 highest fidelity), openai/gpt-image-2 (photoreal, cleanest in-image text, best for ad/landing reproduction \u2014 no --image-size, and no 4:5 / 5:4), recraft/recraft-v4.1-pro-vector (vector/SVG-style with palette control). The result is auto-ingested (describe + embed), so the next `baker images library` query finds it. Pass --reference with image URLs and/or local file paths (Pinterest, stock, brand assets, sandbox files) to ground generation in reality.\n\nExamples:\n baker images generate 'a friendly golden retriever sitting in a bright modern living room' --aspect-ratio 16:9\n baker images generate 'hero shot of a matte black water bottle on marble' --model openai/gpt-image-2 --aspect-ratio 3:2\n baker images generate 'lifestyle photo matching this mood' --reference 'https://\u2026/ref1.jpg,https://\u2026/ref2.jpg'\n baker images generate 'put this product on a marble countertop, soft daylight' --reference './src/brand/logos/product.png,./refs/kitchen-mood.jpg'\n baker images generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
|
|
24097
24130
|
},
|
|
24098
24131
|
args: {
|
|
24099
24132
|
prompt: { type: "positional", description: "What to generate", required: false },
|
|
@@ -24266,6 +24299,34 @@ var gifCommand = defineCommand116({
|
|
|
24266
24299
|
|
|
24267
24300
|
// src/commands/images/google.ts
|
|
24268
24301
|
import { defineCommand as defineCommand117 } from "citty";
|
|
24302
|
+
|
|
24303
|
+
// src/commands/images/searchHints.ts
|
|
24304
|
+
var FALLBACK = {
|
|
24305
|
+
stock: "Still empty \u2192 `baker images find <query> --sources library,pinterest,google` (one call across the providers stock does not cover \u2014 `--sources` is required, `find` alone searches the library only) or `baker images generate` to make the asset. Do not re-run this search with reshuffled flags.",
|
|
24306
|
+
google: "Still empty \u2192 `baker images generate` to make the asset. Google is the last-resort provider; there is nothing below it to retry."
|
|
24307
|
+
};
|
|
24308
|
+
function emptyResultHints({ provider, hitCount, activeFilters }) {
|
|
24309
|
+
if (hitCount > 0) {
|
|
24310
|
+
return [];
|
|
24311
|
+
}
|
|
24312
|
+
const hints = [];
|
|
24313
|
+
if (activeFilters.length > 0) {
|
|
24314
|
+
hints.push(
|
|
24315
|
+
`No hits. Drop the filters before touching the query \u2014 ${activeFilters.join(", ")} narrowed this search and filter combinations are the usual cause of an empty result.`
|
|
24316
|
+
);
|
|
24317
|
+
}
|
|
24318
|
+
hints.push(FALLBACK[provider]);
|
|
24319
|
+
return hints;
|
|
24320
|
+
}
|
|
24321
|
+
function activeFilterFlags(args, candidates) {
|
|
24322
|
+
return candidates.filter((flag) => args[flag] !== void 0 && args[flag] !== "").map((flag) => `--${flag}`);
|
|
24323
|
+
}
|
|
24324
|
+
|
|
24325
|
+
// src/commands/images/google.ts
|
|
24326
|
+
var GOOGLE_ERROR_FIX = {
|
|
24327
|
+
action: "use_different_resource",
|
|
24328
|
+
explanation: "Generate the asset instead of retrying Google. Google is the last-resort image provider. Run `baker images generate` to make the asset. Never sleep-and-retry this command \u2014 the CLI already backs off on rate limits. If no image can be sourced, continue the rest of the task with a placeholder rather than aborting it."
|
|
24329
|
+
};
|
|
24269
24330
|
registerSchema({
|
|
24270
24331
|
command: "images.google",
|
|
24271
24332
|
description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
|
|
@@ -24336,10 +24397,18 @@ var googleCommand2 = defineCommand117({
|
|
|
24336
24397
|
if (args["auto-ingest"]) body.autoIngest = Number(args["auto-ingest"]);
|
|
24337
24398
|
if (args.context) body.descriptionContext = args.context;
|
|
24338
24399
|
const data = await apiPost("/api/images/google", body);
|
|
24339
|
-
|
|
24400
|
+
const hints = emptyResultHints({
|
|
24401
|
+
provider: "google",
|
|
24402
|
+
hitCount: data.hits.length,
|
|
24403
|
+
activeFilters: activeFilterFlags(args, ["type", "size", "color", "safe"])
|
|
24404
|
+
});
|
|
24405
|
+
writeJson({ ok: true, data, ...hints.length ? { hints } : {} });
|
|
24340
24406
|
} catch (err) {
|
|
24341
24407
|
if (err instanceof ApiError) {
|
|
24342
|
-
writeJson({
|
|
24408
|
+
writeJson({
|
|
24409
|
+
ok: false,
|
|
24410
|
+
error: { code: err.code, message: err.message, fix: GOOGLE_ERROR_FIX }
|
|
24411
|
+
});
|
|
24343
24412
|
process.exit(1);
|
|
24344
24413
|
}
|
|
24345
24414
|
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
@@ -25697,6 +25766,10 @@ var stickerCommand = defineCommand126({
|
|
|
25697
25766
|
|
|
25698
25767
|
// src/commands/images/stock.ts
|
|
25699
25768
|
import { defineCommand as defineCommand127 } from "citty";
|
|
25769
|
+
var STOCK_ERROR_FIX = {
|
|
25770
|
+
action: "use_different_resource",
|
|
25771
|
+
explanation: "Switch provider instead of retrying stock search. Stock search is one of several image sources. Run `baker images find <query> --sources library,pinterest,google` (`--sources` is required \u2014 `find` alone searches the library only) or `baker images generate` to make the asset. Never sleep-and-retry this command \u2014 the CLI already backs off on rate limits. If no image can be sourced, continue the rest of the task with a placeholder rather than aborting it."
|
|
25772
|
+
};
|
|
25700
25773
|
registerSchema({
|
|
25701
25774
|
command: "images.stock",
|
|
25702
25775
|
description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
|
|
@@ -25754,6 +25827,21 @@ registerSchema({
|
|
|
25754
25827
|
}
|
|
25755
25828
|
}
|
|
25756
25829
|
});
|
|
25830
|
+
function buildStockRequest(query, args) {
|
|
25831
|
+
const body = { query };
|
|
25832
|
+
if (args.type) body.contentType = args.type;
|
|
25833
|
+
if (args.orientation) body.orientation = args.orientation;
|
|
25834
|
+
if (args.license) body.license = args.license;
|
|
25835
|
+
if (args.color) body.color = args.color;
|
|
25836
|
+
if (args.ai) body.aiGenerated = args.ai;
|
|
25837
|
+
if (args.people) body.people = args.people;
|
|
25838
|
+
if (args.order) body.order = args.order;
|
|
25839
|
+
if (args.limit) body.limit = Number(args.limit);
|
|
25840
|
+
if (args.page) body.page = Number(args.page);
|
|
25841
|
+
if (args["auto-ingest"]) body.autoIngest = Number(args["auto-ingest"]);
|
|
25842
|
+
if (args.context) body.descriptionContext = args.context;
|
|
25843
|
+
return body;
|
|
25844
|
+
}
|
|
25757
25845
|
var stockCommand = defineCommand127({
|
|
25758
25846
|
meta: {
|
|
25759
25847
|
name: "stock",
|
|
@@ -25784,23 +25872,23 @@ var stockCommand = defineCommand127({
|
|
|
25784
25872
|
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Query is required" } });
|
|
25785
25873
|
process.exit(1);
|
|
25786
25874
|
}
|
|
25787
|
-
const
|
|
25788
|
-
|
|
25789
|
-
|
|
25790
|
-
|
|
25791
|
-
|
|
25792
|
-
|
|
25793
|
-
|
|
25794
|
-
if (args.order) body.order = args.order;
|
|
25795
|
-
if (args.limit) body.limit = Number(args.limit);
|
|
25796
|
-
if (args.page) body.page = Number(args.page);
|
|
25797
|
-
if (args["auto-ingest"]) body.autoIngest = Number(args["auto-ingest"]);
|
|
25798
|
-
if (args.context) body.descriptionContext = args.context;
|
|
25799
|
-
const data = await apiPost("/api/images/stock", body);
|
|
25800
|
-
writeJson({ ok: true, data });
|
|
25875
|
+
const data = await apiPost("/api/images/stock", buildStockRequest(query, args));
|
|
25876
|
+
const hints = emptyResultHints({
|
|
25877
|
+
provider: "stock",
|
|
25878
|
+
hitCount: data.hits.length,
|
|
25879
|
+
activeFilters: activeFilterFlags(args, ["type", "orientation", "license", "color", "ai", "people"])
|
|
25880
|
+
});
|
|
25881
|
+
writeJson({ ok: true, data, ...hints.length ? { hints } : {} });
|
|
25801
25882
|
} catch (err) {
|
|
25802
25883
|
if (err instanceof ApiError) {
|
|
25803
|
-
writeJson({
|
|
25884
|
+
writeJson({
|
|
25885
|
+
ok: false,
|
|
25886
|
+
error: {
|
|
25887
|
+
code: err.code,
|
|
25888
|
+
message: err.message,
|
|
25889
|
+
fix: STOCK_ERROR_FIX
|
|
25890
|
+
}
|
|
25891
|
+
});
|
|
25804
25892
|
process.exit(1);
|
|
25805
25893
|
}
|
|
25806
25894
|
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
@@ -28931,9 +29019,514 @@ var schemaCommand = defineCommand154({
|
|
|
28931
29019
|
}
|
|
28932
29020
|
});
|
|
28933
29021
|
|
|
28934
|
-
// src/commands/
|
|
29022
|
+
// src/commands/tag-manager/index.ts
|
|
29023
|
+
import { defineCommand as defineCommand158 } from "citty";
|
|
29024
|
+
|
|
29025
|
+
// src/commands/tag-manager/draft.ts
|
|
28935
29026
|
import { defineCommand as defineCommand155 } from "citty";
|
|
28936
29027
|
|
|
29028
|
+
// src/commands/tag-manager/shared.ts
|
|
29029
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
29030
|
+
function failValidation3(message) {
|
|
29031
|
+
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
29032
|
+
process.exit(1);
|
|
29033
|
+
}
|
|
29034
|
+
function requireTarget4(args, entity) {
|
|
29035
|
+
const positional = Array.isArray(args._) ? args._[0] : void 0;
|
|
29036
|
+
const target = args.id ?? args.target ?? positional;
|
|
29037
|
+
if (typeof target !== "string" || target.length === 0) {
|
|
29038
|
+
failValidation3(`pass the ${entity} id or path as the positional argument`);
|
|
29039
|
+
}
|
|
29040
|
+
return target;
|
|
29041
|
+
}
|
|
29042
|
+
function loadJsonArg(args, flag = "json") {
|
|
29043
|
+
const inline = args[flag];
|
|
29044
|
+
const file = args.file;
|
|
29045
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync12(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
29046
|
+
if (raw === void 0) {
|
|
29047
|
+
failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
29048
|
+
}
|
|
29049
|
+
try {
|
|
29050
|
+
const parsed = JSON.parse(raw);
|
|
29051
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
29052
|
+
failValidation3(`--${flag} must be a JSON object`);
|
|
29053
|
+
}
|
|
29054
|
+
return parsed;
|
|
29055
|
+
} catch {
|
|
29056
|
+
return failValidation3(`--${flag} is not valid JSON`);
|
|
29057
|
+
}
|
|
29058
|
+
}
|
|
29059
|
+
function handleError3(err) {
|
|
29060
|
+
if (err instanceof ApiError) {
|
|
29061
|
+
const notConnected = err.code === "NOT_FOUND" || err.code === "UNAUTHORIZED";
|
|
29062
|
+
writeJsonEnvelope({
|
|
29063
|
+
ok: false,
|
|
29064
|
+
error: {
|
|
29065
|
+
code: err.code,
|
|
29066
|
+
message: err.message,
|
|
29067
|
+
...notConnected ? {
|
|
29068
|
+
fix: {
|
|
29069
|
+
action: "ask_user",
|
|
29070
|
+
explanation: "Tag Manager is not connected for this company yet. Ask the user to connect Tag Manager in Settings \u2192 Connections and pick the container to manage, then retry. Continue with the rest of the task in the meantime."
|
|
29071
|
+
}
|
|
29072
|
+
} : {},
|
|
29073
|
+
retryable: false
|
|
29074
|
+
}
|
|
29075
|
+
});
|
|
29076
|
+
process.exit(1);
|
|
29077
|
+
}
|
|
29078
|
+
writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
29079
|
+
process.exit(1);
|
|
29080
|
+
}
|
|
29081
|
+
function stageHints(response) {
|
|
29082
|
+
const hints = [];
|
|
29083
|
+
if (response.mode === "simulated") {
|
|
29084
|
+
hints.push(
|
|
29085
|
+
"Tag Manager writes are SIMULATED for this company \u2014 this change will not reach the real container on publish."
|
|
29086
|
+
);
|
|
29087
|
+
}
|
|
29088
|
+
hints.push(
|
|
29089
|
+
"Staged only. On publish these changes land in a new Tag Manager version that is NOT published \u2014 tell the user to publish that version in Tag Manager to make it live."
|
|
29090
|
+
);
|
|
29091
|
+
return hints;
|
|
29092
|
+
}
|
|
29093
|
+
async function stageOp3(op) {
|
|
29094
|
+
const chatId = requireChatId();
|
|
29095
|
+
try {
|
|
29096
|
+
const data = await apiPost("/api/tag-manager/draft/stage", { chatId, op });
|
|
29097
|
+
writeJsonEnvelope({ ok: true, data, hints: stageHints(data) });
|
|
29098
|
+
} catch (err) {
|
|
29099
|
+
handleError3(err);
|
|
29100
|
+
}
|
|
29101
|
+
}
|
|
29102
|
+
async function draftAction2(path27, body) {
|
|
29103
|
+
const chatId = requireChatId();
|
|
29104
|
+
try {
|
|
29105
|
+
const data = await apiPost(path27, { chatId, ...body });
|
|
29106
|
+
writeJsonEnvelope({ ok: true, data });
|
|
29107
|
+
return data;
|
|
29108
|
+
} catch (err) {
|
|
29109
|
+
handleError3(err);
|
|
29110
|
+
}
|
|
29111
|
+
}
|
|
29112
|
+
function renderDraft(response) {
|
|
29113
|
+
if (response.count === 0) {
|
|
29114
|
+
return "No Tag Manager changes staged on this chat.";
|
|
29115
|
+
}
|
|
29116
|
+
const lines = [
|
|
29117
|
+
`${response.count} staged Tag Manager change(s) \u2014 mode: ${response.mode}`,
|
|
29118
|
+
...response.ops.map((op) => {
|
|
29119
|
+
const status = op.result ? ` [${op.result.status}]` : "";
|
|
29120
|
+
return ` ${op.ref} ${op.summary}${status}`;
|
|
29121
|
+
})
|
|
29122
|
+
];
|
|
29123
|
+
if (response.versionId) {
|
|
29124
|
+
lines.push(
|
|
29125
|
+
"",
|
|
29126
|
+
`Applied into Tag Manager version ${response.versionId}. It is NOT published \u2014 publish it in Tag Manager to go live.`
|
|
29127
|
+
);
|
|
29128
|
+
}
|
|
29129
|
+
if (response.compilerError) {
|
|
29130
|
+
lines.push("", `Tag Manager reported a problem building the version: ${response.compilerError}`);
|
|
29131
|
+
}
|
|
29132
|
+
return lines.join("\n");
|
|
29133
|
+
}
|
|
29134
|
+
async function draftList(json) {
|
|
29135
|
+
const chatId = requireChatId();
|
|
29136
|
+
try {
|
|
29137
|
+
const data = await apiPost("/api/tag-manager/draft", { chatId });
|
|
29138
|
+
if (json) {
|
|
29139
|
+
writeJsonEnvelope({ ok: true, data });
|
|
29140
|
+
return;
|
|
29141
|
+
}
|
|
29142
|
+
process.stdout.write(`${renderDraft(data)}
|
|
29143
|
+
`);
|
|
29144
|
+
} catch (err) {
|
|
29145
|
+
handleError3(err);
|
|
29146
|
+
}
|
|
29147
|
+
}
|
|
29148
|
+
|
|
29149
|
+
// src/commands/tag-manager/draft.ts
|
|
29150
|
+
registerSchema({
|
|
29151
|
+
command: "tagManager.draft",
|
|
29152
|
+
description: "Review and undo the Tag Manager changes staged on this chat. Use `list` to see everything staged, `show` to inspect one change in full before publish, `amend` to correct one in place, and `remove`/`clear` to drop them.",
|
|
29153
|
+
args: {
|
|
29154
|
+
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
|
|
29155
|
+
}
|
|
29156
|
+
});
|
|
29157
|
+
var draftCommand3 = defineCommand155({
|
|
29158
|
+
meta: {
|
|
29159
|
+
name: "draft",
|
|
29160
|
+
description: "List, show, amend, remove, or clear staged Tag Manager changes for this chat"
|
|
29161
|
+
},
|
|
29162
|
+
subCommands: {
|
|
29163
|
+
list: defineCommand155({
|
|
29164
|
+
meta: {
|
|
29165
|
+
name: "list",
|
|
29166
|
+
description: "Review everything staged on this chat (--json for the raw envelope)"
|
|
29167
|
+
},
|
|
29168
|
+
args: { json: { type: "boolean", description: "Print the raw JSON envelope", required: false } },
|
|
29169
|
+
run: async ({ args }) => {
|
|
29170
|
+
await draftList(args.json === true);
|
|
29171
|
+
}
|
|
29172
|
+
}),
|
|
29173
|
+
show: defineCommand155({
|
|
29174
|
+
meta: {
|
|
29175
|
+
name: "show",
|
|
29176
|
+
description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
|
|
29177
|
+
},
|
|
29178
|
+
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
29179
|
+
run: async ({ args }) => {
|
|
29180
|
+
await draftAction2("/api/tag-manager/draft/show", {
|
|
29181
|
+
ref: requireTarget4(args, "change")
|
|
29182
|
+
});
|
|
29183
|
+
}
|
|
29184
|
+
}),
|
|
29185
|
+
amend: defineCommand155({
|
|
29186
|
+
meta: {
|
|
29187
|
+
name: "amend",
|
|
29188
|
+
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."
|
|
29189
|
+
},
|
|
29190
|
+
args: {
|
|
29191
|
+
ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false },
|
|
29192
|
+
patch: { type: "string", description: "Inline JSON patch object", required: false },
|
|
29193
|
+
file: { type: "string", description: "JSON file with the patch object", required: false }
|
|
29194
|
+
},
|
|
29195
|
+
run: async ({ args }) => {
|
|
29196
|
+
await draftAction2("/api/tag-manager/draft/amend", {
|
|
29197
|
+
ref: requireTarget4(args, "change"),
|
|
29198
|
+
patch: loadJsonArg(args, "patch")
|
|
29199
|
+
});
|
|
29200
|
+
}
|
|
29201
|
+
}),
|
|
29202
|
+
remove: defineCommand155({
|
|
29203
|
+
meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
|
|
29204
|
+
args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
|
|
29205
|
+
run: async ({ args }) => {
|
|
29206
|
+
await draftAction2("/api/tag-manager/draft/remove", {
|
|
29207
|
+
ref: requireTarget4(args, "change")
|
|
29208
|
+
});
|
|
29209
|
+
}
|
|
29210
|
+
}),
|
|
29211
|
+
clear: defineCommand155({
|
|
29212
|
+
meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
|
|
29213
|
+
run: async () => {
|
|
29214
|
+
await draftAction2("/api/tag-manager/draft/clear", {});
|
|
29215
|
+
}
|
|
29216
|
+
})
|
|
29217
|
+
}
|
|
29218
|
+
});
|
|
29219
|
+
|
|
29220
|
+
// src/commands/tag-manager/read.ts
|
|
29221
|
+
import { defineCommand as defineCommand156 } from "citty";
|
|
29222
|
+
registerSchema({
|
|
29223
|
+
command: "tagManager.containers",
|
|
29224
|
+
description: "List the Google Tag Manager containers this company's connection can reach. The connected container is flagged. Start here to confirm which container you are managing.",
|
|
29225
|
+
args: {}
|
|
29226
|
+
});
|
|
29227
|
+
registerSchema({
|
|
29228
|
+
command: "tagManager.read",
|
|
29229
|
+
description: "Read what is currently inside a Tag Manager container: tags, triggers, variables, folders and enabled built-in variables. Start here before proposing any change, so you edit what exists instead of duplicating it. Compact by default; pass --full for raw Tag Manager objects.",
|
|
29230
|
+
args: {
|
|
29231
|
+
container: { type: "string", description: "Numeric container id (defaults to the connected one)", required: false },
|
|
29232
|
+
workspace: { type: "string", description: "Workspace id (defaults to the default workspace)", required: false },
|
|
29233
|
+
entities: {
|
|
29234
|
+
type: "string",
|
|
29235
|
+
description: "Comma-separated subset: tag,trigger,variable,folder,builtInVariable",
|
|
29236
|
+
required: false
|
|
29237
|
+
},
|
|
29238
|
+
full: { type: "boolean", description: "Include the raw Tag Manager object for each entity", required: false }
|
|
29239
|
+
}
|
|
29240
|
+
});
|
|
29241
|
+
function fail6(err) {
|
|
29242
|
+
if (err instanceof ApiError) {
|
|
29243
|
+
const notConnected = err.code === "NOT_FOUND" || err.code === "UNAUTHORIZED";
|
|
29244
|
+
writeJsonEnvelope({
|
|
29245
|
+
ok: false,
|
|
29246
|
+
error: {
|
|
29247
|
+
code: err.code,
|
|
29248
|
+
message: err.message,
|
|
29249
|
+
...notConnected ? {
|
|
29250
|
+
fix: {
|
|
29251
|
+
action: "ask_user",
|
|
29252
|
+
explanation: "Tag Manager is not connected for this company yet. Ask the user to connect Tag Manager in Settings \u2192 Connections and choose the container to manage, then retry. Continue with the rest of the task in the meantime."
|
|
29253
|
+
}
|
|
29254
|
+
} : {},
|
|
29255
|
+
retryable: false
|
|
29256
|
+
}
|
|
29257
|
+
});
|
|
29258
|
+
process.exit(1);
|
|
29259
|
+
}
|
|
29260
|
+
writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
29261
|
+
process.exit(1);
|
|
29262
|
+
}
|
|
29263
|
+
var containersCommand = defineCommand156({
|
|
29264
|
+
meta: {
|
|
29265
|
+
name: "containers",
|
|
29266
|
+
description: `List Tag Manager containers reachable by this company's connection.
|
|
29267
|
+
|
|
29268
|
+
Start here:
|
|
29269
|
+
baker tag-manager containers`
|
|
29270
|
+
},
|
|
29271
|
+
run: async () => {
|
|
29272
|
+
try {
|
|
29273
|
+
const data = await apiGet("/api/tag-manager/containers");
|
|
29274
|
+
writeJsonEnvelope({ ok: true, data });
|
|
29275
|
+
} catch (err) {
|
|
29276
|
+
fail6(err);
|
|
29277
|
+
}
|
|
29278
|
+
}
|
|
29279
|
+
});
|
|
29280
|
+
var readCommand = defineCommand156({
|
|
29281
|
+
meta: {
|
|
29282
|
+
name: "read",
|
|
29283
|
+
description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
|
|
29284
|
+
|
|
29285
|
+
Examples:
|
|
29286
|
+
baker tag-manager read
|
|
29287
|
+
baker tag-manager read --entities tag,trigger
|
|
29288
|
+
baker tag-manager read --full`
|
|
29289
|
+
},
|
|
29290
|
+
args: {
|
|
29291
|
+
container: { type: "string", description: "Numeric container id", required: false },
|
|
29292
|
+
workspace: { type: "string", description: "Workspace id", required: false },
|
|
29293
|
+
entities: { type: "string", description: "Comma-separated entity subset", required: false },
|
|
29294
|
+
full: { type: "boolean", description: "Include raw Tag Manager objects", required: false }
|
|
29295
|
+
},
|
|
29296
|
+
run: async ({ args }) => {
|
|
29297
|
+
const entities = typeof args.entities === "string" && args.entities.length > 0 ? args.entities.split(",").map((entry) => entry.trim()) : void 0;
|
|
29298
|
+
try {
|
|
29299
|
+
const data = await apiPost("/api/tag-manager/read", {
|
|
29300
|
+
containerId: args.container,
|
|
29301
|
+
workspaceId: args.workspace,
|
|
29302
|
+
entities,
|
|
29303
|
+
full: args.full === true
|
|
29304
|
+
});
|
|
29305
|
+
const hints = [];
|
|
29306
|
+
if (data.installedContainerMismatch) {
|
|
29307
|
+
hints.push(data.installedContainerMismatch);
|
|
29308
|
+
}
|
|
29309
|
+
hints.push(
|
|
29310
|
+
"Reference an existing trigger or variable by its numeric id or {{Name}}. To reference something you are staging in this same chat, use its gtm_temp_* ref and the executor resolves it at publish."
|
|
29311
|
+
);
|
|
29312
|
+
writeJsonEnvelope({ ok: true, data, hints });
|
|
29313
|
+
} catch (err) {
|
|
29314
|
+
fail6(err);
|
|
29315
|
+
}
|
|
29316
|
+
}
|
|
29317
|
+
});
|
|
29318
|
+
|
|
29319
|
+
// src/commands/tag-manager/write-commands.ts
|
|
29320
|
+
import { defineCommand as defineCommand157 } from "citty";
|
|
29321
|
+
var ENTITIES = [
|
|
29322
|
+
{
|
|
29323
|
+
entity: "tag",
|
|
29324
|
+
noun: "tag",
|
|
29325
|
+
createHint: 'Payload needs name + type (e.g. "gaawe" for a GA4 event) and usually parameter[] and firingTriggerId[]. Reference a trigger by its numeric id, or by a gtm_temp_* ref if you are staging it in this same chat.'
|
|
29326
|
+
},
|
|
29327
|
+
{
|
|
29328
|
+
entity: "trigger",
|
|
29329
|
+
noun: "trigger",
|
|
29330
|
+
createHint: 'Payload needs name + type (e.g. "pageview", "click", "customEvent"). Stage the trigger BEFORE the tag that fires on it, then reference it by its gtm_temp_* ref.'
|
|
29331
|
+
},
|
|
29332
|
+
{
|
|
29333
|
+
entity: "variable",
|
|
29334
|
+
noun: "variable",
|
|
29335
|
+
createHint: 'Payload needs name + type (e.g. "v" for a data layer variable, "c" for a constant). Other entities reference a variable by NAME as {{Variable Name}}.'
|
|
29336
|
+
},
|
|
29337
|
+
{
|
|
29338
|
+
entity: "folder",
|
|
29339
|
+
noun: "folder",
|
|
29340
|
+
createHint: "Payload needs name. Use folders to keep a large container legible."
|
|
29341
|
+
}
|
|
29342
|
+
];
|
|
29343
|
+
for (const { entity, noun, createHint } of ENTITIES) {
|
|
29344
|
+
registerSchema({
|
|
29345
|
+
command: `tagManager.${entity}.create`,
|
|
29346
|
+
description: `Stage the creation of a Tag Manager ${noun}. ${createHint} Staged only \u2014 applies on publish into an unpublished container version.`,
|
|
29347
|
+
args: {
|
|
29348
|
+
json: { type: "string", description: `Inline JSON ${noun} definition`, required: false },
|
|
29349
|
+
file: { type: "string", description: `Path to a JSON file with the ${noun} definition`, required: false },
|
|
29350
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29351
|
+
}
|
|
29352
|
+
});
|
|
29353
|
+
registerSchema({
|
|
29354
|
+
command: `tagManager.${entity}.update`,
|
|
29355
|
+
description: `Stage an update to an existing Tag Manager ${noun}. Pass the ${noun} id or path as the positional argument and the changed fields as JSON. Read the container first so you send the fields you mean to change.`,
|
|
29356
|
+
args: {
|
|
29357
|
+
json: { type: "string", description: "Inline JSON with the changed fields", required: false },
|
|
29358
|
+
file: { type: "string", description: "Path to a JSON file with the changed fields", required: false }
|
|
29359
|
+
}
|
|
29360
|
+
});
|
|
29361
|
+
registerSchema({
|
|
29362
|
+
command: `tagManager.${entity}.delete`,
|
|
29363
|
+
description: `Stage the deletion of a Tag Manager ${noun}. Pass its id or path as the positional argument. Deleting is irreversible once the resulting version is published \u2014 confirm with the user first.`,
|
|
29364
|
+
args: {}
|
|
29365
|
+
});
|
|
29366
|
+
}
|
|
29367
|
+
function entityCommand(entity, noun) {
|
|
29368
|
+
return defineCommand157({
|
|
29369
|
+
meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
|
|
29370
|
+
subCommands: {
|
|
29371
|
+
create: defineCommand157({
|
|
29372
|
+
meta: {
|
|
29373
|
+
name: "create",
|
|
29374
|
+
description: `Stage a new ${noun}
|
|
29375
|
+
|
|
29376
|
+
Examples:
|
|
29377
|
+
baker tag-manager ${entity} create --json '{"name":"GA4 Config","type":"googtag"}'
|
|
29378
|
+
baker tag-manager ${entity} create --file ./${entity}.json`
|
|
29379
|
+
},
|
|
29380
|
+
args: {
|
|
29381
|
+
json: { type: "string", description: "Inline JSON definition", required: false },
|
|
29382
|
+
file: { type: "string", description: "Path to a JSON file", required: false },
|
|
29383
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29384
|
+
},
|
|
29385
|
+
run: async ({ args }) => {
|
|
29386
|
+
await stageOp3({
|
|
29387
|
+
kind: `tagManager.${entity}.create`,
|
|
29388
|
+
payload: loadJsonArg(args),
|
|
29389
|
+
...typeof args.container === "string" ? { containerId: args.container } : {}
|
|
29390
|
+
});
|
|
29391
|
+
}
|
|
29392
|
+
}),
|
|
29393
|
+
update: defineCommand157({
|
|
29394
|
+
meta: {
|
|
29395
|
+
name: "update",
|
|
29396
|
+
description: `Stage an update to an existing ${noun} (pass its id or path)`
|
|
29397
|
+
},
|
|
29398
|
+
args: {
|
|
29399
|
+
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
29400
|
+
json: { type: "string", description: "Inline JSON with changed fields", required: false },
|
|
29401
|
+
file: { type: "string", description: "Path to a JSON file", required: false },
|
|
29402
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29403
|
+
},
|
|
29404
|
+
run: async ({ args }) => {
|
|
29405
|
+
await stageOp3({
|
|
29406
|
+
kind: `tagManager.${entity}.update`,
|
|
29407
|
+
target: requireTarget4(args, noun),
|
|
29408
|
+
payload: loadJsonArg(args),
|
|
29409
|
+
...typeof args.container === "string" ? { containerId: args.container } : {}
|
|
29410
|
+
});
|
|
29411
|
+
}
|
|
29412
|
+
}),
|
|
29413
|
+
delete: defineCommand157({
|
|
29414
|
+
meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
|
|
29415
|
+
args: {
|
|
29416
|
+
id: { type: "positional", description: `${noun} id or path`, required: false },
|
|
29417
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29418
|
+
},
|
|
29419
|
+
run: async ({ args }) => {
|
|
29420
|
+
await stageOp3({
|
|
29421
|
+
kind: `tagManager.${entity}.delete`,
|
|
29422
|
+
target: requireTarget4(args, noun),
|
|
29423
|
+
...typeof args.container === "string" ? { containerId: args.container } : {}
|
|
29424
|
+
});
|
|
29425
|
+
}
|
|
29426
|
+
})
|
|
29427
|
+
}
|
|
29428
|
+
});
|
|
29429
|
+
}
|
|
29430
|
+
var tagCommand = entityCommand("tag", "tag");
|
|
29431
|
+
var triggerCommand2 = entityCommand("trigger", "trigger");
|
|
29432
|
+
var variableCommand = entityCommand("variable", "variable");
|
|
29433
|
+
var folderCommand = entityCommand("folder", "folder");
|
|
29434
|
+
registerSchema({
|
|
29435
|
+
command: "tagManager.builtin",
|
|
29436
|
+
description: "Enable or disable Tag Manager built-in variables by type (e.g. clickUrl, pageUrl, formId). Built-in variables must be enabled before a trigger or tag can reference them as {{Click URL}}.",
|
|
29437
|
+
args: {
|
|
29438
|
+
types: { type: "string", description: "Comma-separated built-in variable types", required: true }
|
|
29439
|
+
}
|
|
29440
|
+
});
|
|
29441
|
+
function builtinTypes(args) {
|
|
29442
|
+
const raw = args.types;
|
|
29443
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
29444
|
+
process.stdout.write(
|
|
29445
|
+
`${JSON.stringify({ ok: false, error: { code: "VALIDATION_ERROR", message: "pass --types with comma-separated built-in variable types" } }, null, 2)}
|
|
29446
|
+
`
|
|
29447
|
+
);
|
|
29448
|
+
process.exit(1);
|
|
29449
|
+
}
|
|
29450
|
+
return raw.split(",").map((entry) => entry.trim());
|
|
29451
|
+
}
|
|
29452
|
+
var builtinCommand = defineCommand157({
|
|
29453
|
+
meta: {
|
|
29454
|
+
name: "builtin",
|
|
29455
|
+
description: `Enable or disable built-in variables
|
|
29456
|
+
|
|
29457
|
+
Examples:
|
|
29458
|
+
baker tag-manager builtin enable --types clickUrl,clickText
|
|
29459
|
+
baker tag-manager builtin disable --types formId`
|
|
29460
|
+
},
|
|
29461
|
+
subCommands: {
|
|
29462
|
+
enable: defineCommand157({
|
|
29463
|
+
meta: { name: "enable", description: "Stage enabling built-in variables" },
|
|
29464
|
+
args: {
|
|
29465
|
+
types: { type: "string", description: "Comma-separated types", required: false },
|
|
29466
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29467
|
+
},
|
|
29468
|
+
run: async ({ args }) => {
|
|
29469
|
+
await stageOp3({
|
|
29470
|
+
kind: "tagManager.builtInVariable.enable",
|
|
29471
|
+
payload: { type: builtinTypes(args) },
|
|
29472
|
+
...typeof args.container === "string" ? { containerId: args.container } : {}
|
|
29473
|
+
});
|
|
29474
|
+
}
|
|
29475
|
+
}),
|
|
29476
|
+
disable: defineCommand157({
|
|
29477
|
+
meta: { name: "disable", description: "Stage disabling built-in variables" },
|
|
29478
|
+
args: {
|
|
29479
|
+
types: { type: "string", description: "Comma-separated types", required: false },
|
|
29480
|
+
container: { type: "string", description: "Numeric container id", required: false }
|
|
29481
|
+
},
|
|
29482
|
+
run: async ({ args }) => {
|
|
29483
|
+
await stageOp3({
|
|
29484
|
+
kind: "tagManager.builtInVariable.disable",
|
|
29485
|
+
payload: { type: builtinTypes(args) },
|
|
29486
|
+
...typeof args.container === "string" ? { containerId: args.container } : {}
|
|
29487
|
+
});
|
|
29488
|
+
}
|
|
29489
|
+
})
|
|
29490
|
+
}
|
|
29491
|
+
});
|
|
29492
|
+
|
|
29493
|
+
// src/commands/tag-manager/index.ts
|
|
29494
|
+
var tagManagerCommand = defineCommand158({
|
|
29495
|
+
meta: {
|
|
29496
|
+
name: "tag-manager",
|
|
29497
|
+
description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
|
|
29498
|
+
|
|
29499
|
+
Start here:
|
|
29500
|
+
baker tag-manager read \u2014 see what the container holds today
|
|
29501
|
+
|
|
29502
|
+
Then stage changes (nothing is sent to Tag Manager until publish):
|
|
29503
|
+
baker tag-manager trigger create --json '{"name":"Quote Submit","type":"customEvent"}'
|
|
29504
|
+
baker tag-manager tag create --json '{"name":"GA4 Quote","type":"gaawe","firingTriggerId":["gtm_temp_trigger_..."]}'
|
|
29505
|
+
baker tag-manager draft list \u2014 review everything staged
|
|
29506
|
+
|
|
29507
|
+
On publish, staged changes are written into a new Tag Manager version that is NOT published.
|
|
29508
|
+
Tell the user to publish that version in Tag Manager to make it live.
|
|
29509
|
+
|
|
29510
|
+
This owns the CONTENTS of the container. Installing the container snippet on the site is a
|
|
29511
|
+
different job \u2014 that is \`baker tags\` with the googleTagManager tag.
|
|
29512
|
+
|
|
29513
|
+
Full guide: __tooling__/docs/tools/baker/tag-manager.md`
|
|
29514
|
+
},
|
|
29515
|
+
subCommands: {
|
|
29516
|
+
containers: containersCommand,
|
|
29517
|
+
read: readCommand,
|
|
29518
|
+
tag: tagCommand,
|
|
29519
|
+
trigger: triggerCommand2,
|
|
29520
|
+
variable: variableCommand,
|
|
29521
|
+
folder: folderCommand,
|
|
29522
|
+
builtin: builtinCommand,
|
|
29523
|
+
draft: draftCommand3
|
|
29524
|
+
}
|
|
29525
|
+
});
|
|
29526
|
+
|
|
29527
|
+
// src/commands/tags/index.ts
|
|
29528
|
+
import { defineCommand as defineCommand159 } from "citty";
|
|
29529
|
+
|
|
28937
29530
|
// src/commands/tags/shared.ts
|
|
28938
29531
|
function failApi3(err) {
|
|
28939
29532
|
if (err instanceof ApiError) {
|
|
@@ -28998,7 +29591,7 @@ async function listTags(json) {
|
|
|
28998
29591
|
failApi3(err);
|
|
28999
29592
|
}
|
|
29000
29593
|
}
|
|
29001
|
-
var listCommand10 =
|
|
29594
|
+
var listCommand10 = defineCommand159({
|
|
29002
29595
|
meta: {
|
|
29003
29596
|
name: "list",
|
|
29004
29597
|
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"
|
|
@@ -29017,7 +29610,7 @@ async function listDraft3() {
|
|
|
29017
29610
|
failApi3(err);
|
|
29018
29611
|
}
|
|
29019
29612
|
}
|
|
29020
|
-
var
|
|
29613
|
+
var draftCommand4 = defineCommand159({
|
|
29021
29614
|
meta: {
|
|
29022
29615
|
name: "draft",
|
|
29023
29616
|
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)."
|
|
@@ -29026,7 +29619,7 @@ var draftCommand3 = defineCommand155({
|
|
|
29026
29619
|
await listDraft3();
|
|
29027
29620
|
}
|
|
29028
29621
|
});
|
|
29029
|
-
var tagsCommand3 =
|
|
29622
|
+
var tagsCommand3 = defineCommand159({
|
|
29030
29623
|
meta: {
|
|
29031
29624
|
name: "tags",
|
|
29032
29625
|
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.
|
|
@@ -29044,7 +29637,7 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
29044
29637
|
},
|
|
29045
29638
|
subCommands: {
|
|
29046
29639
|
list: listCommand10,
|
|
29047
|
-
draft:
|
|
29640
|
+
draft: draftCommand4
|
|
29048
29641
|
},
|
|
29049
29642
|
run: async () => {
|
|
29050
29643
|
await listTags(false);
|
|
@@ -29052,10 +29645,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
|
29052
29645
|
});
|
|
29053
29646
|
|
|
29054
29647
|
// src/commands/testimonials/index.ts
|
|
29055
|
-
import { defineCommand as
|
|
29648
|
+
import { defineCommand as defineCommand163 } from "citty";
|
|
29056
29649
|
|
|
29057
29650
|
// src/commands/testimonials/get.ts
|
|
29058
|
-
import { defineCommand as
|
|
29651
|
+
import { defineCommand as defineCommand160 } from "citty";
|
|
29059
29652
|
registerSchema({
|
|
29060
29653
|
command: "testimonials.get",
|
|
29061
29654
|
description: "Get a single testimonial by ID",
|
|
@@ -29063,7 +29656,7 @@ registerSchema({
|
|
|
29063
29656
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
29064
29657
|
}
|
|
29065
29658
|
});
|
|
29066
|
-
var getCommand4 =
|
|
29659
|
+
var getCommand4 = defineCommand160({
|
|
29067
29660
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
29068
29661
|
args: {
|
|
29069
29662
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -29100,7 +29693,7 @@ var getCommand4 = defineCommand156({
|
|
|
29100
29693
|
});
|
|
29101
29694
|
|
|
29102
29695
|
// src/commands/testimonials/list.ts
|
|
29103
|
-
import { defineCommand as
|
|
29696
|
+
import { defineCommand as defineCommand161 } from "citty";
|
|
29104
29697
|
registerSchema({
|
|
29105
29698
|
command: "testimonials.list",
|
|
29106
29699
|
description: "List testimonials with optional filters.",
|
|
@@ -29130,7 +29723,7 @@ registerSchema({
|
|
|
29130
29723
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
29131
29724
|
}
|
|
29132
29725
|
});
|
|
29133
|
-
var listCommand11 =
|
|
29726
|
+
var listCommand11 = defineCommand161({
|
|
29134
29727
|
meta: {
|
|
29135
29728
|
name: "list",
|
|
29136
29729
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -29179,7 +29772,7 @@ var listCommand11 = defineCommand157({
|
|
|
29179
29772
|
});
|
|
29180
29773
|
|
|
29181
29774
|
// src/commands/testimonials/search.ts
|
|
29182
|
-
import { defineCommand as
|
|
29775
|
+
import { defineCommand as defineCommand162 } from "citty";
|
|
29183
29776
|
function languageBiasHint(results, requestedLanguage) {
|
|
29184
29777
|
if (requestedLanguage) {
|
|
29185
29778
|
return null;
|
|
@@ -29257,7 +29850,7 @@ function buildSearchRequest(query, args) {
|
|
|
29257
29850
|
}
|
|
29258
29851
|
return body;
|
|
29259
29852
|
}
|
|
29260
|
-
var searchCommand2 =
|
|
29853
|
+
var searchCommand2 = defineCommand162({
|
|
29261
29854
|
meta: {
|
|
29262
29855
|
name: "search",
|
|
29263
29856
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -29313,7 +29906,7 @@ var searchCommand2 = defineCommand158({
|
|
|
29313
29906
|
var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
29314
29907
|
|
|
29315
29908
|
// src/commands/testimonials/index.ts
|
|
29316
|
-
var testimonialsCommand =
|
|
29909
|
+
var testimonialsCommand = defineCommand163({
|
|
29317
29910
|
meta: {
|
|
29318
29911
|
name: "testimonials",
|
|
29319
29912
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -29335,10 +29928,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
|
29335
29928
|
});
|
|
29336
29929
|
|
|
29337
29930
|
// src/commands/videos/index.ts
|
|
29338
|
-
import { defineCommand as
|
|
29931
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
29339
29932
|
|
|
29340
29933
|
// src/commands/videos/delete.ts
|
|
29341
|
-
import { defineCommand as
|
|
29934
|
+
import { defineCommand as defineCommand164 } from "citty";
|
|
29342
29935
|
registerSchema({
|
|
29343
29936
|
command: "videos.delete",
|
|
29344
29937
|
description: "Delete a video by ID",
|
|
@@ -29352,7 +29945,7 @@ registerSchema({
|
|
|
29352
29945
|
}
|
|
29353
29946
|
}
|
|
29354
29947
|
});
|
|
29355
|
-
var deleteCommand3 =
|
|
29948
|
+
var deleteCommand3 = defineCommand164({
|
|
29356
29949
|
meta: {
|
|
29357
29950
|
name: "delete",
|
|
29358
29951
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -29393,7 +29986,7 @@ var deleteCommand3 = defineCommand160({
|
|
|
29393
29986
|
});
|
|
29394
29987
|
|
|
29395
29988
|
// src/commands/videos/get.ts
|
|
29396
|
-
import { defineCommand as
|
|
29989
|
+
import { defineCommand as defineCommand165 } from "citty";
|
|
29397
29990
|
registerSchema({
|
|
29398
29991
|
command: "videos.get",
|
|
29399
29992
|
description: "Get a single video by ID",
|
|
@@ -29401,7 +29994,7 @@ registerSchema({
|
|
|
29401
29994
|
id: { type: "string", description: "Video ID", required: true }
|
|
29402
29995
|
}
|
|
29403
29996
|
});
|
|
29404
|
-
var getCommand5 =
|
|
29997
|
+
var getCommand5 = defineCommand165({
|
|
29405
29998
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
29406
29999
|
args: {
|
|
29407
30000
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -29438,7 +30031,7 @@ var getCommand5 = defineCommand161({
|
|
|
29438
30031
|
});
|
|
29439
30032
|
|
|
29440
30033
|
// src/commands/videos/search.ts
|
|
29441
|
-
import { defineCommand as
|
|
30034
|
+
import { defineCommand as defineCommand166 } from "citty";
|
|
29442
30035
|
registerSchema({
|
|
29443
30036
|
command: "videos.search",
|
|
29444
30037
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -29448,7 +30041,7 @@ registerSchema({
|
|
|
29448
30041
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
29449
30042
|
}
|
|
29450
30043
|
});
|
|
29451
|
-
var searchCommand3 =
|
|
30044
|
+
var searchCommand3 = defineCommand166({
|
|
29452
30045
|
meta: {
|
|
29453
30046
|
name: "search",
|
|
29454
30047
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -29500,7 +30093,7 @@ var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
|
29500
30093
|
// src/commands/videos/upload.ts
|
|
29501
30094
|
import { readFile as readFile22, stat as stat7 } from "fs/promises";
|
|
29502
30095
|
import { extname as extname3 } from "path";
|
|
29503
|
-
import { defineCommand as
|
|
30096
|
+
import { defineCommand as defineCommand167 } from "citty";
|
|
29504
30097
|
var MIME_MAP = {
|
|
29505
30098
|
".mp4": "video/mp4",
|
|
29506
30099
|
".mov": "video/quicktime",
|
|
@@ -29534,7 +30127,7 @@ function detectContentType(filePath) {
|
|
|
29534
30127
|
}
|
|
29535
30128
|
return mime;
|
|
29536
30129
|
}
|
|
29537
|
-
var uploadCommand2 =
|
|
30130
|
+
var uploadCommand2 = defineCommand167({
|
|
29538
30131
|
meta: {
|
|
29539
30132
|
name: "upload",
|
|
29540
30133
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -29588,7 +30181,7 @@ var uploadCommand2 = defineCommand163({
|
|
|
29588
30181
|
});
|
|
29589
30182
|
|
|
29590
30183
|
// src/commands/videos/index.ts
|
|
29591
|
-
var videosCommand =
|
|
30184
|
+
var videosCommand = defineCommand168({
|
|
29592
30185
|
meta: {
|
|
29593
30186
|
name: "videos",
|
|
29594
30187
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -29612,10 +30205,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
29612
30205
|
});
|
|
29613
30206
|
|
|
29614
30207
|
// src/commands/winning-ads/index.ts
|
|
29615
|
-
import { defineCommand as
|
|
30208
|
+
import { defineCommand as defineCommand181 } from "citty";
|
|
29616
30209
|
|
|
29617
30210
|
// src/commands/winning-ads/advertisers.ts
|
|
29618
|
-
import { defineCommand as
|
|
30211
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
29619
30212
|
|
|
29620
30213
|
// src/commands/winning-ads/shared.ts
|
|
29621
30214
|
function splitList(value) {
|
|
@@ -29668,7 +30261,7 @@ function advertiserNormalizer(record, full) {
|
|
|
29668
30261
|
last_synced_at: record.last_synced_at ?? null
|
|
29669
30262
|
};
|
|
29670
30263
|
}
|
|
29671
|
-
var advertisersCommand2 =
|
|
30264
|
+
var advertisersCommand2 = defineCommand169({
|
|
29672
30265
|
meta: {
|
|
29673
30266
|
name: "advertisers",
|
|
29674
30267
|
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'
|
|
@@ -29726,7 +30319,7 @@ var advertisersCommand2 = defineCommand165({
|
|
|
29726
30319
|
});
|
|
29727
30320
|
|
|
29728
30321
|
// src/commands/winning-ads/brief.ts
|
|
29729
|
-
import { defineCommand as
|
|
30322
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
29730
30323
|
registerSchema({
|
|
29731
30324
|
command: "winning-ads.brief",
|
|
29732
30325
|
description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
|
|
@@ -29772,7 +30365,7 @@ function parseDna(raw) {
|
|
|
29772
30365
|
}
|
|
29773
30366
|
return parsed;
|
|
29774
30367
|
}
|
|
29775
|
-
var briefCommand =
|
|
30368
|
+
var briefCommand = defineCommand170({
|
|
29776
30369
|
meta: {
|
|
29777
30370
|
name: "brief",
|
|
29778
30371
|
description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
|
|
@@ -29808,7 +30401,7 @@ var briefCommand = defineCommand166({
|
|
|
29808
30401
|
});
|
|
29809
30402
|
|
|
29810
30403
|
// src/commands/winning-ads/content.ts
|
|
29811
|
-
import { defineCommand as
|
|
30404
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
29812
30405
|
registerSchema({
|
|
29813
30406
|
command: "winning-ads.content",
|
|
29814
30407
|
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.",
|
|
@@ -29821,7 +30414,7 @@ registerSchema({
|
|
|
29821
30414
|
}
|
|
29822
30415
|
}
|
|
29823
30416
|
});
|
|
29824
|
-
var contentCommand =
|
|
30417
|
+
var contentCommand = defineCommand171({
|
|
29825
30418
|
meta: {
|
|
29826
30419
|
name: "content",
|
|
29827
30420
|
description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
@@ -29870,7 +30463,7 @@ var contentCommand = defineCommand167({
|
|
|
29870
30463
|
});
|
|
29871
30464
|
|
|
29872
30465
|
// src/commands/winning-ads/feed.ts
|
|
29873
|
-
import { defineCommand as
|
|
30466
|
+
import { defineCommand as defineCommand172 } from "citty";
|
|
29874
30467
|
function buildFeedParams(input) {
|
|
29875
30468
|
const params = {};
|
|
29876
30469
|
const advertiser = splitList(input.advertiser);
|
|
@@ -29922,7 +30515,7 @@ registerSchema({
|
|
|
29922
30515
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
29923
30516
|
}
|
|
29924
30517
|
});
|
|
29925
|
-
var feedCommand =
|
|
30518
|
+
var feedCommand = defineCommand172({
|
|
29926
30519
|
meta: {
|
|
29927
30520
|
name: "feed",
|
|
29928
30521
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -30007,7 +30600,7 @@ var feedCommand = defineCommand168({
|
|
|
30007
30600
|
});
|
|
30008
30601
|
|
|
30009
30602
|
// src/commands/winning-ads/follow.ts
|
|
30010
|
-
import { defineCommand as
|
|
30603
|
+
import { defineCommand as defineCommand173 } from "citty";
|
|
30011
30604
|
var PLATFORMS = ["meta", "linkedin"];
|
|
30012
30605
|
registerSchema({
|
|
30013
30606
|
command: "winning-ads.follow",
|
|
@@ -30022,7 +30615,7 @@ registerSchema({
|
|
|
30022
30615
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
30023
30616
|
}
|
|
30024
30617
|
});
|
|
30025
|
-
var followCommand =
|
|
30618
|
+
var followCommand = defineCommand173({
|
|
30026
30619
|
meta: {
|
|
30027
30620
|
name: "follow",
|
|
30028
30621
|
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 both Meta + LinkedIn. Example: baker winning-ads follow "deel.com" --platform meta'
|
|
@@ -30069,7 +30662,7 @@ var followCommand = defineCommand169({
|
|
|
30069
30662
|
});
|
|
30070
30663
|
|
|
30071
30664
|
// src/commands/winning-ads/follow-competitors.ts
|
|
30072
|
-
import { defineCommand as
|
|
30665
|
+
import { defineCommand as defineCommand174 } from "citty";
|
|
30073
30666
|
var PLATFORMS2 = ["meta", "linkedin"];
|
|
30074
30667
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
30075
30668
|
function buildFollowBatchBody(input) {
|
|
@@ -30102,7 +30695,7 @@ registerSchema({
|
|
|
30102
30695
|
}
|
|
30103
30696
|
}
|
|
30104
30697
|
});
|
|
30105
|
-
var followCompetitorsCommand =
|
|
30698
|
+
var followCompetitorsCommand = defineCommand174({
|
|
30106
30699
|
meta: {
|
|
30107
30700
|
name: "follow-competitors",
|
|
30108
30701
|
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"'
|
|
@@ -30177,7 +30770,7 @@ var followCompetitorsCommand = defineCommand170({
|
|
|
30177
30770
|
});
|
|
30178
30771
|
|
|
30179
30772
|
// src/commands/winning-ads/following.ts
|
|
30180
|
-
import { defineCommand as
|
|
30773
|
+
import { defineCommand as defineCommand175 } from "citty";
|
|
30181
30774
|
registerSchema({
|
|
30182
30775
|
command: "winning-ads.following",
|
|
30183
30776
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
|
|
@@ -30210,7 +30803,7 @@ function followingNormalizer(record, full) {
|
|
|
30210
30803
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
30211
30804
|
};
|
|
30212
30805
|
}
|
|
30213
|
-
var followingCommand =
|
|
30806
|
+
var followingCommand = defineCommand175({
|
|
30214
30807
|
meta: {
|
|
30215
30808
|
name: "following",
|
|
30216
30809
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -30245,7 +30838,7 @@ var followingCommand = defineCommand171({
|
|
|
30245
30838
|
});
|
|
30246
30839
|
|
|
30247
30840
|
// src/commands/winning-ads/patterns.ts
|
|
30248
|
-
import { defineCommand as
|
|
30841
|
+
import { defineCommand as defineCommand176 } from "citty";
|
|
30249
30842
|
registerSchema({
|
|
30250
30843
|
command: "winning-ads.patterns",
|
|
30251
30844
|
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.",
|
|
@@ -30284,7 +30877,7 @@ function discriminatorRow(record) {
|
|
|
30284
30877
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
30285
30878
|
};
|
|
30286
30879
|
}
|
|
30287
|
-
var patternsCommand =
|
|
30880
|
+
var patternsCommand = defineCommand176({
|
|
30288
30881
|
meta: {
|
|
30289
30882
|
name: "patterns",
|
|
30290
30883
|
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"
|
|
@@ -30340,7 +30933,7 @@ var patternsCommand = defineCommand172({
|
|
|
30340
30933
|
});
|
|
30341
30934
|
|
|
30342
30935
|
// src/commands/winning-ads/search.ts
|
|
30343
|
-
import { defineCommand as
|
|
30936
|
+
import { defineCommand as defineCommand177 } from "citty";
|
|
30344
30937
|
registerSchema({
|
|
30345
30938
|
command: "winning-ads.search",
|
|
30346
30939
|
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.",
|
|
@@ -30448,7 +31041,7 @@ function buildSearchBody(args) {
|
|
|
30448
31041
|
}
|
|
30449
31042
|
return body;
|
|
30450
31043
|
}
|
|
30451
|
-
var searchCommand4 =
|
|
31044
|
+
var searchCommand4 = defineCommand177({
|
|
30452
31045
|
meta: {
|
|
30453
31046
|
name: "search",
|
|
30454
31047
|
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"
|
|
@@ -30563,7 +31156,7 @@ var searchCommand4 = defineCommand173({
|
|
|
30563
31156
|
});
|
|
30564
31157
|
|
|
30565
31158
|
// src/commands/winning-ads/seeds.ts
|
|
30566
|
-
import { defineCommand as
|
|
31159
|
+
import { defineCommand as defineCommand178 } from "citty";
|
|
30567
31160
|
function leanRow(r) {
|
|
30568
31161
|
return {
|
|
30569
31162
|
key: r.key,
|
|
@@ -30591,7 +31184,7 @@ function makeSeedCommand(opts) {
|
|
|
30591
31184
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
30592
31185
|
}
|
|
30593
31186
|
});
|
|
30594
|
-
return
|
|
31187
|
+
return defineCommand178({
|
|
30595
31188
|
meta: { name: opts.name, description: opts.description },
|
|
30596
31189
|
args: {
|
|
30597
31190
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -30640,7 +31233,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
30640
31233
|
});
|
|
30641
31234
|
|
|
30642
31235
|
// src/commands/winning-ads/unfollow.ts
|
|
30643
|
-
import { defineCommand as
|
|
31236
|
+
import { defineCommand as defineCommand179 } from "citty";
|
|
30644
31237
|
registerSchema({
|
|
30645
31238
|
command: "winning-ads.unfollow",
|
|
30646
31239
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -30648,7 +31241,7 @@ registerSchema({
|
|
|
30648
31241
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
30649
31242
|
}
|
|
30650
31243
|
});
|
|
30651
|
-
var unfollowCommand =
|
|
31244
|
+
var unfollowCommand = defineCommand179({
|
|
30652
31245
|
meta: {
|
|
30653
31246
|
name: "unfollow",
|
|
30654
31247
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -30669,7 +31262,7 @@ var unfollowCommand = defineCommand175({
|
|
|
30669
31262
|
});
|
|
30670
31263
|
|
|
30671
31264
|
// src/commands/winning-ads/winners.ts
|
|
30672
|
-
import { defineCommand as
|
|
31265
|
+
import { defineCommand as defineCommand180 } from "citty";
|
|
30673
31266
|
registerSchema({
|
|
30674
31267
|
command: "winning-ads.winners",
|
|
30675
31268
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -30679,7 +31272,7 @@ registerSchema({
|
|
|
30679
31272
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
30680
31273
|
}
|
|
30681
31274
|
});
|
|
30682
|
-
var winnersCommand =
|
|
31275
|
+
var winnersCommand = defineCommand180({
|
|
30683
31276
|
meta: {
|
|
30684
31277
|
name: "winners",
|
|
30685
31278
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -30729,7 +31322,7 @@ var winnersCommand = defineCommand176({
|
|
|
30729
31322
|
});
|
|
30730
31323
|
|
|
30731
31324
|
// src/commands/winning-ads/index.ts
|
|
30732
|
-
var winningAdsCommand =
|
|
31325
|
+
var winningAdsCommand = defineCommand181({
|
|
30733
31326
|
meta: {
|
|
30734
31327
|
name: "winning-ads",
|
|
30735
31328
|
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.
|
|
@@ -30785,7 +31378,7 @@ Full guide: __tooling__/docs/tools/baker/winning-ads.md`
|
|
|
30785
31378
|
});
|
|
30786
31379
|
|
|
30787
31380
|
// src/version.ts
|
|
30788
|
-
import { readFileSync as
|
|
31381
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
30789
31382
|
function packageJsonUrl() {
|
|
30790
31383
|
return new URL("../package.json", import.meta.url);
|
|
30791
31384
|
}
|
|
@@ -30797,15 +31390,15 @@ function parsePackageVersion(raw) {
|
|
|
30797
31390
|
throw new Error("Invalid CLI package.json: missing version");
|
|
30798
31391
|
}
|
|
30799
31392
|
function getCliVersion() {
|
|
30800
|
-
return parsePackageVersion(
|
|
31393
|
+
return parsePackageVersion(readFileSync13(packageJsonUrl(), "utf8"));
|
|
30801
31394
|
}
|
|
30802
31395
|
|
|
30803
31396
|
// src/cli.ts
|
|
30804
|
-
var main =
|
|
31397
|
+
var main = defineCommand182({
|
|
30805
31398
|
meta: {
|
|
30806
31399
|
name: "baker",
|
|
30807
31400
|
version: getCliVersion(),
|
|
30808
|
-
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, marketing tags, account history, and ad platform data in Baker.
|
|
31401
|
+
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, marketing tags, Tag Manager containers, account history, and ad platform data in Baker.
|
|
30809
31402
|
|
|
30810
31403
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
30811
31404
|
Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
|
|
@@ -30828,6 +31421,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
30828
31421
|
testimonials: testimonialsCommand,
|
|
30829
31422
|
canvas: canvasCommand,
|
|
30830
31423
|
tags: tagsCommand3,
|
|
31424
|
+
"tag-manager": tagManagerCommand,
|
|
30831
31425
|
chats: chatsCommand,
|
|
30832
31426
|
history: historyCommand,
|
|
30833
31427
|
"winning-ads": winningAdsCommand,
|