@koda-sl/baker-cli 0.141.0-dev.5c3f9a4ae → 0.141.0-dev.86f91edc8

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/dist/cli.js CHANGED
@@ -73,7 +73,7 @@ import {
73
73
  } from "./chunk-RK67WL4O.js";
74
74
 
75
75
  // src/cli.ts
76
- import { defineCommand as defineCommand175, runMain } from "citty";
76
+ import { defineCommand as defineCommand179, runMain } from "citty";
77
77
 
78
78
  // src/commands/actions/index.ts
79
79
  import { defineCommand as defineCommand18 } from "citty";
@@ -1980,6 +1980,7 @@ var chatChangeTypeSchema = z5.enum([
1980
1980
  "linkedin-ads",
1981
1981
  "google-ads",
1982
1982
  "meta-ads",
1983
+ "tag-manager",
1983
1984
  "briefs"
1984
1985
  ]);
1985
1986
  var chatChangeActionSchema = z5.enum(["created", "updated", "deleted"]);
@@ -3013,7 +3014,7 @@ var createCommand = defineCommand3({
3013
3014
  const hints = [];
3014
3015
  if (looksScheduled(name, args.description ?? "")) {
3015
3016
  hints.push(
3016
- 'This reads as recurring/scheduled work. If it should run on a cadence or a future date, create a Scheduled Action instead \u2014 baker scheduled-actions create --cron "0 9 * * MON" (or --run-at; guide: __tooling__/docs/tools/baker/scheduled-actions.md). Do NOT capture "set up a scheduled action" as a Work Action.'
3017
+ 'This reads as recurring/scheduled work. If it should run on a cadence or a future date, create a Scheduled Action instead \u2014 baker scheduled-actions create --cron "0 9 * * MON" (or --run-at). Do NOT capture "set up a scheduled action" as a Work Action.'
3017
3018
  );
3018
3019
  }
3019
3020
  hints.push(`Link dependencies: baker actions link --blocker <id> --blocked ${tempId}`);
@@ -3711,8 +3712,7 @@ Examples:
3711
3712
  baker actions claim <id>
3712
3713
  baker actions create --name "Build hero" --tags landing,creative --description "..."
3713
3714
  baker actions complete <id>
3714
- baker actions discard <id> --reason "obsolete"
3715
- Full guide: __tooling__/docs/tools/baker/actions.md`
3715
+ baker actions discard <id> --reason "obsolete"`
3716
3716
  },
3717
3717
  subCommands: {
3718
3718
  list: listCommand2,
@@ -7685,8 +7685,7 @@ Staged writes (never touch Google until the chat is published):
7685
7685
  baker ads google budgets create --customer-id 1234567890 --name "Search" --amount 50
7686
7686
  baker ads google campaigns create --customer-id 1234567890 --name "Brand" --channel-type SEARCH --budget-ref g_temp_\u2026 --bidding-strategy MANUAL_CPC
7687
7687
  baker ads google keyword-lists create --customer-id 1234567890 --name "Brand exclusions"
7688
- baker ads google draft list \u2014 review staged Google Ads changes
7689
- Full guide: __tooling__/docs/tools/baker/ads-google.md`
7688
+ baker ads google draft list \u2014 review staged Google Ads changes`
7690
7689
  },
7691
7690
  subCommands: {
7692
7691
  accounts: accountsCommand,
@@ -11146,8 +11145,7 @@ published; if the company's LinkedIn-write flag is off the publish is simulated)
11146
11145
 
11147
11146
  Account ID format:
11148
11147
  --account-id accepts numeric (503001492) or URN (urn:li:sponsoredAccount:503001492).
11149
- Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call.
11150
- Full guide: __tooling__/docs/tools/baker/ads-linkedin.md`
11148
+ Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call.`
11151
11149
  },
11152
11150
  subCommands: {
11153
11151
  accounts: accountsCommand2,
@@ -11348,13 +11346,11 @@ var SPECIAL_AD_CATEGORIES = [
11348
11346
  "NONE",
11349
11347
  "HOUSING",
11350
11348
  "EMPLOYMENT",
11351
- /** Deprecated by Meta on 2025-01-14 — replaced by FINANCIAL_PRODUCTS_SERVICES. Still accepted as input and mapped on the wire. */
11352
11349
  "CREDIT",
11353
11350
  "ISSUES_ELECTIONS_POLITICS",
11354
11351
  "FINANCIAL_PRODUCTS_SERVICES",
11355
11352
  "ONLINE_GAMBLING_AND_GAMING"
11356
11353
  ];
11357
- var SPECIAL_CATEGORIES_REQUIRING_COUNTRY = ["ISSUES_ELECTIONS_POLITICS"];
11358
11354
  var BUYING_TYPES = ["AUCTION", "RESERVED"];
11359
11355
  var BID_STRATEGIES = [
11360
11356
  "LOWEST_COST_WITHOUT_CAP",
@@ -11363,10 +11359,6 @@ var BID_STRATEGIES = [
11363
11359
  "LOWEST_COST_WITH_MIN_ROAS"
11364
11360
  ];
11365
11361
  var BID_STRATEGIES_REQUIRING_AMOUNT = ["LOWEST_COST_WITH_BID_CAP", "COST_CAP"];
11366
- var BID_STRATEGIES_FORBIDDING_AMOUNT = [
11367
- "LOWEST_COST_WITHOUT_CAP",
11368
- "LOWEST_COST_WITH_MIN_ROAS"
11369
- ];
11370
11362
  var BILLING_EVENTS = [
11371
11363
  "APP_INSTALLS",
11372
11364
  "CLICKS",
@@ -11406,9 +11398,6 @@ var OPTIMIZATION_GOALS_REQUIRING_PAGE = [
11406
11398
  "QUALITY_LEAD",
11407
11399
  "PAGE_LIKES"
11408
11400
  ];
11409
- var OPTIMIZATION_GOALS_REQUIRING_PIXEL = ["OFFSITE_CONVERSIONS"];
11410
- var OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE = ["VALUE"];
11411
- var OPTIMIZATION_GOALS_REQUIRING_APP = ["APP_INSTALLS"];
11412
11401
  var DESTINATION_TYPES = [
11413
11402
  "WEBSITE",
11414
11403
  "APP",
@@ -11438,8 +11427,6 @@ var CUSTOM_EVENT_TYPES = [
11438
11427
  "OTHER"
11439
11428
  ];
11440
11429
  var ATTRIBUTION_EVENT_TYPES = ["CLICK_THROUGH", "VIEW_THROUGH", "ENGAGED_VIDEO_VIEW"];
11441
- var ADVANTAGE_AUDIENCE_OPEN_AGE_MAX = 65;
11442
- var ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN = 25;
11443
11430
  var CTA_TYPES2 = [
11444
11431
  "LEARN_MORE",
11445
11432
  "SHOP_NOW",
@@ -11537,44 +11524,6 @@ var metaTargetingSchema = z14.object({
11537
11524
  device_platforms: z14.array(z14.string()).optional(),
11538
11525
  targeting_automation: z14.object({ advantage_audience: z14.union([z14.literal(0), z14.literal(1)]) }).partial().optional()
11539
11526
  }).catchall(z14.unknown());
11540
- var GEO_INCLUSION_KEYS = [
11541
- "countries",
11542
- "country_groups",
11543
- "regions",
11544
- "cities",
11545
- "zips",
11546
- "geo_markets",
11547
- "places",
11548
- "custom_locations",
11549
- "electoral_districts",
11550
- "subcities",
11551
- "neighborhoods"
11552
- ];
11553
- function targetingHasGeo(t) {
11554
- const geo = t?.geo_locations;
11555
- return Boolean(
11556
- geo && GEO_INCLUSION_KEYS.some((key) => Array.isArray(geo[key]) && geo[key].length > 0)
11557
- );
11558
- }
11559
- function targetingHasGeoOrAudience(t) {
11560
- if (!t) {
11561
- return false;
11562
- }
11563
- return targetingHasGeo(t) || Boolean(t.custom_audiences?.length);
11564
- }
11565
- function advantageAudienceSetting(t) {
11566
- const value = t.targeting_automation?.advantage_audience;
11567
- return value === 0 || value === 1 ? value : void 0;
11568
- }
11569
- function targetingHardLimitsDemographics(t) {
11570
- if (!t) {
11571
- return false;
11572
- }
11573
- const narrowsAgeMax = typeof t.age_max === "number" && t.age_max < ADVANTAGE_AUDIENCE_OPEN_AGE_MAX;
11574
- const narrowsAgeMin = typeof t.age_min === "number" && t.age_min > ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN;
11575
- const narrowsGender = Array.isArray(t.genders) && t.genders.length === 1;
11576
- return narrowsAgeMax || narrowsAgeMin || narrowsGender;
11577
- }
11578
11527
  var specialAdCategoriesSchema = z14.array(z14.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
11579
11528
  var campaignCreateSchema3 = z14.object({
11580
11529
  name: z14.string().min(1).max(META_LIMITS.campaign.nameMax),
@@ -11598,14 +11547,6 @@ var campaignCreateSchema3 = z14.object({
11598
11547
  if (p.stop_time && p.start_time && p.stop_time <= p.start_time) {
11599
11548
  ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
11600
11549
  }
11601
- const needsCountry = p.special_ad_categories.some((c) => SPECIAL_CATEGORIES_REQUIRING_COUNTRY.includes(c));
11602
- if (needsCountry && !p.special_ad_category_country?.length) {
11603
- ctx.addIssue({
11604
- code: "custom",
11605
- path: ["special_ad_category_country"],
11606
- message: "ISSUES_ELECTIONS_POLITICS campaigns need special_ad_category_country \u2014 pass the 2-letter country code(s) the ads run in"
11607
- });
11608
- }
11609
11550
  });
11610
11551
  var campaignUpdateSchema3 = z14.object({
11611
11552
  name: z14.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
@@ -11657,41 +11598,8 @@ var adSetFields = {
11657
11598
  attribution_spec: attributionSpecSchema.optional(),
11658
11599
  start_time: z14.number().int().positive().optional(),
11659
11600
  end_time: z14.number().int().positive().optional(),
11660
- targeting: metaTargetingSchema,
11661
- /** EU Digital Services Act: who benefits from / pays for the ad. Auto-filled from the account for EU geo when omitted. */
11662
- dsa_beneficiary: z14.string().min(1).max(100).optional(),
11663
- dsa_payor: z14.string().min(1).max(100).optional()
11601
+ targeting: metaTargetingSchema
11664
11602
  };
11665
- function validateBidStrategy(p, ctx) {
11666
- const strategy = p.bid_strategy;
11667
- if (!strategy) {
11668
- return;
11669
- }
11670
- if (BID_STRATEGIES_REQUIRING_AMOUNT.includes(strategy) && !p.bidAmount) {
11671
- ctx.addIssue({ code: "custom", path: ["bidAmount"], message: `${strategy} requires a bidAmount` });
11672
- }
11673
- if (BID_STRATEGIES_FORBIDDING_AMOUNT.includes(strategy) && p.bidAmount) {
11674
- ctx.addIssue({
11675
- code: "custom",
11676
- path: ["bidAmount"],
11677
- message: `${strategy} must not set a bidAmount \u2014 Meta rejects one (it bids automatically)`
11678
- });
11679
- }
11680
- if (strategy === "COST_CAP" && p.billing_event && p.billing_event !== "IMPRESSIONS") {
11681
- ctx.addIssue({
11682
- code: "custom",
11683
- path: ["billing_event"],
11684
- message: "COST_CAP requires billing_event IMPRESSIONS"
11685
- });
11686
- }
11687
- if (strategy === "LOWEST_COST_WITH_MIN_ROAS" && p.optimization_goal && p.optimization_goal !== "VALUE") {
11688
- ctx.addIssue({
11689
- code: "custom",
11690
- path: ["bid_strategy"],
11691
- message: "LOWEST_COST_WITH_MIN_ROAS requires optimization_goal VALUE"
11692
- });
11693
- }
11694
- }
11695
11603
  function validateAdSetBudgetAndBid(p, ctx) {
11696
11604
  if (p.dailyBudget && p.lifetimeBudget) {
11697
11605
  ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
@@ -11700,74 +11608,25 @@ function validateAdSetBudgetAndBid(p, ctx) {
11700
11608
  if (p.lifetimeBudget && !p.end_time) {
11701
11609
  ctx.addIssue({ code: "custom", path: ["end_time"], message: "lifetimeBudget ad sets need an end_time" });
11702
11610
  }
11703
- validateBidStrategy(p, ctx);
11611
+ if (p.bid_strategy && BID_STRATEGIES_REQUIRING_AMOUNT.includes(p.bid_strategy) && !p.bidAmount) {
11612
+ ctx.addIssue({ code: "custom", path: ["bidAmount"], message: `${p.bid_strategy} requires a bidAmount` });
11613
+ }
11704
11614
  if (p.end_time && p.start_time && p.end_time <= p.start_time) {
11705
11615
  ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
11706
11616
  }
11707
11617
  }
11708
11618
  function validateAdSetPromotedObject(p, ctx) {
11709
- const goal = p.optimization_goal;
11710
- if (!goal) {
11711
- return;
11712
- }
11713
- const po = p.promoted_object;
11714
- if (OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(goal) && !po?.page_id) {
11619
+ if (p.optimization_goal && OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(p.optimization_goal) && !p.promoted_object?.page_id) {
11715
11620
  ctx.addIssue({
11716
11621
  code: "custom",
11717
11622
  path: ["promoted_object", "page_id"],
11718
- message: `optimization_goal ${goal} needs promoted_object.page_id \u2014 pass --page-id with the Facebook Page the leads/likes belong to`
11719
- });
11720
- }
11721
- if (OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) && !po?.pixel_id) {
11722
- ctx.addIssue({
11723
- code: "custom",
11724
- path: ["promoted_object", "pixel_id"],
11725
- message: `optimization_goal ${goal} needs promoted_object.pixel_id \u2014 pass --pixel-id with the conversion pixel`
11726
- });
11727
- }
11728
- if (OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal) && !po?.pixel_id && !po?.application_id) {
11729
- ctx.addIssue({
11730
- code: "custom",
11731
- path: ["promoted_object", "pixel_id"],
11732
- message: `optimization_goal ${goal} needs a conversion source \u2014 pass promoted_object.pixel_id (web value optimization) or promoted_object.application_id (app value optimization)`
11733
- });
11734
- }
11735
- if ((OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) || OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal)) && !po?.custom_event_type) {
11736
- ctx.addIssue({
11737
- code: "custom",
11738
- path: ["promoted_object", "custom_event_type"],
11739
- message: `optimization_goal ${goal} needs promoted_object.custom_event_type \u2014 pass --custom-event-type (e.g. PURCHASE, LEAD)`
11740
- });
11741
- }
11742
- if (OPTIMIZATION_GOALS_REQUIRING_APP.includes(goal) && !po?.application_id) {
11743
- ctx.addIssue({
11744
- code: "custom",
11745
- path: ["promoted_object", "application_id"],
11746
- message: `optimization_goal ${goal} needs promoted_object.application_id`
11747
- });
11748
- }
11749
- }
11750
- function validateAdvantageAudience(p, ctx) {
11751
- const t = p.targeting;
11752
- if (t && targetingHardLimitsDemographics(t) && advantageAudienceSetting(t) === 1) {
11753
- ctx.addIssue({
11754
- code: "custom",
11755
- path: ["targeting", "targeting_automation", "advantage_audience"],
11756
- message: "Advantage+ Audience (advantage_audience: 1) treats age and gender as suggestions, so a hard age/gender limit is rejected \u2014 set advantage_audience: 0 to enforce the limit, or drop the age_max/age_min/gender restriction"
11623
+ message: `optimization_goal ${p.optimization_goal} needs promoted_object.page_id \u2014 pass --page-id with the Facebook Page the leads/likes belong to`
11757
11624
  });
11758
11625
  }
11759
11626
  }
11760
11627
  var adSetCreateSchema = z14.object(adSetFields).superRefine((p, ctx) => {
11761
11628
  validateAdSetBudgetAndBid(p, ctx);
11762
11629
  validateAdSetPromotedObject(p, ctx);
11763
- validateAdvantageAudience(p, ctx);
11764
- if (!targetingHasGeoOrAudience(p.targeting)) {
11765
- ctx.addIssue({
11766
- code: "custom",
11767
- path: ["targeting", "geo_locations"],
11768
- message: 'targeting needs a location \u2014 set targeting.geo_locations (e.g. countries: ["US"]) or include a custom audience; Meta rejects an ad set with no geo'
11769
- });
11770
- }
11771
11630
  });
11772
11631
  var adSetUpdateSchema = z14.object({
11773
11632
  name: adSetFields.name.optional(),
@@ -11782,9 +11641,7 @@ var adSetUpdateSchema = z14.object({
11782
11641
  attribution_spec: attributionSpecSchema.optional(),
11783
11642
  start_time: z14.number().int().positive().optional(),
11784
11643
  end_time: z14.number().int().positive().optional(),
11785
- targeting: metaTargetingSchema.optional(),
11786
- dsa_beneficiary: z14.string().min(1).max(100).optional(),
11787
- dsa_payor: z14.string().min(1).max(100).optional()
11644
+ targeting: metaTargetingSchema.optional()
11788
11645
  }).superRefine((p, ctx) => {
11789
11646
  if (!Object.values(p).some((val) => val !== void 0)) {
11790
11647
  ctx.addIssue({ code: "custom", message: "update needs at least one field" });
@@ -11793,7 +11650,6 @@ var adSetUpdateSchema = z14.object({
11793
11650
  if (p.optimization_goal) {
11794
11651
  validateAdSetPromotedObject(p, ctx);
11795
11652
  }
11796
- validateAdvantageAudience(p, ctx);
11797
11653
  });
11798
11654
  var messageSchema = z14.string().min(1).max(META_LIMITS.creative.messageHardMax);
11799
11655
  var headlineSchema2 = z14.string().min(1).max(META_LIMITS.creative.headlineMax);
@@ -13572,8 +13428,7 @@ Performance (the workhorse):
13572
13428
 
13573
13429
  Audit & review:
13574
13430
  baker ads meta activities --account-id act_123 --days 14
13575
- baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html
13576
- Full guide: __tooling__/docs/tools/baker/ads-meta.md`
13431
+ baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html`
13577
13432
  },
13578
13433
  subCommands: {
13579
13434
  accounts: accountsCommand3,
@@ -15037,8 +14892,7 @@ Examples:
15037
14892
  --start-time 2026-04-01T00:00:00Z --end-time 2026-05-01T00:00:00Z \\
15038
14893
  --metric-groups ENGAGEMENT,BILLING --segmentation-type LOCATIONS
15039
14894
 
15040
- The CLI auto-detects --account-id when exactly one X Ads account is connected, or via BAKER_X_ADS_ACCOUNT_ID.
15041
- Full guide: __tooling__/docs/tools/baker/ads-x.md`
14895
+ The CLI auto-detects --account-id when exactly one X Ads account is connected, or via BAKER_X_ADS_ACCOUNT_ID.`
15042
14896
  },
15043
14897
  subCommands: {
15044
14898
  accounts: accountsCommand4,
@@ -15076,8 +14930,7 @@ Examples:
15076
14930
  baker ads meta insights --object act_123 --level ad --date-preset last_7d --fields impressions,spend,ctr
15077
14931
  baker ads linkedin accounts
15078
14932
  baker ads x accounts
15079
- baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def
15080
- Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedin|x)`
14933
+ baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def`
15081
14934
  },
15082
14935
  subCommands: {
15083
14936
  google: googleCommand,
@@ -21774,8 +21627,7 @@ Subcommands:
21774
21627
  baker canvas catalog \u2014 print the agent-facing node + composition catalog (JSON Schema)
21775
21628
  baker canvas inspect <run_id> \u2014 one-page summary of a completed run
21776
21629
  baker canvas scaffold-video <video> \u2014 turn a reference video into a runnable reproduction canvas (deconstruct + recurring-element detection)
21777
- baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)
21778
- Full guide: __tooling__/docs/tools/baker/canvas.md`
21630
+ baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)`
21779
21631
  },
21780
21632
  subCommands: {
21781
21633
  run: runCommand,
@@ -22012,8 +21864,7 @@ var diffCommand = defineCommand96({
22012
21864
  var chatsCommand = defineCommand96({
22013
21865
  meta: {
22014
21866
  name: "chats",
22015
- description: `Inspect other Sessions on this account (read-only): list them, view what they produced, read their conversation, and see their real file changes \u2014 so you can reuse past work for a new goal.
22016
- Full guide: __tooling__/docs/tools/baker/chats.md`
21867
+ description: "Inspect other Sessions on this account (read-only): list them, view what they produced, read their conversation, and see their real file changes \u2014 so you can reuse past work for a new goal."
22017
21868
  },
22018
21869
  subCommands: {
22019
21870
  list: listCommand5,
@@ -22237,8 +22088,7 @@ var creativesCommand3 = defineCommand98({
22237
22088
  Static creative handoff:
22238
22089
  baker creatives publish ./canvas/run/final.png --title "Spring Offer Static Ad"
22239
22090
 
22240
- Publishing uploads the image to the Company image library, applies the official creative tag, and returns an image reference for chat previews.
22241
- Full guide: __tooling__/docs/tools/baker/creatives.md`
22091
+ Publishing uploads the image to the Company image library, applies the official creative tag, and returns an image reference for chat previews.`
22242
22092
  },
22243
22093
  subCommands: {
22244
22094
  publish: publishCommand
@@ -22446,8 +22296,7 @@ This command is READ-ONLY and never reveals secret values. Author a Form's struc
22446
22296
  Examples:
22447
22297
  baker flows list # every Form + how many confidential fields still need setup
22448
22298
  baker flows show contact # one Form's confidential fields and their status
22449
- baker flows show contact --full
22450
- Full guide: __tooling__/docs/tools/baker/flows.md`
22299
+ baker flows show contact --full`
22451
22300
  },
22452
22301
  subCommands: {
22453
22302
  list: listCommand6,
@@ -22856,8 +22705,7 @@ Examples:
22856
22705
  baker ga4 audit \u2014 full property health check
22857
22706
  baker ga4 query --preset tracking-health \u2014 compare GA4 vs GAds data
22858
22707
  baker ga4 query --preset lp-performance --days 14 \u2014 landing page UX audit
22859
- baker ga4 query --dimensions "date" --metrics "sessions" --days 7 \u2014 free-form query
22860
- Full guide: __tooling__/docs/tools/baker/ga4.md`
22708
+ baker ga4 query --dimensions "date" --metrics "sessions" --days 7 \u2014 free-form query`
22861
22709
  },
22862
22710
  subCommands: {
22863
22711
  properties: propertiesCommand,
@@ -23266,8 +23114,7 @@ Examples:
23266
23114
  baker gsc query --preset cannibalization \u2014 find PPC-SEO overlap
23267
23115
  baker gsc query --preset brand-halo --brand "Acme" --days 90 \u2014 brand search trends
23268
23116
  baker gsc query --dimensions "query,page" --days 28 \u2014 free-form query
23269
- baker gsc sitemaps \u2014 check sitemap health
23270
- Full guide: __tooling__/docs/tools/baker/gsc.md`
23117
+ baker gsc sitemaps \u2014 check sitemap health`
23271
23118
  },
23272
23119
  subCommands: {
23273
23120
  sites: sitesCommand,
@@ -23381,8 +23228,7 @@ var listCommand7 = defineCommand108({
23381
23228
  var historyCommand = defineCommand108({
23382
23229
  meta: {
23383
23230
  name: "history",
23384
- description: `Unified account history (audit log): what changed, who did it, and when.
23385
- Full guide: __tooling__/docs/tools/baker/history.md`
23231
+ description: "Unified account history (audit log): what changed, who did it, and when."
23386
23232
  },
23387
23233
  subCommands: { list: listCommand7 }
23388
23234
  });
@@ -25980,8 +25826,7 @@ Taxonomy:
25980
25826
  baker images tags List available image tag names (defaults + company custom tags)
25981
25827
 
25982
25828
  Paid transforms (run on the Convex backend, cost-tracked):
25983
- baker images upscale <imageId> Real-ESRGAN super-resolution ($0.05/image, waits for completion)
25984
- Full guide: __tooling__/docs/tools/baker/images.md`
25829
+ baker images upscale <imageId> Real-ESRGAN super-resolution ($0.05/image, waits for completion)`
25985
25830
  },
25986
25831
  subCommands: {
25987
25832
  get: getCommand2,
@@ -26045,53 +25890,6 @@ function fail4(err) {
26045
25890
  writeJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
26046
25891
  process.exit(1);
26047
25892
  }
26048
- registerSchema({
26049
- command: "mcp.connected",
26050
- description: "List every third-party tool this chat can reach: managed integrations (Attio, Slack, Gmail, Google Sheets, \u2026) plus custom MCP servers. Start here when the user mentions an external tool.",
26051
- args: {}
26052
- });
26053
- var connectedCommand = defineCommand133({
26054
- meta: {
26055
- name: "connected",
26056
- description: `List all connected third-party tools \u2014 managed integrations plus custom MCP servers.
26057
-
26058
- Managed tools ride the composio servers (mcp__composio_<scope>__*); custom servers expose mcp__<name>__*.
26059
- A tool the user names that is NOT listed here is simply not connected yet.`
26060
- },
26061
- run: async () => {
26062
- try {
26063
- const user = actingUserId();
26064
- const data = await apiGet("/api/mcp/connected", user ? { actingUserId: user } : void 0);
26065
- const managed = data.managed.map((c) => ({
26066
- toolkit: c.toolkitSlug,
26067
- scope: c.scope,
26068
- ...c.status !== "ACTIVE" ? { status: c.status } : {},
26069
- ...c.accountLabel ? { account: c.accountLabel } : {},
26070
- ...c.readOnly ? { readOnly: true } : {}
26071
- }));
26072
- const custom = data.custom.map((s) => ({ name: s.name, scope: s.scope, enabled: s.enabled }));
26073
- const hints = [];
26074
- if (data.managedDisabled) {
26075
- hints.push("Managed integrations are disabled for this company \u2014 only custom MCP servers load.");
26076
- }
26077
- if ([...data.managed, ...data.custom].some((e) => e.scope === "user" || e.scope === "user_org")) {
26078
- hints.push(
26079
- "user/user_org entries are personal: they belong to the current message sender and load only in their turns \u2014 other users in this chat won't have them."
26080
- );
26081
- }
26082
- hints.push(
26083
- "Not listed = not connected. Managed app (Slack, HubSpot, Attio, \u2026) \u2192 the user connects it in the dashboard: Brain \u2192 Integrations \u2192 Tools. Custom HTTPS MCP endpoint \u2192 `baker mcp add`."
26084
- );
26085
- writeJson({
26086
- ok: true,
26087
- data: { ...data.managedDisabled ? { managedDisabled: true } : {}, managed, custom },
26088
- hints
26089
- });
26090
- } catch (err) {
26091
- fail4(err);
26092
- }
26093
- }
26094
- });
26095
25893
  registerSchema({
26096
25894
  command: "mcp.list",
26097
25895
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
@@ -26188,22 +25986,20 @@ Example:
26188
25986
  var mcpCommand = defineCommand133({
26189
25987
  meta: {
26190
25988
  name: "mcp",
26191
- description: `Third-party tools for this company \u2014 see what's connected, register custom HTTPS MCP endpoints.
25989
+ description: `Custom MCP servers for this company \u2014 point the agent at any HTTPS MCP endpoint.
26192
25990
 
26193
25991
  Tools from a registered server appear as mcp__<name>__* on the next message.
26194
25992
  Managed here are **company-scoped** servers; user- and org-scoped servers are managed in the dashboard.
26195
25993
 
26196
25994
  Start here:
26197
- baker mcp connected # everything this chat can reach: managed integrations + custom servers
25995
+ baker mcp list
26198
25996
 
26199
25997
  Examples:
26200
25998
  baker mcp add --name weather --url https://mcp.example.com/mcp
26201
25999
  baker mcp add --name acme --url https://acme.dev/mcp --header "Authorization: Bearer sk-\u2026"
26202
- baker mcp remove --name weather
26203
- Full guide: __tooling__/docs/tools/baker/mcp.md`
26000
+ baker mcp remove --name weather`
26204
26001
  },
26205
26002
  subCommands: {
26206
- connected: connectedCommand,
26207
26003
  list: listCommand8,
26208
26004
  add: addCommand,
26209
26005
  remove: removeCommand4
@@ -27075,8 +26871,7 @@ Examples:
27075
26871
  baker research advertisers "running shoes"
27076
26872
  baker research intent "buy running shoes,best running shoes 2026"
27077
26873
  baker research keywords-for-site "competitor.com"
27078
- baker research keyword-gap "them.com" "us.com"
27079
- Full guide: __tooling__/docs/tools/baker/research.md`
26874
+ baker research keyword-gap "them.com" "us.com"`
27080
26875
  },
27081
26876
  subCommands: {
27082
26877
  web: webCommand,
@@ -27523,8 +27318,7 @@ Examples:
27523
27318
  baker scheduled-actions create --name "Weekly report" --description "Prepare weekly report" --cron "0 9 * * MON"
27524
27319
  baker scheduled-actions update <id-or-temp_sched_id> --enabled false
27525
27320
  baker scheduled-actions delete <id-or-temp_sched_id>
27526
- baker scheduled-actions trigger <id>
27527
- Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
27321
+ baker scheduled-actions trigger <id>`
27528
27322
  },
27529
27323
  subCommands: {
27530
27324
  list: listCommand9,
@@ -27560,17 +27354,11 @@ var schemaCommand = defineCommand152({
27560
27354
  const schema = getSchema(commandName);
27561
27355
  if (!schema) {
27562
27356
  const available = listSchemas();
27563
- const segments = commandName.split(".");
27564
- const family = segments[0] === "ads" && segments[1] ? `ads-${segments[1]}` : segments[0];
27565
27357
  writeJson({
27566
27358
  ok: false,
27567
27359
  error: {
27568
27360
  code: "NOT_FOUND",
27569
- message: `Schema "${commandName}" not found. Available: ${available.join(", ")}`,
27570
- fix: {
27571
- action: `Run the command with --help for exact args, and read __tooling__/docs/tools/baker/${family}.md`,
27572
- explanation: "Not every command registers a schema; --help and the family doc are the ground truth for those."
27573
- }
27361
+ message: `Schema "${commandName}" not found. Available: ${available.join(", ")}`
27574
27362
  }
27575
27363
  });
27576
27364
  process.exit(1);
@@ -27579,9 +27367,512 @@ var schemaCommand = defineCommand152({
27579
27367
  }
27580
27368
  });
27581
27369
 
27582
- // src/commands/tags/index.ts
27370
+ // src/commands/tag-manager/index.ts
27371
+ import { defineCommand as defineCommand156 } from "citty";
27372
+
27373
+ // src/commands/tag-manager/draft.ts
27583
27374
  import { defineCommand as defineCommand153 } from "citty";
27584
27375
 
27376
+ // src/commands/tag-manager/shared.ts
27377
+ import { readFileSync as readFileSync12 } from "fs";
27378
+ function failValidation3(message) {
27379
+ writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
27380
+ process.exit(1);
27381
+ }
27382
+ function requireTarget4(args, entity) {
27383
+ const positional = Array.isArray(args._) ? args._[0] : void 0;
27384
+ const target = args.id ?? args.target ?? positional;
27385
+ if (typeof target !== "string" || target.length === 0) {
27386
+ failValidation3(`pass the ${entity} id or path as the positional argument`);
27387
+ }
27388
+ return target;
27389
+ }
27390
+ function loadJsonArg(args, flag = "json") {
27391
+ const inline = args[flag];
27392
+ const file = args.file;
27393
+ const raw = typeof file === "string" && file.length > 0 ? readFileSync12(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
27394
+ if (raw === void 0) {
27395
+ failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
27396
+ }
27397
+ try {
27398
+ const parsed = JSON.parse(raw);
27399
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
27400
+ failValidation3(`--${flag} must be a JSON object`);
27401
+ }
27402
+ return parsed;
27403
+ } catch {
27404
+ return failValidation3(`--${flag} is not valid JSON`);
27405
+ }
27406
+ }
27407
+ function handleError3(err) {
27408
+ if (err instanceof ApiError) {
27409
+ const notConnected = err.code === "NOT_FOUND" || err.code === "UNAUTHORIZED";
27410
+ writeJsonEnvelope({
27411
+ ok: false,
27412
+ error: {
27413
+ code: err.code,
27414
+ message: err.message,
27415
+ ...notConnected ? {
27416
+ fix: {
27417
+ action: "ask_user",
27418
+ 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."
27419
+ }
27420
+ } : {},
27421
+ retryable: false
27422
+ }
27423
+ });
27424
+ process.exit(1);
27425
+ }
27426
+ writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
27427
+ process.exit(1);
27428
+ }
27429
+ function stageHints(response) {
27430
+ const hints = [];
27431
+ if (response.mode === "simulated") {
27432
+ hints.push(
27433
+ "Tag Manager writes are SIMULATED for this company \u2014 this change will not reach the real container on publish."
27434
+ );
27435
+ }
27436
+ hints.push(
27437
+ "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."
27438
+ );
27439
+ return hints;
27440
+ }
27441
+ async function stageOp3(op) {
27442
+ const chatId = requireChatId();
27443
+ try {
27444
+ const data = await apiPost("/api/tag-manager/draft/stage", { chatId, op });
27445
+ writeJsonEnvelope({ ok: true, data, hints: stageHints(data) });
27446
+ } catch (err) {
27447
+ handleError3(err);
27448
+ }
27449
+ }
27450
+ async function draftAction2(path23, body) {
27451
+ const chatId = requireChatId();
27452
+ try {
27453
+ const data = await apiPost(path23, { chatId, ...body });
27454
+ writeJsonEnvelope({ ok: true, data });
27455
+ return data;
27456
+ } catch (err) {
27457
+ handleError3(err);
27458
+ }
27459
+ }
27460
+ function renderDraft(response) {
27461
+ if (response.count === 0) {
27462
+ return "No Tag Manager changes staged on this chat.";
27463
+ }
27464
+ const lines = [
27465
+ `${response.count} staged Tag Manager change(s) \u2014 mode: ${response.mode}`,
27466
+ ...response.ops.map((op) => {
27467
+ const status = op.result ? ` [${op.result.status}]` : "";
27468
+ return ` ${op.ref} ${op.summary}${status}`;
27469
+ })
27470
+ ];
27471
+ if (response.versionId) {
27472
+ lines.push(
27473
+ "",
27474
+ `Applied into Tag Manager version ${response.versionId}. It is NOT published \u2014 publish it in Tag Manager to go live.`
27475
+ );
27476
+ }
27477
+ if (response.compilerError) {
27478
+ lines.push("", `Tag Manager reported a problem building the version: ${response.compilerError}`);
27479
+ }
27480
+ return lines.join("\n");
27481
+ }
27482
+ async function draftList(json) {
27483
+ const chatId = requireChatId();
27484
+ try {
27485
+ const data = await apiPost("/api/tag-manager/draft", { chatId });
27486
+ if (json) {
27487
+ writeJsonEnvelope({ ok: true, data });
27488
+ return;
27489
+ }
27490
+ process.stdout.write(`${renderDraft(data)}
27491
+ `);
27492
+ } catch (err) {
27493
+ handleError3(err);
27494
+ }
27495
+ }
27496
+
27497
+ // src/commands/tag-manager/draft.ts
27498
+ registerSchema({
27499
+ command: "tagManager.draft",
27500
+ 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.",
27501
+ args: {
27502
+ json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
27503
+ }
27504
+ });
27505
+ var draftCommand3 = defineCommand153({
27506
+ meta: {
27507
+ name: "draft",
27508
+ description: "List, show, amend, remove, or clear staged Tag Manager changes for this chat"
27509
+ },
27510
+ subCommands: {
27511
+ list: defineCommand153({
27512
+ meta: {
27513
+ name: "list",
27514
+ description: "Review everything staged on this chat (--json for the raw envelope)"
27515
+ },
27516
+ args: { json: { type: "boolean", description: "Print the raw JSON envelope", required: false } },
27517
+ run: async ({ args }) => {
27518
+ await draftList(args.json === true);
27519
+ }
27520
+ }),
27521
+ show: defineCommand153({
27522
+ meta: {
27523
+ name: "show",
27524
+ description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
27525
+ },
27526
+ args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
27527
+ run: async ({ args }) => {
27528
+ await draftAction2("/api/tag-manager/draft/show", {
27529
+ ref: requireTarget4(args, "change")
27530
+ });
27531
+ }
27532
+ }),
27533
+ amend: defineCommand153({
27534
+ meta: {
27535
+ name: "amend",
27536
+ 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."
27537
+ },
27538
+ args: {
27539
+ ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false },
27540
+ patch: { type: "string", description: "Inline JSON patch object", required: false },
27541
+ file: { type: "string", description: "JSON file with the patch object", required: false }
27542
+ },
27543
+ run: async ({ args }) => {
27544
+ await draftAction2("/api/tag-manager/draft/amend", {
27545
+ ref: requireTarget4(args, "change"),
27546
+ patch: loadJsonArg(args, "patch")
27547
+ });
27548
+ }
27549
+ }),
27550
+ remove: defineCommand153({
27551
+ meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
27552
+ args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
27553
+ run: async ({ args }) => {
27554
+ await draftAction2("/api/tag-manager/draft/remove", {
27555
+ ref: requireTarget4(args, "change")
27556
+ });
27557
+ }
27558
+ }),
27559
+ clear: defineCommand153({
27560
+ meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
27561
+ run: async () => {
27562
+ await draftAction2("/api/tag-manager/draft/clear", {});
27563
+ }
27564
+ })
27565
+ }
27566
+ });
27567
+
27568
+ // src/commands/tag-manager/read.ts
27569
+ import { defineCommand as defineCommand154 } from "citty";
27570
+ registerSchema({
27571
+ command: "tagManager.containers",
27572
+ 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.",
27573
+ args: {}
27574
+ });
27575
+ registerSchema({
27576
+ command: "tagManager.read",
27577
+ 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.",
27578
+ args: {
27579
+ container: { type: "string", description: "Numeric container id (defaults to the connected one)", required: false },
27580
+ workspace: { type: "string", description: "Workspace id (defaults to the default workspace)", required: false },
27581
+ entities: {
27582
+ type: "string",
27583
+ description: "Comma-separated subset: tag,trigger,variable,folder,builtInVariable",
27584
+ required: false
27585
+ },
27586
+ full: { type: "boolean", description: "Include the raw Tag Manager object for each entity", required: false }
27587
+ }
27588
+ });
27589
+ function fail5(err) {
27590
+ if (err instanceof ApiError) {
27591
+ const notConnected = err.code === "NOT_FOUND" || err.code === "UNAUTHORIZED";
27592
+ writeJsonEnvelope({
27593
+ ok: false,
27594
+ error: {
27595
+ code: err.code,
27596
+ message: err.message,
27597
+ ...notConnected ? {
27598
+ fix: {
27599
+ action: "ask_user",
27600
+ 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."
27601
+ }
27602
+ } : {},
27603
+ retryable: false
27604
+ }
27605
+ });
27606
+ process.exit(1);
27607
+ }
27608
+ writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
27609
+ process.exit(1);
27610
+ }
27611
+ var containersCommand = defineCommand154({
27612
+ meta: {
27613
+ name: "containers",
27614
+ description: `List Tag Manager containers reachable by this company's connection.
27615
+
27616
+ Start here:
27617
+ baker tag-manager containers`
27618
+ },
27619
+ run: async () => {
27620
+ try {
27621
+ const data = await apiGet("/api/tag-manager/containers");
27622
+ writeJsonEnvelope({ ok: true, data });
27623
+ } catch (err) {
27624
+ fail5(err);
27625
+ }
27626
+ }
27627
+ });
27628
+ var readCommand = defineCommand154({
27629
+ meta: {
27630
+ name: "read",
27631
+ description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
27632
+
27633
+ Examples:
27634
+ baker tag-manager read
27635
+ baker tag-manager read --entities tag,trigger
27636
+ baker tag-manager read --full`
27637
+ },
27638
+ args: {
27639
+ container: { type: "string", description: "Numeric container id", required: false },
27640
+ workspace: { type: "string", description: "Workspace id", required: false },
27641
+ entities: { type: "string", description: "Comma-separated entity subset", required: false },
27642
+ full: { type: "boolean", description: "Include raw Tag Manager objects", required: false }
27643
+ },
27644
+ run: async ({ args }) => {
27645
+ const entities = typeof args.entities === "string" && args.entities.length > 0 ? args.entities.split(",").map((entry) => entry.trim()) : void 0;
27646
+ try {
27647
+ const data = await apiPost("/api/tag-manager/read", {
27648
+ containerId: args.container,
27649
+ workspaceId: args.workspace,
27650
+ entities,
27651
+ full: args.full === true
27652
+ });
27653
+ const hints = [];
27654
+ if (data.installedContainerMismatch) {
27655
+ hints.push(data.installedContainerMismatch);
27656
+ }
27657
+ hints.push(
27658
+ "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."
27659
+ );
27660
+ writeJsonEnvelope({ ok: true, data, hints });
27661
+ } catch (err) {
27662
+ fail5(err);
27663
+ }
27664
+ }
27665
+ });
27666
+
27667
+ // src/commands/tag-manager/write-commands.ts
27668
+ import { defineCommand as defineCommand155 } from "citty";
27669
+ var ENTITIES = [
27670
+ {
27671
+ entity: "tag",
27672
+ noun: "tag",
27673
+ 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.'
27674
+ },
27675
+ {
27676
+ entity: "trigger",
27677
+ noun: "trigger",
27678
+ 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.'
27679
+ },
27680
+ {
27681
+ entity: "variable",
27682
+ noun: "variable",
27683
+ 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}}.'
27684
+ },
27685
+ {
27686
+ entity: "folder",
27687
+ noun: "folder",
27688
+ createHint: "Payload needs name. Use folders to keep a large container legible."
27689
+ }
27690
+ ];
27691
+ for (const { entity, noun, createHint } of ENTITIES) {
27692
+ registerSchema({
27693
+ command: `tagManager.${entity}.create`,
27694
+ description: `Stage the creation of a Tag Manager ${noun}. ${createHint} Staged only \u2014 applies on publish into an unpublished container version.`,
27695
+ args: {
27696
+ json: { type: "string", description: `Inline JSON ${noun} definition`, required: false },
27697
+ file: { type: "string", description: `Path to a JSON file with the ${noun} definition`, required: false },
27698
+ container: { type: "string", description: "Numeric container id", required: false }
27699
+ }
27700
+ });
27701
+ registerSchema({
27702
+ command: `tagManager.${entity}.update`,
27703
+ 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.`,
27704
+ args: {
27705
+ json: { type: "string", description: "Inline JSON with the changed fields", required: false },
27706
+ file: { type: "string", description: "Path to a JSON file with the changed fields", required: false }
27707
+ }
27708
+ });
27709
+ registerSchema({
27710
+ command: `tagManager.${entity}.delete`,
27711
+ 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.`,
27712
+ args: {}
27713
+ });
27714
+ }
27715
+ function entityCommand(entity, noun) {
27716
+ return defineCommand155({
27717
+ meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
27718
+ subCommands: {
27719
+ create: defineCommand155({
27720
+ meta: {
27721
+ name: "create",
27722
+ description: `Stage a new ${noun}
27723
+
27724
+ Examples:
27725
+ baker tag-manager ${entity} create --json '{"name":"GA4 Config","type":"googtag"}'
27726
+ baker tag-manager ${entity} create --file ./${entity}.json`
27727
+ },
27728
+ args: {
27729
+ json: { type: "string", description: "Inline JSON definition", required: false },
27730
+ file: { type: "string", description: "Path to a JSON file", required: false },
27731
+ container: { type: "string", description: "Numeric container id", required: false }
27732
+ },
27733
+ run: async ({ args }) => {
27734
+ await stageOp3({
27735
+ kind: `tagManager.${entity}.create`,
27736
+ payload: loadJsonArg(args),
27737
+ ...typeof args.container === "string" ? { containerId: args.container } : {}
27738
+ });
27739
+ }
27740
+ }),
27741
+ update: defineCommand155({
27742
+ meta: {
27743
+ name: "update",
27744
+ description: `Stage an update to an existing ${noun} (pass its id or path)`
27745
+ },
27746
+ args: {
27747
+ id: { type: "positional", description: `${noun} id or path`, required: false },
27748
+ json: { type: "string", description: "Inline JSON with changed fields", required: false },
27749
+ file: { type: "string", description: "Path to a JSON file", required: false },
27750
+ container: { type: "string", description: "Numeric container id", required: false }
27751
+ },
27752
+ run: async ({ args }) => {
27753
+ await stageOp3({
27754
+ kind: `tagManager.${entity}.update`,
27755
+ target: requireTarget4(args, noun),
27756
+ payload: loadJsonArg(args),
27757
+ ...typeof args.container === "string" ? { containerId: args.container } : {}
27758
+ });
27759
+ }
27760
+ }),
27761
+ delete: defineCommand155({
27762
+ meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
27763
+ args: {
27764
+ id: { type: "positional", description: `${noun} id or path`, required: false },
27765
+ container: { type: "string", description: "Numeric container id", required: false }
27766
+ },
27767
+ run: async ({ args }) => {
27768
+ await stageOp3({
27769
+ kind: `tagManager.${entity}.delete`,
27770
+ target: requireTarget4(args, noun),
27771
+ ...typeof args.container === "string" ? { containerId: args.container } : {}
27772
+ });
27773
+ }
27774
+ })
27775
+ }
27776
+ });
27777
+ }
27778
+ var tagCommand = entityCommand("tag", "tag");
27779
+ var triggerCommand2 = entityCommand("trigger", "trigger");
27780
+ var variableCommand = entityCommand("variable", "variable");
27781
+ var folderCommand = entityCommand("folder", "folder");
27782
+ registerSchema({
27783
+ command: "tagManager.builtin",
27784
+ 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}}.",
27785
+ args: {
27786
+ types: { type: "string", description: "Comma-separated built-in variable types", required: true }
27787
+ }
27788
+ });
27789
+ function builtinTypes(args) {
27790
+ const raw = args.types;
27791
+ if (typeof raw !== "string" || raw.length === 0) {
27792
+ process.stdout.write(
27793
+ `${JSON.stringify({ ok: false, error: { code: "VALIDATION_ERROR", message: "pass --types with comma-separated built-in variable types" } }, null, 2)}
27794
+ `
27795
+ );
27796
+ process.exit(1);
27797
+ }
27798
+ return raw.split(",").map((entry) => entry.trim());
27799
+ }
27800
+ var builtinCommand = defineCommand155({
27801
+ meta: {
27802
+ name: "builtin",
27803
+ description: `Enable or disable built-in variables
27804
+
27805
+ Examples:
27806
+ baker tag-manager builtin enable --types clickUrl,clickText
27807
+ baker tag-manager builtin disable --types formId`
27808
+ },
27809
+ subCommands: {
27810
+ enable: defineCommand155({
27811
+ meta: { name: "enable", description: "Stage enabling built-in variables" },
27812
+ args: {
27813
+ types: { type: "string", description: "Comma-separated types", required: false },
27814
+ container: { type: "string", description: "Numeric container id", required: false }
27815
+ },
27816
+ run: async ({ args }) => {
27817
+ await stageOp3({
27818
+ kind: "tagManager.builtInVariable.enable",
27819
+ payload: { type: builtinTypes(args) },
27820
+ ...typeof args.container === "string" ? { containerId: args.container } : {}
27821
+ });
27822
+ }
27823
+ }),
27824
+ disable: defineCommand155({
27825
+ meta: { name: "disable", description: "Stage disabling built-in variables" },
27826
+ args: {
27827
+ types: { type: "string", description: "Comma-separated types", required: false },
27828
+ container: { type: "string", description: "Numeric container id", required: false }
27829
+ },
27830
+ run: async ({ args }) => {
27831
+ await stageOp3({
27832
+ kind: "tagManager.builtInVariable.disable",
27833
+ payload: { type: builtinTypes(args) },
27834
+ ...typeof args.container === "string" ? { containerId: args.container } : {}
27835
+ });
27836
+ }
27837
+ })
27838
+ }
27839
+ });
27840
+
27841
+ // src/commands/tag-manager/index.ts
27842
+ var tagManagerCommand = defineCommand156({
27843
+ meta: {
27844
+ name: "tag-manager",
27845
+ description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
27846
+
27847
+ Start here:
27848
+ baker tag-manager read \u2014 see what the container holds today
27849
+
27850
+ Then stage changes (nothing is sent to Tag Manager until publish):
27851
+ baker tag-manager trigger create --json '{"name":"Quote Submit","type":"customEvent"}'
27852
+ baker tag-manager tag create --json '{"name":"GA4 Quote","type":"gaawe","firingTriggerId":["gtm_temp_trigger_..."]}'
27853
+ baker tag-manager draft list \u2014 review everything staged
27854
+
27855
+ On publish, staged changes are written into a new Tag Manager version that is NOT published.
27856
+ Tell the user to publish that version in Tag Manager to make it live.
27857
+
27858
+ This owns the CONTENTS of the container. Installing the container snippet on the site is a
27859
+ different job \u2014 that is \`baker tags\` with the googleTagManager tag.`
27860
+ },
27861
+ subCommands: {
27862
+ containers: containersCommand,
27863
+ read: readCommand,
27864
+ tag: tagCommand,
27865
+ trigger: triggerCommand2,
27866
+ variable: variableCommand,
27867
+ folder: folderCommand,
27868
+ builtin: builtinCommand,
27869
+ draft: draftCommand3
27870
+ }
27871
+ });
27872
+
27873
+ // src/commands/tags/index.ts
27874
+ import { defineCommand as defineCommand157 } from "citty";
27875
+
27585
27876
  // src/commands/tags/shared.ts
27586
27877
  function failApi3(err) {
27587
27878
  if (err instanceof ApiError) {
@@ -27646,7 +27937,7 @@ async function listTags(json) {
27646
27937
  failApi3(err);
27647
27938
  }
27648
27939
  }
27649
- var listCommand10 = defineCommand153({
27940
+ var listCommand10 = defineCommand157({
27650
27941
  meta: {
27651
27942
  name: "list",
27652
27943
  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"
@@ -27665,7 +27956,7 @@ async function listDraft3() {
27665
27956
  failApi3(err);
27666
27957
  }
27667
27958
  }
27668
- var draftCommand3 = defineCommand153({
27959
+ var draftCommand4 = defineCommand157({
27669
27960
  meta: {
27670
27961
  name: "draft",
27671
27962
  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)."
@@ -27674,7 +27965,7 @@ var draftCommand3 = defineCommand153({
27674
27965
  await listDraft3();
27675
27966
  }
27676
27967
  });
27677
- var tagsCommand3 = defineCommand153({
27968
+ var tagsCommand3 = defineCommand157({
27678
27969
  meta: {
27679
27970
  name: "tags",
27680
27971
  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.
@@ -27687,12 +27978,11 @@ Refs: \`baker tags list\` prints each tag's ref \u2014 a real tag id, or tag_tem
27687
27978
 
27688
27979
  Examples:
27689
27980
  baker tags list # production + staged, full readable config + secret status
27690
- baker tags draft # review the staged changes awaiting publish
27691
- Full guide: __tooling__/docs/tools/baker/tags.md`
27981
+ baker tags draft # review the staged changes awaiting publish`
27692
27982
  },
27693
27983
  subCommands: {
27694
27984
  list: listCommand10,
27695
- draft: draftCommand3
27985
+ draft: draftCommand4
27696
27986
  },
27697
27987
  run: async () => {
27698
27988
  await listTags(false);
@@ -27700,10 +27990,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
27700
27990
  });
27701
27991
 
27702
27992
  // src/commands/testimonials/index.ts
27703
- import { defineCommand as defineCommand157 } from "citty";
27993
+ import { defineCommand as defineCommand161 } from "citty";
27704
27994
 
27705
27995
  // src/commands/testimonials/get.ts
27706
- import { defineCommand as defineCommand154 } from "citty";
27996
+ import { defineCommand as defineCommand158 } from "citty";
27707
27997
  registerSchema({
27708
27998
  command: "testimonials.get",
27709
27999
  description: "Get a single testimonial by ID",
@@ -27711,7 +28001,7 @@ registerSchema({
27711
28001
  id: { type: "string", description: "Testimonial ID", required: true }
27712
28002
  }
27713
28003
  });
27714
- var getCommand4 = defineCommand154({
28004
+ var getCommand4 = defineCommand158({
27715
28005
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
27716
28006
  args: {
27717
28007
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -27748,7 +28038,7 @@ var getCommand4 = defineCommand154({
27748
28038
  });
27749
28039
 
27750
28040
  // src/commands/testimonials/list.ts
27751
- import { defineCommand as defineCommand155 } from "citty";
28041
+ import { defineCommand as defineCommand159 } from "citty";
27752
28042
  registerSchema({
27753
28043
  command: "testimonials.list",
27754
28044
  description: "List testimonials with optional filters.",
@@ -27778,7 +28068,7 @@ registerSchema({
27778
28068
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
27779
28069
  }
27780
28070
  });
27781
- var listCommand11 = defineCommand155({
28071
+ var listCommand11 = defineCommand159({
27782
28072
  meta: {
27783
28073
  name: "list",
27784
28074
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -27827,7 +28117,7 @@ var listCommand11 = defineCommand155({
27827
28117
  });
27828
28118
 
27829
28119
  // src/commands/testimonials/search.ts
27830
- import { defineCommand as defineCommand156 } from "citty";
28120
+ import { defineCommand as defineCommand160 } from "citty";
27831
28121
  function languageBiasHint(results, requestedLanguage) {
27832
28122
  if (requestedLanguage) {
27833
28123
  return null;
@@ -27905,7 +28195,7 @@ function buildSearchRequest(query, args) {
27905
28195
  }
27906
28196
  return body;
27907
28197
  }
27908
- var searchCommand2 = defineCommand156({
28198
+ var searchCommand2 = defineCommand160({
27909
28199
  meta: {
27910
28200
  name: "search",
27911
28201
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -27961,7 +28251,7 @@ var searchCommand2 = defineCommand156({
27961
28251
  var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
27962
28252
 
27963
28253
  // src/commands/testimonials/index.ts
27964
- var testimonialsCommand = defineCommand157({
28254
+ var testimonialsCommand = defineCommand161({
27965
28255
  meta: {
27966
28256
  name: "testimonials",
27967
28257
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -27971,8 +28261,7 @@ Examples:
27971
28261
  baker testimonials search "value for money" --rating-min 4
27972
28262
  baker testimonials get <testimonial-id>
27973
28263
  baker testimonials list --source google --sentiment positive
27974
- baker testimonials tags
27975
- Full guide: __tooling__/docs/tools/baker/testimonials.md`
28264
+ baker testimonials tags`
27976
28265
  },
27977
28266
  subCommands: {
27978
28267
  get: getCommand4,
@@ -27983,10 +28272,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
27983
28272
  });
27984
28273
 
27985
28274
  // src/commands/videos/index.ts
27986
- import { defineCommand as defineCommand162 } from "citty";
28275
+ import { defineCommand as defineCommand166 } from "citty";
27987
28276
 
27988
28277
  // src/commands/videos/delete.ts
27989
- import { defineCommand as defineCommand158 } from "citty";
28278
+ import { defineCommand as defineCommand162 } from "citty";
27990
28279
  registerSchema({
27991
28280
  command: "videos.delete",
27992
28281
  description: "Delete a video by ID",
@@ -28000,7 +28289,7 @@ registerSchema({
28000
28289
  }
28001
28290
  }
28002
28291
  });
28003
- var deleteCommand3 = defineCommand158({
28292
+ var deleteCommand3 = defineCommand162({
28004
28293
  meta: {
28005
28294
  name: "delete",
28006
28295
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -28041,7 +28330,7 @@ var deleteCommand3 = defineCommand158({
28041
28330
  });
28042
28331
 
28043
28332
  // src/commands/videos/get.ts
28044
- import { defineCommand as defineCommand159 } from "citty";
28333
+ import { defineCommand as defineCommand163 } from "citty";
28045
28334
  registerSchema({
28046
28335
  command: "videos.get",
28047
28336
  description: "Get a single video by ID",
@@ -28049,7 +28338,7 @@ registerSchema({
28049
28338
  id: { type: "string", description: "Video ID", required: true }
28050
28339
  }
28051
28340
  });
28052
- var getCommand5 = defineCommand159({
28341
+ var getCommand5 = defineCommand163({
28053
28342
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
28054
28343
  args: {
28055
28344
  id: { type: "positional", description: "Video ID", required: false },
@@ -28086,7 +28375,7 @@ var getCommand5 = defineCommand159({
28086
28375
  });
28087
28376
 
28088
28377
  // src/commands/videos/search.ts
28089
- import { defineCommand as defineCommand160 } from "citty";
28378
+ import { defineCommand as defineCommand164 } from "citty";
28090
28379
  registerSchema({
28091
28380
  command: "videos.search",
28092
28381
  description: "Search videos by text query. Only returns ready videos.",
@@ -28096,7 +28385,7 @@ registerSchema({
28096
28385
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
28097
28386
  }
28098
28387
  });
28099
- var searchCommand3 = defineCommand160({
28388
+ var searchCommand3 = defineCommand164({
28100
28389
  meta: {
28101
28390
  name: "search",
28102
28391
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -28148,7 +28437,7 @@ var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
28148
28437
  // src/commands/videos/upload.ts
28149
28438
  import { readFile as readFile20, stat as stat5 } from "fs/promises";
28150
28439
  import { extname as extname3 } from "path";
28151
- import { defineCommand as defineCommand161 } from "citty";
28440
+ import { defineCommand as defineCommand165 } from "citty";
28152
28441
  var MIME_MAP = {
28153
28442
  ".mp4": "video/mp4",
28154
28443
  ".mov": "video/quicktime",
@@ -28182,7 +28471,7 @@ function detectContentType(filePath) {
28182
28471
  }
28183
28472
  return mime;
28184
28473
  }
28185
- var uploadCommand2 = defineCommand161({
28474
+ var uploadCommand2 = defineCommand165({
28186
28475
  meta: {
28187
28476
  name: "upload",
28188
28477
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -28236,7 +28525,7 @@ var uploadCommand2 = defineCommand161({
28236
28525
  });
28237
28526
 
28238
28527
  // src/commands/videos/index.ts
28239
- var videosCommand = defineCommand162({
28528
+ var videosCommand = defineCommand166({
28240
28529
  meta: {
28241
28530
  name: "videos",
28242
28531
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -28247,8 +28536,7 @@ Examples:
28247
28536
  baker videos get <video-id>
28248
28537
  baker videos upload ./demo.mp4
28249
28538
  baker videos delete <video-id> --dry-run
28250
- baker videos tags
28251
- Full guide: __tooling__/docs/tools/baker/videos.md`
28539
+ baker videos tags`
28252
28540
  },
28253
28541
  subCommands: {
28254
28542
  get: getCommand5,
@@ -28260,10 +28548,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
28260
28548
  });
28261
28549
 
28262
28550
  // src/commands/winning-ads/index.ts
28263
- import { defineCommand as defineCommand174 } from "citty";
28551
+ import { defineCommand as defineCommand178 } from "citty";
28264
28552
 
28265
28553
  // src/commands/winning-ads/advertisers.ts
28266
- import { defineCommand as defineCommand163 } from "citty";
28554
+ import { defineCommand as defineCommand167 } from "citty";
28267
28555
 
28268
28556
  // src/commands/winning-ads/shared.ts
28269
28557
  function splitList(value) {
@@ -28316,7 +28604,7 @@ function advertiserNormalizer(record, full) {
28316
28604
  last_synced_at: record.last_synced_at ?? null
28317
28605
  };
28318
28606
  }
28319
- var advertisersCommand2 = defineCommand163({
28607
+ var advertisersCommand2 = defineCommand167({
28320
28608
  meta: {
28321
28609
  name: "advertisers",
28322
28610
  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'
@@ -28374,7 +28662,7 @@ var advertisersCommand2 = defineCommand163({
28374
28662
  });
28375
28663
 
28376
28664
  // src/commands/winning-ads/brief.ts
28377
- import { defineCommand as defineCommand164 } from "citty";
28665
+ import { defineCommand as defineCommand168 } from "citty";
28378
28666
  registerSchema({
28379
28667
  command: "winning-ads.brief",
28380
28668
  description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
@@ -28420,7 +28708,7 @@ function parseDna(raw) {
28420
28708
  }
28421
28709
  return parsed;
28422
28710
  }
28423
- var briefCommand = defineCommand164({
28711
+ var briefCommand = defineCommand168({
28424
28712
  meta: {
28425
28713
  name: "brief",
28426
28714
  description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
@@ -28456,7 +28744,7 @@ var briefCommand = defineCommand164({
28456
28744
  });
28457
28745
 
28458
28746
  // src/commands/winning-ads/feed.ts
28459
- import { defineCommand as defineCommand165 } from "citty";
28747
+ import { defineCommand as defineCommand169 } from "citty";
28460
28748
  function buildFeedParams(input) {
28461
28749
  const params = {};
28462
28750
  const advertiser = splitList(input.advertiser);
@@ -28508,7 +28796,7 @@ registerSchema({
28508
28796
  format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
28509
28797
  }
28510
28798
  });
28511
- var feedCommand = defineCommand165({
28799
+ var feedCommand = defineCommand169({
28512
28800
  meta: {
28513
28801
  name: "feed",
28514
28802
  description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
@@ -28593,7 +28881,7 @@ var feedCommand = defineCommand165({
28593
28881
  });
28594
28882
 
28595
28883
  // src/commands/winning-ads/follow.ts
28596
- import { defineCommand as defineCommand166 } from "citty";
28884
+ import { defineCommand as defineCommand170 } from "citty";
28597
28885
  var PLATFORMS = ["meta", "linkedin"];
28598
28886
  registerSchema({
28599
28887
  command: "winning-ads.follow",
@@ -28608,7 +28896,7 @@ registerSchema({
28608
28896
  label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
28609
28897
  }
28610
28898
  });
28611
- var followCommand = defineCommand166({
28899
+ var followCommand = defineCommand170({
28612
28900
  meta: {
28613
28901
  name: "follow",
28614
28902
  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'
@@ -28655,7 +28943,7 @@ var followCommand = defineCommand166({
28655
28943
  });
28656
28944
 
28657
28945
  // src/commands/winning-ads/follow-competitors.ts
28658
- import { defineCommand as defineCommand167 } from "citty";
28946
+ import { defineCommand as defineCommand171 } from "citty";
28659
28947
  var PLATFORMS2 = ["meta", "linkedin"];
28660
28948
  var BATCH_TIMEOUT_MS = 3e5;
28661
28949
  function buildFollowBatchBody(input) {
@@ -28688,7 +28976,7 @@ registerSchema({
28688
28976
  }
28689
28977
  }
28690
28978
  });
28691
- var followCompetitorsCommand = defineCommand167({
28979
+ var followCompetitorsCommand = defineCommand171({
28692
28980
  meta: {
28693
28981
  name: "follow-competitors",
28694
28982
  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"'
@@ -28763,7 +29051,7 @@ var followCompetitorsCommand = defineCommand167({
28763
29051
  });
28764
29052
 
28765
29053
  // src/commands/winning-ads/following.ts
28766
- import { defineCommand as defineCommand168 } from "citty";
29054
+ import { defineCommand as defineCommand172 } from "citty";
28767
29055
  registerSchema({
28768
29056
  command: "winning-ads.following",
28769
29057
  description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
@@ -28796,7 +29084,7 @@ function followingNormalizer(record, full) {
28796
29084
  platforms: Array.isArray(record.platforms) ? record.platforms : []
28797
29085
  };
28798
29086
  }
28799
- var followingCommand = defineCommand168({
29087
+ var followingCommand = defineCommand172({
28800
29088
  meta: {
28801
29089
  name: "following",
28802
29090
  description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
@@ -28831,7 +29119,7 @@ var followingCommand = defineCommand168({
28831
29119
  });
28832
29120
 
28833
29121
  // src/commands/winning-ads/patterns.ts
28834
- import { defineCommand as defineCommand169 } from "citty";
29122
+ import { defineCommand as defineCommand173 } from "citty";
28835
29123
  registerSchema({
28836
29124
  command: "winning-ads.patterns",
28837
29125
  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.",
@@ -28870,7 +29158,7 @@ function discriminatorRow(record) {
28870
29158
  top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
28871
29159
  };
28872
29160
  }
28873
- var patternsCommand = defineCommand169({
29161
+ var patternsCommand = defineCommand173({
28874
29162
  meta: {
28875
29163
  name: "patterns",
28876
29164
  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"
@@ -28926,7 +29214,7 @@ var patternsCommand = defineCommand169({
28926
29214
  });
28927
29215
 
28928
29216
  // src/commands/winning-ads/search.ts
28929
- import { defineCommand as defineCommand170 } from "citty";
29217
+ import { defineCommand as defineCommand174 } from "citty";
28930
29218
  registerSchema({
28931
29219
  command: "winning-ads.search",
28932
29220
  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.",
@@ -29034,7 +29322,7 @@ function buildSearchBody(args) {
29034
29322
  }
29035
29323
  return body;
29036
29324
  }
29037
- var searchCommand4 = defineCommand170({
29325
+ var searchCommand4 = defineCommand174({
29038
29326
  meta: {
29039
29327
  name: "search",
29040
29328
  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"
@@ -29149,7 +29437,7 @@ var searchCommand4 = defineCommand170({
29149
29437
  });
29150
29438
 
29151
29439
  // src/commands/winning-ads/seeds.ts
29152
- import { defineCommand as defineCommand171 } from "citty";
29440
+ import { defineCommand as defineCommand175 } from "citty";
29153
29441
  function leanRow(r) {
29154
29442
  return {
29155
29443
  key: r.key,
@@ -29177,7 +29465,7 @@ function makeSeedCommand(opts) {
29177
29465
  limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
29178
29466
  }
29179
29467
  });
29180
- return defineCommand171({
29468
+ return defineCommand175({
29181
29469
  meta: { name: opts.name, description: opts.description },
29182
29470
  args: {
29183
29471
  platform: { type: "string", description: "Single platform to segment on", required: false },
@@ -29226,7 +29514,7 @@ var formatsCommand = makeSeedCommand({
29226
29514
  });
29227
29515
 
29228
29516
  // src/commands/winning-ads/unfollow.ts
29229
- import { defineCommand as defineCommand172 } from "citty";
29517
+ import { defineCommand as defineCommand176 } from "citty";
29230
29518
  registerSchema({
29231
29519
  command: "winning-ads.unfollow",
29232
29520
  description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
@@ -29234,7 +29522,7 @@ registerSchema({
29234
29522
  advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
29235
29523
  }
29236
29524
  });
29237
- var unfollowCommand = defineCommand172({
29525
+ var unfollowCommand = defineCommand176({
29238
29526
  meta: {
29239
29527
  name: "unfollow",
29240
29528
  description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
@@ -29255,7 +29543,7 @@ var unfollowCommand = defineCommand172({
29255
29543
  });
29256
29544
 
29257
29545
  // src/commands/winning-ads/winners.ts
29258
- import { defineCommand as defineCommand173 } from "citty";
29546
+ import { defineCommand as defineCommand177 } from "citty";
29259
29547
  registerSchema({
29260
29548
  command: "winning-ads.winners",
29261
29549
  description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
@@ -29265,7 +29553,7 @@ registerSchema({
29265
29553
  platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
29266
29554
  }
29267
29555
  });
29268
- var winnersCommand = defineCommand173({
29556
+ var winnersCommand = defineCommand177({
29269
29557
  meta: {
29270
29558
  name: "winners",
29271
29559
  description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
@@ -29315,7 +29603,7 @@ var winnersCommand = defineCommand173({
29315
29603
  });
29316
29604
 
29317
29605
  // src/commands/winning-ads/index.ts
29318
- var winningAdsCommand = defineCommand174({
29606
+ var winningAdsCommand = defineCommand178({
29319
29607
  meta: {
29320
29608
  name: "winning-ads",
29321
29609
  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.
@@ -29347,8 +29635,7 @@ Examples:
29347
29635
  baker winning-ads winners adv_123 --top 15 --output md
29348
29636
  baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
29349
29637
  baker winning-ads search "fintech onboarding" --hook-archetype callout --winner-category winner --output md
29350
- baker winning-ads patterns --winners a_1,a_2 --duds a_9,a_8 --output md
29351
- Full guide: __tooling__/docs/tools/baker/winning-ads.md`
29638
+ baker winning-ads patterns --winners a_1,a_2 --duds a_9,a_8 --output md`
29352
29639
  },
29353
29640
  subCommands: {
29354
29641
  search: searchCommand4,
@@ -29368,7 +29655,7 @@ Full guide: __tooling__/docs/tools/baker/winning-ads.md`
29368
29655
  });
29369
29656
 
29370
29657
  // src/version.ts
29371
- import { readFileSync as readFileSync12 } from "fs";
29658
+ import { readFileSync as readFileSync13 } from "fs";
29372
29659
  function packageJsonUrl() {
29373
29660
  return new URL("../package.json", import.meta.url);
29374
29661
  }
@@ -29380,15 +29667,15 @@ function parsePackageVersion(raw) {
29380
29667
  throw new Error("Invalid CLI package.json: missing version");
29381
29668
  }
29382
29669
  function getCliVersion() {
29383
- return parsePackageVersion(readFileSync12(packageJsonUrl(), "utf8"));
29670
+ return parsePackageVersion(readFileSync13(packageJsonUrl(), "utf8"));
29384
29671
  }
29385
29672
 
29386
29673
  // src/cli.ts
29387
- var main = defineCommand175({
29674
+ var main = defineCommand179({
29388
29675
  meta: {
29389
29676
  name: "baker",
29390
29677
  version: getCliVersion(),
29391
- 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.
29678
+ 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.
29392
29679
 
29393
29680
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
29394
29681
  Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
@@ -29410,6 +29697,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
29410
29697
  testimonials: testimonialsCommand,
29411
29698
  canvas: canvasCommand,
29412
29699
  tags: tagsCommand3,
29700
+ "tag-manager": tagManagerCommand,
29413
29701
  chats: chatsCommand,
29414
29702
  history: historyCommand,
29415
29703
  "winning-ads": winningAdsCommand,