@koda-sl/baker-cli 0.383.0-dev.2caa8a15e → 0.384.0-dev.4699b7308

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 CHANGED
@@ -892,7 +892,7 @@ baker ads meta insights --object act_123 --level adset \
892
892
  baker ads meta activities --account-id act_123 --days 7
893
893
 
894
894
  # "Which Page should this ad run from?"
895
- baker ads meta pages # Facebook Pages the selected ad accounts can promote
895
+ baker ads meta pages # Facebook Pages the user manages (tasks shows which can ADVERTISE)
896
896
 
897
897
  # "What is the lead form collecting, and how many came in?"
898
898
  baker ads meta lead-forms --page-id 100635183117758 # instant forms on a Page + lead counts
@@ -3409,7 +3409,7 @@ baker scheduled-agents templates --delete weekly-posthog-check
3409
3409
 
3410
3410
  ### Marketing Tags (`baker tags`)
3411
3411
 
3412
- Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, PostHog, …) — production tags overlaid with the changes staged in this chat.
3412
+ Read the client's marketing/analytics tags (Meta pixel, ChatGPT Ads pixel, GA4, Google Ads, GTM, Clarity, Hotjar, PostHog, …) — production tags overlaid with the changes staged in this chat.
3413
3413
 
3414
3414
  **The CLI is read-only.** Every tag change (create, edit, delete) goes through the `request_tag_input` tool (`baker_ui` MCP server): the agent proposes one or more changes — each becomes a tab in one blocking approval form — pre-filling the non-secret fields it knows; the user reviews, edits, fills secret fields, and approves or skips each tab. Approved changes stage on the chat and apply when the chat is published; discarding the chat drops them.
3415
3415
 
@@ -3425,6 +3425,7 @@ Notes:
3425
3425
  - **Both reads restate the write path, on stderr.** `list` and `draft` end with the two lines that say the approval form is the only way to change a tag, that it rides on every turn, and that a tag change is never a Task. They are there because a chat concluded from its tool list alone that the form did not exist, never called it, and filed the change as a Task for the user to carry out by hand. stdout stays the list, so piping it is unaffected; `--json` carries the same lines in the envelope's `hints`.
3426
3426
  - **`list` prints each tag's full readable config.** Every non-secret field is shown in full under the tag — the Clarity `projectId`, GA4 `measurementId`, the entire custom `code` snippet, etc. — so the agent reuses a stored value to pre-fill a follow-up change instead of asking the user for something already installed. Secrets are never among these fields. (`--json` emits the same data as the raw envelope.)
3427
3427
  - **Secrets never travel through this CLI or the chat.** Secret fields (`accessToken`, `apiSecret`, `authorizationToken`, `apiKey`, `conversionToken`, `oauthProviderId`) are entered only in the dashboard's secure tag form and flow straight into the staged draft; tool responses only ever name which secret fields are set/pending.
3428
+ - A `chatgptAds` tag takes a Pixel ID. Its optional `apiKey` is the Conversions API key and enables the server copy of page and Form events; the key stays out of the CLI and published page.
3428
3429
  - Staged creates get a server-generated `tag_temp_*` ref (returned in the tool result and printed by `list`). Use it (or a real tag id) as flow side-effect `tagIds` — the published tag keeps resolving under the temp ref.
3429
3430
  - Proposing a delete on a `tag_temp_*` ref drops the staged create instead.
3430
3431
  - Single-instance types (`code`, `posthog`, `datafast`) reject a second instance against the chat's effective view.
@@ -3434,6 +3435,8 @@ Notes:
3434
3435
 
3435
3436
  Read and shape this workspace's Forms (flows). Operates on the local `_data.json` files only; no secret values are ever decrypted or printed.
3436
3437
 
3438
+ For ChatGPT Ads conversions, add a `chatgptAds` side effect to the Form step, choose a supported event name, and use `baker flows map` to map `advancedMatching` and optional `eventParams` (`value` and `currency`).
3439
+
3437
3440
  **A Form has two halves, split by a trust boundary.** Its *structure* — steps, conditions, side effects, field mappings — is yours, and the write subcommands below edit exactly that. Its *confidential* half — connection secrets, OAuth accounts, third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal) — is configured through the `request_flow_input` tool (`baker_ui` MCP server): the agent authors the surrounding structure and references it by `nodeId`/`sideEffectId`, and the user enters secrets, connects accounts, and picks resources in the dashboard. Those values are written (encrypted, where a secret) into the Form on the chat's branch and go live when the chat is published. Nothing any of these commands does touches a live system.
