@koda-sl/baker-cli 0.325.1 → 0.327.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.
Files changed (28) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-GJVXXYCX.js → chunk-4VP5WWPR.js} +13 -2
  3. package/dist/chunk-4VP5WWPR.js.map +1 -0
  4. package/dist/{chunk-HPRKO6P2.js → chunk-FFOURYP5.js} +7 -5
  5. package/dist/chunk-FFOURYP5.js.map +1 -0
  6. package/dist/{chunk-UWFF6WEV.js → chunk-JWMLQSGK.js} +4 -4
  7. package/dist/{chunk-MSZSDYOJ.js → chunk-KGDL7F7M.js} +3 -3
  8. package/dist/{chunk-6BD32M7K.js → chunk-PWGY347J.js} +26 -3
  9. package/dist/chunk-PWGY347J.js.map +1 -0
  10. package/dist/{chunk-KAE5M5R7.js → chunk-XPUSSDLR.js} +3 -3
  11. package/dist/cli.js +151 -26
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{client-XUSSAB6O.js → client-PWRZOA3Q.js} +4 -4
  14. package/dist/engine/index.js +3 -3
  15. package/dist/{env-VIA5U56G.js → env-TQTHWLBN.js} +2 -2
  16. package/dist/{output-ZPACGSH2.js → output-HD63GTWI.js} +5 -5
  17. package/dist/{shared-OHOCOE2L.js → shared-5662SBDW.js} +6 -6
  18. package/package.json +1 -1
  19. package/dist/chunk-6BD32M7K.js.map +0 -1
  20. package/dist/chunk-GJVXXYCX.js.map +0 -1
  21. package/dist/chunk-HPRKO6P2.js.map +0 -1
  22. /package/dist/{chunk-UWFF6WEV.js.map → chunk-JWMLQSGK.js.map} +0 -0
  23. /package/dist/{chunk-MSZSDYOJ.js.map → chunk-KGDL7F7M.js.map} +0 -0
  24. /package/dist/{chunk-KAE5M5R7.js.map → chunk-XPUSSDLR.js.map} +0 -0
  25. /package/dist/{client-XUSSAB6O.js.map → client-PWRZOA3Q.js.map} +0 -0
  26. /package/dist/{env-VIA5U56G.js.map → env-TQTHWLBN.js.map} +0 -0
  27. /package/dist/{output-ZPACGSH2.js.map → output-HD63GTWI.js.map} +0 -0
  28. /package/dist/{shared-OHOCOE2L.js.map → shared-5662SBDW.js.map} +0 -0
@@ -2,13 +2,13 @@ import {
2
2
  handleConnectionError,
3
3
  needsConnectionFix,
4
4
  writeAdsJson
5
- } from "./chunk-MSZSDYOJ.js";
5
+ } from "./chunk-KGDL7F7M.js";
6
6
  import {
7
7
  ApiError
8
- } from "./chunk-KAE5M5R7.js";
8
+ } from "./chunk-XPUSSDLR.js";
9
9
  import {
10
10
  getEnv
11
- } from "./chunk-GJVXXYCX.js";
11
+ } from "./chunk-4VP5WWPR.js";
12
12
 
13
13
  // src/commands/ads/meta/shared.ts
14
14
  var DAY_MS = 864e5;
@@ -108,4 +108,4 @@ export {
108
108
  csvOrJson,
109
109
  resolveEffectiveStatus
110
110
  };
111
- //# sourceMappingURL=chunk-UWFF6WEV.js.map
111
+ //# sourceMappingURL=chunk-JWMLQSGK.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  ApiError,
3
3
  apiGet
4
- } from "./chunk-KAE5M5R7.js";
4
+ } from "./chunk-XPUSSDLR.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-GJVXXYCX.js";
7
+ } from "./chunk-4VP5WWPR.js";
8
8
 
9
9
  // src/error-handler.ts
10
10
  var REQUEST_CONNECTION_PLATFORM = {
@@ -294,4 +294,4 @@ export {
294
294
  writeAdsOutput,
295
295
  resolveCustomerId
296
296
  };
297
- //# sourceMappingURL=chunk-MSZSDYOJ.js.map
297
+ //# sourceMappingURL=chunk-KGDL7F7M.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  debugLogSetting
3
- } from "./chunk-GJVXXYCX.js";
3
+ } from "./chunk-4VP5WWPR.js";
4
4
 
5
5
  // src/debugLog.ts
6
6
  import { appendFileSync, mkdirSync, renameSync, statSync } from "fs";
