@koda-sl/baker-cli 0.104.0 → 0.106.0-dev.a605c0acb

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
@@ -870,7 +870,7 @@ LinkedIn Marketing API for B2B ad insights. Connect via OAuth in the dashboard,
870
870
 
871
871
  **LinkedIn's superpower over Meta/Google:** firmographic pivots on every analytics query — `pivot=job-title|company|industry|seniority|function|company-size`. Meta has nothing like `MEMBER_COMPANY` returning company URNs of every account whose employees saw the ad. AI agents should reach for `linkedin demographics` and `linkedin top-companies` first when answering ABM/persona questions.
872
872
 
873
- **Read-only v1.** No campaign/creative writes. The surface is curated for AI agents per the LinkedIn Ads playbook (B2B operating manual covering audits, ABM, attribution, scaling).
873
+ **Reads + staged writes.** The read surface is curated for AI agents per the LinkedIn Ads playbook (B2B operating manual covering audits, ABM, attribution, scaling). Write commands (campaign groups, campaigns, creatives, audiences, conversions, lead forms) are **staged**: they never hit the LinkedIn API when you run them — each op is fully validated at stage time, shows in the dashboard chat as a pending LinkedIn change, and applies only when the chat is published. See [Staged writes](#staged-writes) below.
874
874
 
875
875
  #### Common AI questions, mapped to commands
876
876
 
@@ -967,8 +967,58 @@ conversions health # 5-point Insight Tag / CAPI health check (playbo
967
967
 
968
968
  audit # 30+ playbook checks → severity-tagged findings
969
969
  audit --format md # deliverable-ready markdown table
970
+
971
+ campaign-groups create|update|pause|resume|duplicate # staged writes (see below)
972
+ campaigns create|update|pause|resume|archive|duplicate
973
+ creatives create|update|pause|resume|duplicate
974
+ audiences create|upload
975
+ conversions create|update
976
+ lead-forms create|update
977
+ draft [remove <ref> | clear] # review/undo staged write ops
978
+ ```
979
+
980
+ #### Staged writes
981
+
982
+ Write commands never call the LinkedIn API at stage time. Each stages an op on the current chat's draft, fully validated at staging (field limits, enums, budget minimums, URN shapes, parent existence, Baker media readiness, status-transition legality). Validation errors are structured per-field; non-blocking warnings (Maximum Delivery when no `--bid`, budget below playbook floor, audience under 300 rows, >4 lead-form questions, audience expansion/LAN on) come back in the stage envelope. Ops apply when the chat is published.
983
+
984
+ If the company's LinkedIn-write flag is off (the default), publish runs the identical lifecycle **simulated** — fake `urn:li:simulated:*` results, zero LinkedIn calls. The stage response and `baker ads linkedin draft` show `mode: "simulated"`.
985
+
986
+ ```bash
987
+ # Chain creates via li_temp_* refs — group → campaign → creative in one chat
988
+ baker ads linkedin campaign-groups create --name "Q3 ABM" --total-budget 5000 --currency EUR # → li_temp_x1
989
+ baker ads linkedin campaigns create --name "ABM Tier-1" --group li_temp_x1 \
990
+ --objective WEBSITE_VISIT --type SPONSORED_UPDATES --cost-type CPC \
991
+ --bid 8.50 --daily-budget 75 --currency EUR --locale en_US --targeting-file targeting.json # → li_temp_x2
992
+ baker ads linkedin creatives create --campaign li_temp_x2 --format image \
993
+ --image-id <bakerImageId> --headline "Book a demo" --landing-url https://example.com/demo --cta REQUEST_DEMO
994
+
995
+ # Fix the classic audit findings
996
+ baker ads linkedin campaigns update 123456 --audience-expansion off --lan off
997
+ baker ads linkedin campaigns update 123456 --bid 7.50 --daily-budget 100 --currency USD
998
+
999
+ # Matched audiences (CSV with header; email columns SHA-256 hashed locally)
1000
+ baker ads linkedin audiences create --name "ABM Tier-1" --type company-list --list-file accounts.csv
1001
+
1002
+ # Conversions with playbook-default windows
1003
+ baker ads linkedin conversions create --name "Demo booked" --type LEAD --method INSIGHT_TAG \
1004
+ --post-click-window 30 --view-window 7
1005
+
1006
+ # Safe duplication — stage-time read of the source → staged DRAFT create ("Duplicate ad", never "Link to original")
1007
+ baker ads linkedin campaigns duplicate 123456 --name "New variant"
1008
+
1009
+ # Review / undo before publish; after publish shows per-op results (applied/simulated/failed/skipped)
1010
+ baker ads linkedin draft
1011
+ baker ads linkedin draft remove li_temp_x2 # removing a create cascades to dependents
1012
+ baker ads linkedin draft clear
970
1013
  ```
971
1014
 
1015
+ Notes:
1016
+
1017
+ - All write commands take `--file <json>` payloads; explicit flags override file keys. `baker schema ads.linkedin.campaigns.create` for exact args.
1018
+ - Money flags (`--bid`, `--daily-budget`, `--total-budget`) require `--currency`.
1019
+ - Creative media comes from the Baker library (`--image-id`/`--video-id` from `baker images`/`baker videos` — uploaded to LinkedIn at publish) or as LinkedIn URNs (`--image-urn`/`--video-urn`). Formats: `image|video|text|spotlight|follower|document|carousel|conversation|tla|jobs`; complex formats take `--file` with the full content object. Limits: headline ≤70, text-ad 25/75, intro soft-truncates at 600 chars. TLA sponsors an existing post via `--post-urn`.
1020
+ - Lead forms are file-first (`lead-forms create --file form.json`): name, headline (≤60), privacyPolicyUrl, questions[] (≤12; playbook: ≤4 for completion).
1021
+
972
1022
  #### `audit` — playbook diagnostic
973
1023
 
974
1024
  Runs in parallel: account detail + every campaign + every creative + conversion rules + account-level analytics + per-campaign frequency. Synthesizes findings across:
@@ -4283,6 +4333,8 @@ This CLI is designed for AI agent consumption. Key patterns:
4283
4333
 
4284
4334
  - **0.103.0**: `baker actions ...` commands now type their `/api/actions/...` request/response payloads from the shared `@baker/api` contract package (also consumed by the backend) instead of hand-written local interfaces. No command, flag, or output-shape changes.
4285
4335
  - **0.104.0**: `baker actions tags ...` commands now type their `/api/actions/tags...` request/response payloads from the shared `@baker/api` contract package instead of hand-written local interfaces. No command, flag, or output-shape changes.
4336
+ - **0.105.0**: `baker images ...`, `baker videos ...`, and `baker testimonials ...` commands now type their `/api/{images,videos,testimonials}/...` request/response payloads from the shared `@baker/api` contract package instead of hand-written local interfaces. No command, flag, or output-shape changes.
4337
+ - **0.106.0**: `baker ads linkedin` gains staged write commands — `campaign-groups`/`campaigns`/`creatives` create|update|pause|resume|(archive|)duplicate, `audiences create|upload`, `conversions create|update`, `lead-forms create|update`, plus `draft [remove|clear]` for review/undo. Ops validate at stage time, apply on chat publish, and run simulated (`urn:li:simulated:*`) unless LinkedIn writes are enabled for the company.
4286
4338
 
4287
4339
  ## Publishing
4288
4340
 
@@ -24,9 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  mod
25
25
  ));
26
26
 
27
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
27
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
28
28
  var require_safe_stable_stringify = __commonJS({
29
- "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
29
+ "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js"(exports, module) {
30
30
  "use strict";
31
31
  var { hasOwnProperty } = Object.prototype;
32
32
  var stringify = configure2();
@@ -890,7 +890,7 @@ function describeCause(c) {
890
890
  }
891
891
  }
892
892
 
893
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
893
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/esm/wrapper.js
894
894
  var import__ = __toESM(require_safe_stable_stringify(), 1);
895
895
  var configure = import__.default.configure;
896
896
  var wrapper_default = import__.default;
@@ -6252,4 +6252,4 @@ export {
6252
6252
  defaultRegistry,
6253
6253
  createEngineFromEnv
6254
6254
  };
6255
- //# sourceMappingURL=chunk-3JVYU72O.js.map
6255
+ //# sourceMappingURL=chunk-26K7V346.js.map