3438
3441
 
3439
3442
  ```bash
package/dist/cli.js CHANGED
@@ -299,7 +299,6 @@ var chatActionDraftOpViewSchema = z.object({
299
299
  targetActionId: z.string().optional(),
300
300
  tempId: z.string().optional(),
301
301
  tags: z.array(z.string()).optional(),
302
- priority: actionPrioritySchema.nullable().optional(),
303
302
  reason: z.string().optional(),
304
303
  note: z.string().optional(),
305
304
  name: z.string().optional(),
@@ -5124,6 +5123,16 @@ var FLOW_SIDE_EFFECT_CATALOG = [
5124
5123
  },
5125
5124
  "`advancedMatching` is how Meta re-identifies the visitor, and it is the difference between a matched conversion and a discarded one. Fill at least `em` and `ph` from the form: `baker flows map <slug> --map em=email --map ph=phone`."
5126
5125
  ),
5126
+ eventSideEffect(
5127
+ "chatgptAds",
5128
+ "Fires a ChatGPT Ads pixel conversion and mirrors it through the Conversions API when a key is configured.",
5129
+ {
5130
+ eventType: "standard",
5131
+ eventParams: [],
5132
+ advancedMatching: matchingSlots("em", "ph", "fn", "ln", "external_id", "ct", "st", "zp", "country")
5133
+ },
5134
+ "Use ChatGPT Ads event names such as lead_created, order_created or appointment_scheduled. For a custom event use a lowercase name of 1\u201364 letters, digits, underscores or dashes. Only value (major currency units) and currency are supported in eventParams. Map em from the form to improve conversion matching."
5135
+ ),
5127
5136
  eventSideEffect("googleAnalytics", "Fires a GA4 event.", { eventType: "custom", eventParams: [] }),
5128
5137
  {
5129
5138
  kind: "side-effect",
@@ -8036,6 +8045,7 @@ var studioImproveResponseSchema = z27.object({ prompt: z27.string(), original: z
8036
8045
  import { z as z28 } from "zod";
8037
8046
  var TAG_TYPES = [
8038
8047
  "meta",
8048
+ "chatgptAds",
8039
8049
  "amplitude",
8040
8050
  "googleAds",
8041
8051
  "tiktok",
@@ -8057,6 +8067,7 @@ var TAG_TYPES = [
8057
8067
  var tagTypeSchema = z28.enum(TAG_TYPES);
8058
8068
  var TAG_IDENTIFYING_FIELD = {
8059
8069
  meta: "pixelId",
8070
+ chatgptAds: "pixelId",
8060
8071
  googleAds: "conversionID",
8061
8072
  tiktok: "pixelCode",
8062
8073
  pinterest: "tagId",
@@ -15027,7 +15038,14 @@ function parseEventKey(key) {
15027
15038
  }
15028
15039
 
15029
15040
  // ../api/src/analytics/sends.ts
15030
- var SEND_PLATFORMS = ["meta", "googleAds", "linkedinInsightTag", "twitterAds", "googleAnalytics"];
15041
+ var SEND_PLATFORMS = [
15042
+ "meta",
15043
+ "chatgptAds",
15044
+ "googleAds",
15045
+ "linkedinInsightTag",
15046
+ "twitterAds",
15047
+ "googleAnalytics"
15048
+ ];
15031
15049
  function isSendPlatform(value) {
15032
15050
  return SEND_PLATFORMS.includes(value);
15033
15051
  }
@@ -15039,6 +15057,13 @@ var SEND_PLATFORM_SPECS = {
15039
15057
  credentialFields: ["accessToken"],
15040
15058
  setupHint: "Add the Conversions API access token to the Meta pixel in Tracking"
15041
15059
  },
15060
+ chatgptAds: {
15061
+ title: "ChatGPT Ads",
15062
+ eventMeans: "A ChatGPT Ads event \u2014 lead_created, order_created, or a custom name",
15063
+ eventKind: "name",
15064
+ credentialFields: ["apiKey"],
15065
+ setupHint: "Add the Conversions API key to the ChatGPT Ads pixel in Tracking"
15066
+ },
15042
15067
  googleAds: {
15043
15068
  title: "Google Ads",
15044
15069
  eventMeans: "One of the account's conversion actions, picked from its list",
@@ -15089,6 +15114,7 @@ function isConversionSend(type) {
15089
15114
  }
15090
15115
  var SERVER_SIDE_SENDER_TAG = {
15091
15116
  metaCapi: "meta",
15117
+ chatgptAdsCapi: "chatgptAds",
15092
15118
  googleAdsCapi: "googleAds",
15093
15119
  linkedinCapi: "linkedinInsightTag",
15094
15120
  twitterAdsCapi: "twitterAds",
@@ -28398,10 +28424,19 @@ var metaMediaCommand = defineCommand68({
28398
28424
 
28399
28425
  // src/commands/ads/meta/pages.ts
28400
28426
  import { defineCommand as defineCommand69 } from "citty";
28427
+ function advertisablePages(data) {
28428
+ return data.filter((p) => Array.isArray(p.tasks) && p.tasks.includes("ADVERTISE"));
28429
+ }
28401
28430
  function pageSelectionHints(data) {
28402
- if (data.length > 1) {
28431
+ const advertisable = advertisablePages(data);
28432
+ if (advertisable.length > 1) {
28433
+ return [
28434
+ "MULTIPLE Pages can run ads \u2014 do NOT guess. Confirm with the user which Page an ad should run from before passing --page to `creatives create`; a wrong Page publishes the ad under the wrong brand identity and staging will not catch it."
28435
+ ];
28436
+ }
28437
+ if (data.length > 0 && advertisable.length === 0) {
28403
28438
  return [
28404
- "MULTIPLE Pages can run ads from the selected Meta ad accounts \u2014 do NOT guess. Confirm with the user which Page an ad should run from before passing --page to `creatives create`; a wrong Page publishes the ad under the wrong brand identity and staging will not catch it."
28439
+ "NO Page can run ads \u2014 none of the connected user's Pages carry the ADVERTISE task. Ask the user to grant Advertise access to the right Page before creating an ad; a readable-but-non-advertising Page still passes staging and would fail or run under the wrong identity."
28405
28440
  ];
28406
28441
  }
28407
28442
  return [];
@@ -28409,7 +28444,7 @@ function pageSelectionHints(data) {
28409
28444
  var pagesCommand = defineCommand69({
28410
28445
  meta: {
28411
28446
  name: "pages",
28412
- description: `List the Facebook Pages that the selected Meta ad accounts can promote. Every Meta ad publishes from a Page, so use this to identify the Page an ad should run from. If more than one Page is listed, confirm with the user which Page to use \u2014 a wrong Page publishes under the wrong brand identity.
28447
+ description: `List the Facebook Pages the connected user manages. Every Meta ad publishes from a Page, so use this to identify the Page an ad should run from. The 'tasks' field shows what the user can do on each Page (ADVERTISE means it can back ads). If exactly one Page can ADVERTISE, use it; if more than one can, confirm with the user which Page to use; if none can, ask the user to grant Advertise access \u2014 a wrong or non-advertising Page publishes under the wrong brand identity.
28413
28448
 
28414
28449
  Examples:
28415
28450
  baker ads meta pages`