@@ -12,7 +12,10 @@ var MAX_BYTES = 64 * 1024 * 1024;
12
12
  var REDACTIONS = [
13
13
  [/Bearer\s+[A-Za-z0-9._-]+/g, "Bearer [redacted]"],
14
14
  // Authorization headers
15
- [/bk_[A-Za-z0-9]+/g, "bk_[redacted]"],
15
+ // Both prefixes, captured rather than listed twice: `bkr_` does not contain
16
+ // the literal `bk_`, so the company-key rule matched no part of the read-only
17
+ // credential a Session review runs with.
18
+ [/\b(bkr?)_[A-Za-z0-9]+/g, "$1_[redacted]"],
16
19
  // Baker API keys
17
20
  [/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, "[redacted-jwt]"],
18
21
  // JWTs / id tokens
@@ -92,9 +95,28 @@ function errorToPlain(err) {
92
95
  }
93
96
  return { message: String(err) };
94
97
  }
98
+ var invocationStartedAt;
95
99
  function logInvocation(argv) {
100
+ invocationStartedAt = Date.now();
96
101
  append({ kind: "invocation", argv, cwd: process.cwd() });
97
102
  }
103
+ function logExit(code) {
104
+ append({
105
+ kind: "exit",
106
+ code,
107
+ ...invocationStartedAt === void 0 ? {} : { durationMs: Date.now() - invocationStartedAt }
108
+ });
109
+ }
110
+ var exitHookInstalled = false;
111
+ function installExitRecord() {
112
+ if (exitHookInstalled || !isDebugLogEnabled()) {
113
+ return;
114
+ }
115
+ exitHookInstalled = true;
116
+ process.on("exit", (code) => {
117
+ logExit(typeof code === "number" ? code : 0);
118
+ });
119
+ }
98
120
  function debugLogHttp(entry) {
99
121
  if (!isDebugLogEnabled()) {
100
122
  return;
@@ -146,8 +168,9 @@ function installStreamTaps() {
146
168
 
147
169
  export {
148
170
  logInvocation,
171
+ installExitRecord,
149
172
  debugLogHttp,
150
173
  readBodyForLog,
151
174
  installStreamTaps
152
175
  };
153
- //# sourceMappingURL=chunk-6BD32M7K.js.map
176
+ //# sourceMappingURL=chunk-PWGY347J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/debugLog.ts"],"sourcesContent":["// Full-fidelity debug capture for the whole CLI.\n//\n// Set BAKER_DEBUG_LOG to turn it on:\n// BAKER_DEBUG_LOG=1 -> appends to ./baker-cli-debug.jsonl\n// BAKER_DEBUG_LOG=/tmp/baker.jsonl -> appends to that file\n// BAKER_DEBUG_LOG=0|false|off|no -> disabled (same as unset)\n//\n// When enabled, every HTTP request/response (both the REST client and the\n// canvas engine client), every byte written to stdout/stderr, and the command\n// invocation are appended as JSONL entries. Known secret shapes are redacted\n// before anything is written (best-effort — see redactSecrets). Logging is\n// always fail-open: a logging error is swallowed so it can never break a\n// command. The file rotates once past MAX_BYTES so an always-on capture cannot\n// fill the disk.\n\nimport { appendFileSync, mkdirSync, renameSync, statSync } from \"node:fs\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { debugLogSetting } from \"./env.ts\";\n\nconst DEFAULT_FILE = \"baker-cli-debug.jsonl\";\nconst BOOLEAN_ON = new Set([\"1\", \"true\", \"on\", \"yes\"]);\nconst BOOLEAN_OFF = new Set([\"0\", \"false\", \"off\", \"no\"]);\n\n// Rotate once the active file passes this size (one older generation, `<file>.1`,\n// is kept). Bounds growth for the always-on sandbox capture without a per-write stat.\nconst MAX_BYTES = 64 * 1024 * 1024;\n\n// Best-effort redaction. Response/request bodies are stored as escaped strings, so\n// key/value matching is unreliable there; instead we scrub the token *values*\n// themselves (quote-agnostic) plus the auth header and Baker keys. This is not\n// exhaustive — a secret in an unrecognized shape can still be written. See README.\nconst REDACTIONS: ReadonlyArray<readonly [RegExp, string]> = [\n [/Bearer\\s+[A-Za-z0-9._-]+/g, \"Bearer [redacted]\"], // Authorization headers\n // Both prefixes, captured rather than listed twice: `bkr_` does not contain\n // the literal `bk_`, so the company-key rule matched no part of the read-only\n // credential a Session review runs with.\n [/\\b(bkr?)_[A-Za-z0-9]+/g, \"$1_[redacted]\"], // Baker API keys\n [/eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g, \"[redacted-jwt]\"], // JWTs / id tokens\n [/ya29\\.[A-Za-z0-9._-]+/g, \"[redacted-google-token]\"], // Google OAuth access tokens\n [/1\\/\\/[A-Za-z0-9._-]+/g, \"[redacted-google-refresh]\"], // Google refresh tokens\n [/EAA[A-Za-z0-9]{20,}/g, \"[redacted-meta-token]\"], // Meta/Facebook access tokens\n];\n\nexport function redactSecrets(input: string): string {\n let out = input;\n for (const [pattern, replacement] of REDACTIONS) {\n out = out.replace(pattern, replacement);\n }\n return out;\n}\n\nfunction resolveTarget(): string | undefined {\n const raw = debugLogSetting();\n if (!raw) {\n return undefined;\n }\n const lower = raw.toLowerCase();\n if (BOOLEAN_OFF.has(lower)) {\n return undefined;\n }\n const target = BOOLEAN_ON.has(lower) ? DEFAULT_FILE : raw;\n return isAbsolute(target) ? target : resolve(process.cwd(), target);\n}\n\nexport function isDebugLogEnabled(): boolean {\n return resolveTarget() !== undefined;\n}\n\nlet sessionId: string | undefined;\nfunction getSessionId(): string {\n if (!sessionId) {\n sessionId = `${process.pid}-${Date.now()}`;\n }\n return sessionId;\n}\n\n// Per-resolved-path bookkeeping so the hot path skips redundant syscalls: the\n// directory is ensured once and the current size is read once (via statSync),\n// then tracked in-process. Resets when the resolved path changes.\nlet trackedPath: string | undefined;\nlet bytesInFile = 0;\n\nfunction ensureReady(filePath: string): void {\n if (trackedPath !== filePath) {\n trackedPath = filePath;\n mkdirSync(dirname(filePath), { recursive: true });\n try {\n bytesInFile = statSync(filePath).size;\n } catch {\n bytesInFile = 0;\n }\n }\n}\n\nfunction append(entry: Record<string, unknown>): void {\n const filePath = resolveTarget();\n if (!filePath) {\n return;\n }\n try {\n const payload = { ts: new Date().toISOString(), session: getSessionId(), ...entry };\n const line = `${redactSecrets(JSON.stringify(payload))}\\n`;\n ensureReady(filePath);\n const size = Buffer.byteLength(line);\n if (bytesInFile + size > MAX_BYTES) {\n renameSync(filePath, `${filePath}.1`);\n bytesInFile = 0;\n }\n appendFileSync(filePath, line);\n bytesInFile += size;\n } catch {\n // Fail-open: debug logging must never break a command.\n }\n}\n\nfunction errorToPlain(err: unknown): Record<string, unknown> {\n if (err instanceof Error) {\n const code = (err as { code?: unknown }).code;\n return { name: err.name, message: err.message, ...(typeof code === \"string\" ? { code } : {}) };\n }\n return { message: String(err) };\n}\n\nlet invocationStartedAt: number | undefined;\n\nexport function logInvocation(argv: string[]): void {\n invocationStartedAt = Date.now();\n append({ kind: \"invocation\", argv, cwd: process.cwd() });\n}\n\n/**\n * Close an invocation with its outcome and its wall time.\n *\n * Until this existed the log could say what was called and what every HTTP hop\n * cost, and nothing at all about whether the command succeeded or how long the\n * whole thing took — so \"this verb is slow\" and \"this verb fails half the time\"\n * were both unanswerable from the one record that sees every call. `durationMs`\n * is measured from `logInvocation`, which runs before any command does.\n */\nexport function logExit(code: number): void {\n append({\n kind: \"exit\",\n code,\n ...(invocationStartedAt === undefined ? {} : { durationMs: Date.now() - invocationStartedAt }),\n });\n}\n\nlet exitHookInstalled = false;\n\n/**\n * Write the exit record however the process ends.\n *\n * `process.on(\"exit\")` is the only hook that sees all of them — a clean return, a\n * `process.exit` from the error handler, an unhandled rejection — and it is\n * synchronous-only, which is exactly what `appendFileSync` needs. Installed once,\n * and only when logging is on, so the disabled path adds no listener at all.\n */\nexport function installExitRecord(): void {\n if (exitHookInstalled || !isDebugLogEnabled()) {\n return;\n }\n exitHookInstalled = true;\n process.on(\"exit\", (code) => {\n logExit(typeof code === \"number\" ? code : 0);\n });\n}\n\nexport type HttpLogEntry = {\n source: \"cli\" | \"canvas\";\n method: string;\n url: string;\n requestBody?: unknown;\n status?: number;\n ok?: boolean;\n responseBody?: string;\n durationMs?: number;\n error?: unknown;\n};\n\nexport function debugLogHttp(entry: HttpLogEntry): void {\n if (!isDebugLogEnabled()) {\n return;\n }\n append({\n kind: \"http\",\n source: entry.source,\n method: entry.method,\n url: entry.url,\n durationMs: entry.durationMs,\n request: entry.requestBody,\n status: entry.status,\n ok: entry.ok,\n response: entry.responseBody,\n error: entry.error === undefined ? undefined : errorToPlain(entry.error),\n });\n}\n\n// Reads a response body for logging without consuming it for the real caller.\nexport async function readBodyForLog(response: Response): Promise<string | undefined> {\n if (!isDebugLogEnabled()) {\n return undefined;\n }\n try {\n return await response.clone().text();\n } catch {\n return undefined;\n }\n}\n\n// Method syntax (bivariant) so a real `process.stdout`/`stderr` and a plain\n// test double both satisfy it.\ntype Writable = { write(...args: unknown[]): boolean };\n\n// Wraps a stream's `write` so every chunk is mirrored into the debug log while\n// the original write semantics (args + return value) are preserved. A single\n// streaming TextDecoder per stream decodes byte chunks so a multi-byte character\n// split across two writes is reassembled instead of garbled.\nexport function tapStream(name: string, stream: Writable): void {\n const original = stream.write.bind(stream) as (...args: unknown[]) => boolean;\n const decoder = new TextDecoder(\"utf-8\");\n stream.write = ((chunk: unknown, ...rest: unknown[]): boolean => {\n try {\n const text =\n typeof chunk === \"string\"\n ? chunk\n : chunk instanceof Uint8Array\n ? decoder.decode(chunk, { stream: true })\n : String(chunk);\n append({ kind: \"output\", stream: name, text });\n } catch {\n // ignore capture failures\n }\n return original(chunk, ...rest);\n }) as typeof stream.write;\n}\n\nlet tapsInstalled = false;\n\n// Mirrors everything written to stdout/stderr into the debug log. Installed once,\n// only when enabled, so the common (disabled) path leaves the streams untouched.\nexport function installStreamTaps(): void {\n if (tapsInstalled || !isDebugLogEnabled()) {\n return;\n }\n tapsInstalled = true;\n tapStream(\"stdout\", process.stdout);\n tapStream(\"stderr\", process.stderr);\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  debugLogHttp,
3
3
  readBodyForLog
4
- } from "./chunk-6BD32M7K.js";
4
+ } from "./chunk-PWGY347J.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-GJVXXYCX.js";
7
+ } from "./chunk-4VP5WWPR.js";
8
8
 
