@koda-sl/baker-cli 0.173.0-dev.6ecd65d29 → 0.173.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/dist/{chunk-K424D3CY.js → chunk-CG6OTNUU.js} +4 -4
- package/dist/chunk-CG6OTNUU.js.map +1 -0
- package/dist/cli.js +111 -30
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-K424D3CY.js.map +0 -1
package/README.md
CHANGED
|
@@ -563,6 +563,13 @@ baker ads google asset-groups create --customer-id 1234567890 --campaign-ref g_t
|
|
|
563
563
|
--descriptions "Best widgets around.,Ships tomorrow." --business-name "Acme" --final-urls https://example.com
|
|
564
564
|
baker ads google asset-groups update g_temp_<assetgroup> --status ENABLED
|
|
565
565
|
|
|
566
|
+
# Refresh a LIVE asset group's creatives — attach the replacement first, then detach the old one
|
|
567
|
+
baker ads google assets create --customer-id 1234567890 --file new-image-asset.json # -> g_temp_<img>
|
|
568
|
+
baker ads google asset-groups attach --customer-id 1234567890 \
|
|
569
|
+
--asset-group-ref 6718302454 --asset-ref g_temp_<img> --field-type PORTRAIT_MARKETING_IMAGE
|
|
570
|
+
baker ads google asset-groups detach customers/1234567890/assetGroupAssets/6718302454~402654762568~PORTRAIT_MARKETING_IMAGE \
|
|
571
|
+
--customer-id 1234567890
|
|
572
|
+
|
|
566
573
|
# Review / undo / amend staged changes
|
|
567
574
|
baker ads google draft list # readable campaign ▸ ad group ▸ ad tree + completeness advisories
|
|
568
575
|
baker ads google draft list --json # raw JSON envelope for scripting
|
|
@@ -572,7 +579,7 @@ baker ads google draft remove g_temp_ab12 # cascades to dependents
|
|
|
572
579
|
baker ads google draft clear
|
|
573
580
|
```
|
|
574
581
|
|
|
575
|
-
Command groups: `budgets`, `campaigns`, `ad-groups`, `keywords` (add/update/remove), `negative-keywords`, `keyword-lists`, `ads`, `assets` (create/update/attach/detach), `asset-groups` (create/update — Performance Max), `audiences`, `conversions` (create/update/goal), `bidding-strategies`, `labels`, `campaign-criteria`, and `draft`. Amounts are in major currency units (converted to micros). Money/bids: `--amount`, `--cpc-bid`, `--target-cpa`, `--max-cpc` take major units; `--target-roas` a ratio. `--max-cpc` sets the max CPC bid ceiling for `TARGET_IMPRESSION_SHARE` / `TARGET_SPEND` / `PERCENT_CPC` and must be paired with `--bidding-strategy`. Less-common ops accept a `--file <payload.json>` (flags override file keys). Updates target a resource name or bare id as the positional argument; a target that names an op staged earlier **amends it in place**.
|
|
582
|
+
Command groups: `budgets`, `campaigns`, `ad-groups`, `keywords` (add/update/remove), `negative-keywords`, `keyword-lists`, `ads`, `assets` (create/update/attach/detach), `asset-groups` (create/update/attach/detach — Performance Max), `audiences`, `conversions` (create/update/goal), `bidding-strategies`, `labels`, `campaign-criteria`, and `draft`. Amounts are in major currency units (converted to micros). Money/bids: `--amount`, `--cpc-bid`, `--target-cpa`, `--max-cpc` take major units; `--target-roas` a ratio. `--max-cpc` sets the max CPC bid ceiling for `TARGET_IMPRESSION_SHARE` / `TARGET_SPEND` / `PERCENT_CPC` and must be paired with `--bidding-strategy`. Less-common ops accept a `--file <payload.json>` (flags override file keys). Updates target a resource name or bare id as the positional argument; a target that names an op staged earlier **amends it in place**.
|
|
576
583
|
|
|
577
584
|
**Primary vs secondary conversion actions** — `conversions update <id> --primary` makes an action a primary action (automated bidding optimizes toward it); `--no-primary` (or `--primary=false`) demotes it to secondary (reported only) — the spaced form `--primary false` is rejected, since a boolean flag written with a space is set to true and the word dropped. `conversions create` stages a new action as **secondary** unless its `--file` payload sets `"primaryForGoal": true`, so a new action never silently joins the bidding target of a Maximize Conversions or Target CPA campaign. The staged card shows an "Action optimization" row with the before/after role.
|
|
578
585
|
|
|
@@ -2754,7 +2761,7 @@ baker hubspot meetings view <slug> --as-node # the form.external blob for a f
|
|
|
2754
2761
|
**`workflows list` flags:** `--search <text>`, `--enabled-only`. Disabled workflows are listed too — a form wired to one that is off looks connected and does nothing.
|
|
2755
2762
|
**`pipelines list`:** no flags; stages come back in the order they run in HubSpot.
|
|
2756
2763
|
**`contacts summary` flags:** `--days <1-365>` (default 30) over contact creation date. Returns counts only — total contacts, how many have an owner, and the lifecycle-stage split — never a name or an email. `truncated: true` means the page budget ran out, so the counts are floors.
|
|
2757
|
-
**`contacts lookup`:** positional `<email>`; returns that contact's lifecycle stage, owner, the account (company) it was filed under, and associated deals with their stage. `companyReadable: false`
|
|
2764
|
+
**`contacts lookup`:** positional `<email>`; returns that contact's lifecycle stage, owner, the account (company) it was filed under, and associated deals with their stage. `dealsReadable: false` / `companyReadable: false` mean the connection does not cover deals or accounts, so an empty `deals` or a null `company` is unknown rather than absent. `found: false` means no contact with that email — the lead never reached the CRM, which is a finding rather than an error.
|
|
2758
2765
|
**`meetings list` flags:** `--search <text>`, `--redirecting-only`.
|
|
2759
2766
|
**`meetings view`:** positional `<slug>` — the only reliable source for a calendar's booking fields (HubSpot omits `customParams` from the list endpoint, so `fieldCount: null` there means unknown, not zero); `--as-node` as above.
|
|
2760
2767
|
|
|
@@ -4913,6 +4920,10 @@ This CLI is designed for AI agent consumption. Key patterns:
|
|
|
4913
4920
|
|
|
4914
4921
|
- **0.168.0**: `baker ads google conversions goal` sets the **account-level** conversion goal (`CustomerConversionGoal`) — Google Ads' "Included in account-level goals" column, keyed by `(category, origin)`. `goal --category PURCHASE --origin WEBSITE --biddable` includes a conversion category in what the account bids toward; `--no-biddable` measures it only. This is the half the surface was missing: a conversion drives automated bidding only when BOTH its action is primary AND its category's account-level goal is biddable, which is why an account could show lead-form conversions as Primary and still bid toward nothing. Promoting an action whose goal is off now stages with a warning saying the promotion alone changes no spend, and names the command for the other half. One staged op per pair — a second op for the same `(category, origin)` is refused rather than silently overwriting the first at publish. Switching off the last goal that still has a primary action behind it is refused like a last demotion, and the "no primary left" guard now discounts actions whose goal is already off (they were never steering bidding), while still treating an unread goal as bidding. A goal staged against an account that does not own conversion tracking is refused up front with the id that does, instead of failing the whole atomic batch at publish. The staged card gains "Included in account-level goals", "Conversion category" and "Where it happens" rows.
|
|
4915
4922
|
|
|
4923
|
+
- **0.170.0**: `baker ads google asset-groups attach|detach` — link and unlink one asset on a Performance Max asset group that **already exists**, which is what refreshing a live group's creatives actually is. Until now nothing could do it: `asset-groups create` links a group's opening assets inline, `asset-groups update` takes only `--name --final-urls --status`, and `assets attach` reaches campaign/adGroup/customer but not an asset group — so replacing a low-performing PMax image had no route through Baker at all and ended in the Google Ads interface. `create` also gains `--portrait-image-assets`; the 4:5 slot was missing from the asset group contract entirely, so a portrait image could not be staged even at creation. Ordering is the agent's job and is now stated everywhere it matters: operations publish in **stage order**, Google Ads removals carry no dependency edge and are not reordered to run last (`docs/publishing.md` → Known gap), so a detach staged before its replacement reaches Google first and is rejected when it was the last asset of that ratio — attach first, always.
|
|
4924
|
+
|
|
4925
|
+
Shipped with it: **staging a second removal of the same shape silently did nothing.** Amend-matching reduced any composite ref to the segment after its last `~` — built for the two-segment `adGroupId~adId` refs that ad and keyword targets heal to, where that segment really is the entity's own id. It is not, in three other places: an asset-group asset (`{assetGroup}~{asset}~{FIELD_TYPE}`) and a customer-level asset link (`{asset}~{FIELD_TYPE}`) both end in a field type every asset of that ratio shares, and a campaign shared set (`{campaign}~{sharedSet}`) ends in the list's id, the same in every campaign it is attached to. So the second detach amended the first instead of staging, returned the first's ref and reported success: a PMax creative swap could only ever remove one image per ratio, and detaching one negative list from three campaigns removed it from one. Nothing in the output said the rest had been dropped. Refs now compare whole, with one one-sided exception — a **bare** id still collapses onto the two-segment composite whose child it names, which is the only case the reduction ever existed for. The duplicate copy of the same helper in the staging path is gone rather than fixed twice. Also: linking an asset Google created automatically is refused at stage time on an asset group, not just on a campaign/ad-group/customer link — a Performance Max group is where auto-created creative is most likely to be picked up. And the live-context resolver now reads the asset group and asset an attach/detach names, so the review of a swap shows names and the images themselves rather than the ids inside a resource name.
|
|
4926
|
+
|
|
4916
4927
|
- **0.169.0**: `baker capabilities` — one call, before any platform work, that answers what Baker **cannot** do. Everything else (`baker schema`, the family docs, `--help`) describes what it can, so the only way to learn a capability was absent was to try it, usually after telling the user it would happen. Per surface (`google-ads`, `meta-ads`, `linkedin-ads`, `x-ads`, `tag-manager`, `ga4`, `gsc`) it reports: what is connected and which accounts/properties/containers were picked; whether writes are **live** or **simulated** for this company, and that Tag Manager has neither mode — completing the chat changes the real container; and a `limits` list separating *not built yet* from *the platform forbids it* from *we hold no permission for it*, because each leads to something different to tell the user. Naming one surface (`baker capabilities google-ads`) also returns `ops`: every change with its required and optional fields and the exact values each accepts — so "is there a field to demote a conversion action, and how is it spelled?" is one call instead of four guesses. Almost everything is derived rather than written down: the accounts and permissions come from the connection, the write mode from the company's gate, the writable entities and field contracts from the same schemas the backend parses with, and read-only vs read-write from the OAuth scopes the app actually requests (which is why "GA4 is read-only" is a fact, not a sentence). The handful of hand-written entries each carry a machine-checkable claim about the code behind them, and a coverage test fails when one stops holding. A rejected staged write on Google, Meta or LinkedIn now points at this command instead of leaving the agent to guess another field name.
|
|
4917
4928
|
|
|
4918
4929
|
## Publishing
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
__toESM
|
|
8
8
|
} from "./chunk-RK67WL4O.js";
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
|
|
11
11
|
var require_safe_stable_stringify = __commonJS({
|
|
12
|
-
"
|
|
12
|
+
"../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
|
|
13
13
|
"use strict";
|
|
14
14
|
var { hasOwnProperty } = Object.prototype;
|
|
15
15
|
var stringify = configure2();
|
|
@@ -1075,7 +1075,7 @@ function resolveAdaptFormats(params) {
|
|
|
1075
1075
|
return params.formats ?? [];
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
|
-
//
|
|
1078
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
1079
1079
|
var import__ = __toESM(require_safe_stable_stringify(), 1);
|
|
1080
1080
|
var configure = import__.default.configure;
|
|
1081
1081
|
var wrapper_default = import__.default;
|
|
@@ -8028,4 +8028,4 @@ export {
|
|
|
8028
8028
|
defaultRegistry,
|
|
8029
8029
|
createEngineFromEnv
|
|
8030
8030
|
};
|
|
8031
|
-
//# sourceMappingURL=chunk-
|
|
8031
|
+
//# sourceMappingURL=chunk-CG6OTNUU.js.map
|