@@ -28670,7 +28705,7 @@ Discovery:
28670
28705
  baker ads meta accounts \u2014 accounts in this company's connected scope
28671
28706
  baker ads meta accounts --include-all \u2014 every account the token can see
28672
28707
  baker ads meta businesses \u2014 Business Manager IDs
28673
- baker ads meta pages \u2014 Facebook Pages the selected ad accounts can promote (an ad's identity)
28708
+ baker ads meta pages \u2014 Facebook Pages the user manages (an ad's identity)
28674
28709
  baker ads meta lead-forms --page-id 100635183117758 \u2014 instant (lead) forms on a Page, with lead counts
28675
28710
  baker ads meta leads --form-id 987654321 \u2014 the leads one form collected (contact details masked)
28676
28711
 
@@ -49560,6 +49595,14 @@ var MAPPING_SLOTS = {
49560
49595
  code: [PAYLOAD("eventProperties")],
49561
49596
  datafast: [PAYLOAD("goalParams")],
49562
49597
  meta: [PAYLOAD("eventParams"), { kind: "record", key: "advancedMatching", allowed: META_MATCHING }],
49598
+ chatgptAds: [
49599
+ PAYLOAD("eventParams"),
49600
+ {
49601
+ kind: "record",
49602
+ key: "advancedMatching",
49603
+ allowed: ["em", "ph", "fn", "ln", "external_id", "ct", "st", "zp", "country"]
49604
+ }
49605
+ ],
49563
49606
  tiktok: [
49564
49607
  PAYLOAD("eventParams"),
49565
49608
  { kind: "record", key: "identify", allowed: ["email", "phone_number", "external_id"] }