9
9
  // src/client.ts
10
10
  var MAX_RATE_LIMIT_RETRIES = 3;
@@ -205,4 +205,4 @@ export {
205
205
  apiGet,
206
206
  apiPost
207
207
  };
208
- //# sourceMappingURL=chunk-KAE5M5R7.js.map
208
+ //# sourceMappingURL=chunk-XPUSSDLR.js.map
package/dist/cli.js CHANGED
@@ -67,7 +67,7 @@ import {
67
67
  validateCanvasDeep,
68
68
  withoutCastName,
69
69
  ytDlpBlockSignal
70
- } from "./chunk-HPRKO6P2.js";
70
+ } from "./chunk-FFOURYP5.js";
71
71
  import {
72
72
  csvOrJson,
73
73
  daysAgoIso,
@@ -76,7 +76,7 @@ import {
76
76
  resolveAccountIdArg,
77
77
  resolveEffectiveStatus,
78
78
  todayIso
79
- } from "./chunk-UWFF6WEV.js";
79
+ } from "./chunk-JWMLQSGK.js";
80
80
  import {
81
81
  buildQueryCacheKey,
82
82
  cacheGet,
@@ -92,18 +92,19 @@ import {
92
92
  writeAdsJson,
93
93
  writeAdsOutput,
94
94
  writeJsonEnvelope
95
- } from "./chunk-MSZSDYOJ.js";
95
+ } from "./chunk-KGDL7F7M.js";
96
96
  import {
97
97
  ApiError,
98
98
  apiGet,
99
99
  apiGetWithHeaders,
100
100
  apiPost,
101
101
  validateConvexId
102
- } from "./chunk-KAE5M5R7.js";
102
+ } from "./chunk-XPUSSDLR.js";
103
103
  import {
104
+ installExitRecord,
104
105
  installStreamTaps,
105
106
  logInvocation
106
- } from "./chunk-6BD32M7K.js";
107
+ } from "./chunk-PWGY347J.js";
107
108
  import {
108
109
  captureBudgetMs,
109
110
  captureProxyCredentials,
@@ -117,7 +118,7 @@ import {
117
118
  requireChatId,
118
119
  resolveChatId,
119
120
  shouldEscalate
120
- } from "./chunk-GJVXXYCX.js";
121
+ } from "./chunk-4VP5WWPR.js";
121
122
 
122
123
  // src/cli.ts
123
124
  import { defineCommand as defineCommand244, runMain } from "citty";
@@ -955,7 +956,11 @@ var winnersSearchResponseSchema = z2.object({
955
956
  // the dashboard then falls back to a single non-paged page.
956
957
  offset: z2.number().nullable(),
957
958
  total: z2.number().nullable(),
958
- has_more: z2.boolean().nullable()
959
+ has_more: z2.boolean().nullable(),
960
+ // Ads the corpus holds for each requested `country`; null when the search did
961
+ // not filter by country. Tells "no winners matched" apart from "unsupported"
962
+ // (an unknown code is refused outright).
963
+ country_coverage: z2.array(z2.object({ code: z2.string(), ads: z2.number() })).nullable()
959
964
  });
960
965
  var advertiserPlatformSchema = z2.object({
961
966
  platform: z2.string(),
@@ -4928,7 +4933,33 @@ var adEffectSchema = z13.object({
4928
4933
  */
4929
4934
  outcome: z13.enum(["applied", "simulated", "failed", "skipped"]).nullable(),
4930
4935
  /** Why it failed, verbatim from the platform. Null unless the op failed. */
4931
- error: z13.string().nullable()
4936
+ error: z13.string().nullable(),
4937
+ /**
4938
+ * Why the publish never attempted it — a dependency that failed first, a
4939
+ * connection that went read-only. Distinct from `error`, which is the
4940
+ * provider's refusal of an op that was actually sent: a reader that cannot
4941
+ * tell the two apart reads "we never tried" as "the platform said no".
4942
+ */
4943
+ skippedBecause: z13.string().nullable().optional()
4944
+ });
4945
+ var configEffectSchema = z13.object({
4946
+ op: effectOpSchema,
4947
+ staged: z13.boolean(),
4948
+ /** The full stored op kind, e.g. `tagManager.tag.create`, `ga4.keyEvent.update`. */
4949
+ operation: z13.string(),
4950
+ /** The entity class the op acts on, e.g. `tag`, `customDimension`. */
4951
+ entity: z13.string().nullable(),
4952
+ summary: z13.string(),
4953
+ ref: z13.string(),
4954
+ outcome: z13.enum(["applied", "failed", "skipped"]).nullable(),
4955
+ error: z13.string().nullable(),
4956
+ skippedBecause: z13.string().nullable(),
4957
+ /**
4958
+ * The post-publish read-back, when one ran. Annotation only — Tag Manager can
4959
+ * answer 200 to a write it silently dropped, so a fresh read is the only
4960
+ * thing that distinguishes "applied" from "accepted and discarded".
4961
+ */
4962
+ verified: z13.boolean().nullable()
4932
4963
  });
4933
4964
  var creativeEffectSchema = z13.object({
4934
4965
  op: effectOpSchema,
@@ -4948,7 +4979,51 @@ var chatEffectsSchema = z13.object({
4948
4979
  linkedin: z13.array(adEffectSchema),
4949
4980
  x: z13.array(adEffectSchema)
4950
4981
  }),
4951
- creatives: z13.array(creativeEffectSchema)
4982
+ creatives: z13.array(creativeEffectSchema),
4983
+ tagManager: z13.array(configEffectSchema),
4984
+ ga4: z13.array(configEffectSchema)
4985
+ });
4986
+ var publishSurfaceFailureSchema = z13.object({
4987
+ summary: z13.string(),
4988
+ /** The provider's own words, trimmed. Empty when it said nothing. */
4989
+ error: z13.string()
4990
+ });
4991
+ var publishSurfaceOutcomeSchema = z13.object({
4992
+ surface: z13.string(),
4993
+ label: z13.string(),
4994
+ total: z13.number(),
4995
+ landed: z13.number(),
4996
+ failed: z13.number(),
4997
+ /** True while this surface is still applying — not yet a verdict either way. */
4998
+ running: z13.boolean(),
4999
+ failures: z13.array(publishSurfaceFailureSchema)
5000
+ });
5001
+ var chatPublishSummarySchema = z13.object({
5002
+ complete: z13.boolean(),
5003
+ running: z13.boolean(),
5004
+ failedTotal: z13.number(),
5005
+ surfaces: z13.array(publishSurfaceOutcomeSchema)
5006
+ });
5007
+ var chatActivityEntrySchema = z13.object({
5008
+ action: z13.string(),
5009
+ actorType: z13.string(),
5010
+ createdAt: z13.number(),
5011
+ threadId: z13.string().nullable(),
5012
+ /** Compact truncates this; `--full` returns it whole. */
5013
+ metadata: z13.unknown().optional()
5014
+ });
5015
+ var chatThreadUsageSchema = z13.object({
5016
+ threadId: z13.string(),
5017
+ costUsd: z13.number(),
5018
+ model: z13.string().nullable()
5019
+ });
5020
+ var chatUsageSchema = z13.object({
5021
+ threads: z13.array(chatThreadUsageSchema),
5022
+ totalCostUsd: z13.number(),
5023
+ inputTokens: z13.number(),
5024
+ outputTokens: z13.number(),
5025
+ cacheReadTokens: z13.number(),
5026
+ cacheWriteTokens: z13.number()
4952
5027
  });
4953
5028
  var chatDetailSchema = z13.object({
4954
5029
  id: z13.string(),
@@ -4967,7 +5042,15 @@ var chatDetailSchema = z13.object({
4967
5042
  threads: z13.array(chatThreadSummarySchema),
4968
5043
  commits: z13.array(chatCommitSummarySchema),
4969
5044
  /** True when a real file-level diff is available via `baker chats diff`. */
4970
- diffAvailable: z13.boolean()
5045
+ diffAvailable: z13.boolean(),
5046
+ /** What the Publish did on each external surface. Absent when nothing was ever published. */
5047
+ publish: chatPublishSummarySchema.optional(),
5048
+ /** Why the Publish itself failed, as the backend recorded it. */
5049
+ publishFailureReason: z13.string().nullable().optional(),
5050
+ /** The chat's own timeline: status changes, publish start/fail, sandbox recoveries, timeouts. */
5051
+ activity: z13.array(chatActivityEntrySchema).optional(),
5052
+ /** What the Session cost, per thread and in total. */
5053
+ usage: chatUsageSchema.optional()
4971
5054
  });
4972
5055
  var chatsViewResponseSchema = z13.object({
4973
5056
  ok: z13.literal(true),
@@ -24823,10 +24906,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
24823
24906
  }
24824
24907
  },
24825
24908
  run: async ({ args: args4 }) => {
24826
- const { apiPost: apiPost2 } = await import("./client-XUSSAB6O.js");
24827
- const { requireChatId: requireChatId2 } = await import("./env-VIA5U56G.js");
24828
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-ZPACGSH2.js");
24829
- const { handleMetaError: handleMetaError2 } = await import("./shared-OHOCOE2L.js");
24909
+ const { apiPost: apiPost2 } = await import("./client-PWRZOA3Q.js");
24910
+ const { requireChatId: requireChatId2 } = await import("./env-TQTHWLBN.js");
24911
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HD63GTWI.js");
24912
+ const { handleMetaError: handleMetaError2 } = await import("./shared-5662SBDW.js");
24830
24913
  try {
24831
24914
  const accountId = bareAccountId2(args4);
24832
24915
  const urlTags = typeof args4["url-tags"] === "string" ? args4["url-tags"] : void 0;
@@ -24971,10 +25054,10 @@ function duplicateCommand2(entity, label) {
24971
25054
  replace: { type: "boolean", description: "Pause the original once the copy publishes" }
24972
25055
  },
24973
25056
  run: async ({ args: args4 }) => {
24974
- const { apiPost: apiPost2 } = await import("./client-XUSSAB6O.js");
24975
- const { requireChatId: requireChatId2 } = await import("./env-VIA5U56G.js");
24976
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-ZPACGSH2.js");
24977
- const { handleMetaError: handleMetaError2 } = await import("./shared-OHOCOE2L.js");
25057
+ const { apiPost: apiPost2 } = await import("./client-PWRZOA3Q.js");
25058
+ const { requireChatId: requireChatId2 } = await import("./env-TQTHWLBN.js");
25059
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HD63GTWI.js");
25060
+ const { handleMetaError: handleMetaError2 } = await import("./shared-5662SBDW.js");
24978
25061
  try {
24979
25062
  const accountId = bareAccountId2(args4);
24980
25063
  const chatId = requireChatId2();
@@ -43909,7 +43992,7 @@ var canvasCommand = defineCommand118({
43909
43992
  name: "canvas",
43910
43993
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
43911
43994
 
43912
- Auth: BAKER_API_KEY (must start with bk_) + BAKER_API_URL (your Convex .convex.site URL).
43995
+ Auth: BAKER_API_KEY (bk_ or bkr_) + BAKER_API_URL (your Convex .convex.site URL).
43913
43996
 
43914
43997
  Subcommands:
43915
43998
  baker canvas validate <file.json> \u2014 schema/registry check + composition-meta deep check + cost preview
@@ -44119,12 +44202,12 @@ var listCommand13 = defineCommand120({
44119
44202
  });
44120
44203
  registerSchema({
44121
44204
  command: "chats.view",
44122
- description: "Inspect one Session's FULL picture of what it changed \u2014 the unified `effects`: git content (landings, creatives, flows, knowledge, brand), plus DB-only effects that never touch the repo \u2014 Actions, Scheduled Actions, Tags, and ad-platform writes \u2014 each resolved to real detail (names, descriptions, priorities, tag types, ad operations). Also the kickoff (how it was asked), threads, and commits. Effects are `staged` (in-progress draft) or applied. Use after `baker chats list` to decide whether to reuse it. Read-only.",
44205
+ description: "Inspect one Session's FULL picture of what it changed \u2014 the unified `effects`: git content (landings, creatives, flows, knowledge, brand), plus DB-only effects that never touch the repo \u2014 Actions, Scheduled Actions, Tags, Tag Manager, Google Analytics, and ad-platform writes \u2014 each resolved to real detail (names, descriptions, priorities, tag types, ad operations). Also `publish` (what each external surface actually did, with the provider's own error), `activity` (the chat's own timeline: status changes, publish start/fail, workspace recoveries, timeouts), `usage` (per-thread cost and the Session's token totals), the kickoff (how it was asked), threads, and commits. Effects are `staged` (in-progress draft) or applied. A completed Session is NOT proof its external changes landed \u2014 read `publish`. Use after `baker chats list` to decide whether to reuse it. Read-only.",
44123
44206
  args: {
44124
44207
  id: { type: "positional", description: "The Session id (from `baker chats list`)", required: true },
44125
44208
  full: {
44126
44209
  type: "boolean",
44127
- description: "No-op today; view already returns full effect detail",
44210
+ description: "Untruncated effect lists and full activity metadata (compact caps each list at 25)",
44128
44211
  required: false,
44129
44212
  default: false
44130
44213
  }
@@ -44146,6 +44229,12 @@ var viewCommand = defineCommand120({
44146
44229
  ...args4.full ? { full: true } : {}
44147
44230
  });
44148
44231
  const hints2 = [];
44232
+ if (response.data.publish && !response.data.publish.complete) {
44233
+ const failed = response.data.publish.failedTotal;
44234
+ hints2.push(
44235
+ `This Session's publish left ${failed} change${failed === 1 ? "" : "s"} behind \u2014 see \`publish.surfaces\` for the platform's own words. Do not report those changes as live.`
44236
+ );
44237
+ }
44149
44238
  if (response.data.diffAvailable) {
44150
44239
  hints2.push("See the real file-level diff of the git content with `baker chats diff <id> --full`.");
44151
44240
  } else if (response.data.status === "in_progress" || response.data.status === "publishing") {
@@ -66301,7 +66390,11 @@ registerSchema({
66301
66390
  description: "Comma list: unaware,problem_aware,solution_aware,product_aware,most_aware",
66302
66391
  required: false
66303
66392
  },
66304
- country: { type: "string", description: "Comma list of country codes", required: false },
66393
+ country: {
66394
+ type: "string",
66395
+ description: "Comma list of ISO country codes (US,GB) \u2014 an unknown code is refused with the codes that have ads",
66396
+ required: false
66397
+ },
66305
66398
  language: { type: "string", description: "Comma list of language codes", required: false },
66306
66399
  "advertiser-id": {
66307
66400
  type: "string",
@@ -66374,6 +66467,32 @@ function buildSearchBody2(args4) {
66374
66467
  }
66375
66468
  return body;
66376
66469
  }
66470
+ var UNKNOWN_COUNTRY_RE = /Unknown country code\(s\): ([^.]+)\. Countries with ads: ([^.]+)\./;
66471
+ function unknownCountryFix(message) {
66472
+ const match = UNKNOWN_COUNTRY_RE.exec(message);
66473
+ if (!match) {
66474
+ return null;
66475
+ }
66476
+ const unknownCountries = splitList2(match[1]);
66477
+ const validCountries = splitList2(match[2]);
66478
+ if (unknownCountries.length === 0 || validCountries.length === 0) {
66479
+ return null;
66480
+ }
66481
+ return {
66482
+ action: "retry_with_a_valid_country",
66483
+ explanation: `${unknownCountries.join(", ")} is not a country the winning-ads library holds ads for. Re-run with codes from \`validCountries\`, or drop --country to search every market.`,
66484
+ unknownCountries,
66485
+ validCountries
66486
+ };
66487
+ }
66488
+ function reportSearchError(err) {
66489
+ const fix = err instanceof ApiError ? unknownCountryFix(err.message) : null;
66490
+ if (err instanceof ApiError && fix) {
66491
+ writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
66492
+ process.exit(1);
66493
+ }
66494
+ reportError2(err);
66495
+ }
66377
66496
  var searchCommand5 = defineCommand239({
66378
66497
  meta: {
66379
66498
  name: "search",
@@ -66406,7 +66525,11 @@ var searchCommand5 = defineCommand239({
66406
66525
  required: false
66407
66526
  },
66408
66527
  awareness: { type: "string", description: "Comma list of awareness stages", required: false },
66409
- country: { type: "string", description: "Comma list of country codes", required: false },
66528
+ country: {
66529
+ type: "string",
66530
+ description: "Comma list of ISO country codes (US,GB) \u2014 an unknown code is refused with the codes that have ads",
66531
+ required: false
66532
+ },
66410
66533
  language: { type: "string", description: "Comma list of language codes", required: false },
66411
66534
  "advertiser-id": { type: "string", description: "Restrict to these advertiser ids", required: false },
66412
66535
  "exclude-advertiser": {
@@ -66470,7 +66593,8 @@ var searchCommand5 = defineCommand239({
66470
66593
  results,
66471
66594
  pool_size: data?.pool_size ?? null,
66472
66595
  match_confidence: data?.match_confidence ?? null,
66473
- below_floor_count: data?.below_floor_count ?? null
66596
+ below_floor_count: data?.below_floor_count ?? null,
66597
+ country_coverage: data?.country_coverage ?? null
66474
66598
  }
66475
66599
  });
66476
66600
  return;
@@ -66483,7 +66607,7 @@ var searchCommand5 = defineCommand239({
66483
66607
  winningAdNormalizer
66484
66608
  );
66485
66609
  } catch (err) {
66486
- reportError2(err);
66610
+ reportSearchError(err);
66487
66611
  }
66488
66612
  }
66489
66613
  });
@@ -66660,7 +66784,7 @@ var winningAdsCommand = defineCommand243({
66660
66784
  name: "winning-ads",
66661
66785
  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.
66662
66786
 
66663
- Auth: BAKER_API_KEY (must start with bk_) + BAKER_API_URL (your Convex .convex.site URL).
66787
+ Auth: BAKER_API_KEY (bk_ or bkr_) + BAKER_API_URL (your Convex .convex.site URL).
66664
66788
 
66665
66789
  Subcommands:
66666
66790
  baker winning-ads search "<free text>" \u2014 semantic search across the corpus; lean shortlist (advertiser, summary, scores, media_url)
@@ -66939,6 +67063,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
66939
67063
  process.argv = [...process.argv.slice(0, 2), ...normalizeCacheFlag(process.argv.slice(2))];
66940
67064
  installStreamTaps();
66941
67065
  logInvocation(process.argv.slice(2));
67066
+ installExitRecord();
66942
67067
  refuseUnknownFlags(main, process.argv.slice(2));
66943
67068
  process.argv = [...process.argv.slice(0, 2), ...cacheFlagForParser(process.argv.slice(2))];
66944
67069
  runMain(main);