@koda-sl/baker-cli 0.361.0-dev.a5e33d211 → 0.361.0-dev.d766dc120

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
@@ -110,6 +110,18 @@ question — and nothing in the output said so. Both spellings of an option work
110
110
  that lists every option: `baker schema <command>` (`check_schema`) when the command
111
111
  registers a schema, `baker <command> --help` (`check_help`) when it does not.
112
112
 
113
+ ### Narrowing a result: `--fields`
114
+
115
+ `--fields a,b,c` works on every command that prints the JSON envelope. It keeps only
116
+ those keys of each record in `data` — the rows when `data` is a list or wraps one
117
+ (`baker chats list --fields id,title`), `data` itself when it is a single record
118
+ (`baker experiment plan ... --fields traffic,warning`). `meta`, `hints` and warnings are
119
+ kept, and a name no record carries is reported in `hints` alongside the keys that do
120
+ exist. Commands that declare `--fields` themselves keep their own meaning
121
+ (`ads meta insights` chooses which metrics to request; `ads linkedin creatives` takes dotted
122
+ paths). A command whose default output is text needs `--output json` for there to be an
123
+ envelope to narrow; without it a note on stderr says the flag changed nothing.
124
+
113
125
  ### Fresh reads: `--no-cache`
114
126
 
115
127
  Every command that caches takes `--no-cache`, and it skips **both** cache layers — the
@@ -5420,7 +5432,7 @@ Validate, then execute the graph. Blocks until done. Logs one line per node. Ret
5420
5432
 
5421
5433
  **Run history streams live.** The run posts its plan (every node + its dependency edges) the moment validation passes, then re-posts a progress snapshot as each node starts and settles — the dashboard's creative workflow graph shows nodes flipping pending → running → done in real time, with each node's outputs attached as they land. A failed run keeps its per-node trail (what completed, what died). All best-effort: an unreachable backend never changes the run's outcome.
5422
5434
 
5423
- **Failures don't abandon sibling work.** Nodes in a layer run under the concurrency cap and every one **settles** — a failed clip no longer kills its in-flight siblings, whose finished results still land in the content-addressed cache. One failure re-throws as-is; several are reported together (each failed node named). Re-running `baker canvas run` resumes from the cache and re-executes **only** the failed nodes and their descendants — never hand-orchestrate per-node renders. **One render per canvas at a time:** a `run` of a canvas that another live process in the same workspace is still rendering (a backgrounded render, or a subagent's) is refused with `CONFLICT` instead of sharing its run — wait for it and use its result. Long `video_generate` clips execute as **backend jobs** (the CLI polls; a CDN/proxy timeout can no longer kill a generation mid-flight).
5435
+ **Failures don't abandon sibling work.** Nodes in a layer run under the concurrency cap and every one **settles** — a failed clip no longer kills its in-flight siblings, whose finished results still land in the content-addressed cache. One failure re-throws as-is; several are reported together (each failed node named). Re-running `baker canvas run` resumes from the cache and re-executes **only** the failed nodes and their descendants — never hand-orchestrate per-node renders. Long `video_generate` clips execute as **backend jobs** (the CLI polls; a CDN/proxy timeout can no longer kill a generation mid-flight).
5424
5436
 
5425
5437
  #### `baker canvas scaffold-video <video> [flags]`
5426
5438
 
package/dist/cli.js CHANGED
@@ -40880,7 +40880,6 @@ async function clearCreativeDirty(slug, base) {
40880
40880
  }
40881
40881
 
40882
40882
  // src/commands/canvas/run-resume.ts
40883
- import { readFileSync as readFileSync14 } from "fs";
40884
40883
  import { mkdir as mkdir4, readFile as readFile9, rm as rm4, writeFile as writeFile6 } from "fs/promises";
40885
40884
  import path13 from "path";
40886
40885
  function markerKey(canvasPath) {
@@ -40903,12 +40902,9 @@ function classifyRemoteRun(run, now) {
40903
40902
  }
40904
40903
  async function resolveRunId(opts) {
40905
40904
  if (opts.explicitRunId) return { runId: opts.explicitRunId, resumed: false };
40906
- const existing = await readMarker(opts.outputsDir, opts.canvasPath);
40907
- if (existing?.pid !== void 0 && existing.pid !== process.pid && (opts.isRendering ?? isRenderProcess)(existing.pid)) {
40908
- return { runId: existing.runId, resumed: false, rendering: { runId: existing.runId, pid: existing.pid } };
40909
- }
40910
40905
  if (!opts.fresh) {
40911
- if (existing) return { runId: existing.runId, resumed: true, source: "local" };
40906
+ const existing = await readMarkerRunId(opts.outputsDir, opts.canvasPath);
40907
+ if (existing) return { runId: existing, resumed: true, source: "local" };
40912
40908
  if (opts.remote) {
40913
40909
  try {
40914
40910
  const active = await opts.remote.getActiveRun(opts.remote.creativeSlug, opts.remote.canvasSha);
@@ -40928,31 +40924,22 @@ async function resolveRunId(opts) {
40928
40924
  }
40929
40925
  return { runId: `r_${ulid()}`, resumed: false };
40930
40926
  }
40931
- async function readMarker(outputsDir, canvasPath) {
40927
+ async function readMarkerRunId(outputsDir, canvasPath) {
40932
40928
  for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
40933
40929
  try {
40934
40930
  const raw = await readFile9(markerFile(outputsDir, key), "utf8");
40935
40931
  const parsed = JSON.parse(raw);
40936
- if (typeof parsed.runId === "string" && parsed.runId.length > 0) {
40937
- return { runId: parsed.runId, ...Number.isInteger(parsed.pid) ? { pid: parsed.pid } : {} };
40938
- }
40932
+ if (typeof parsed.runId === "string" && parsed.runId.length > 0) return parsed.runId;
40939
40933
  } catch {
40940
40934
  }
40941
40935
  }
40942
40936
  return null;
40943
40937
  }
40944
- function isRenderProcess(pid) {
40945
- try {
40946
- return readFileSync14(`/proc/${pid}/cmdline`, "utf8").includes("canvas");
40947
- } catch {
40948
- return false;
40949
- }
40950
- }
40951
40938
  async function markRunInFlight(outputsDir, canvasPath, runId) {
40952
40939
  try {
40953
40940
  const file = markerFile(outputsDir, markerKey(canvasPath));
40954
40941
  await mkdir4(path13.dirname(file), { recursive: true });
40955
- await writeFile6(file, JSON.stringify({ runId, pid: process.pid, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
40942
+ await writeFile6(file, JSON.stringify({ runId, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
40956
40943
  } catch {
40957
40944
  }
40958
40945
  }
@@ -41910,31 +41897,13 @@ ${describeRewrites(healed.rewrites)}
41910
41897
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
41911
41898
  const client = opts.record === false ? null : buildBackendClient();
41912
41899
  const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : path16.resolve("canvas");
41913
- const { runId, resumed, source, concurrentRunId, rendering } = await resolveRunId({
41900
+ const { runId, resumed, source, concurrentRunId } = await resolveRunId({
41914
41901
  explicitRunId: opts.runId,
41915
41902
  fresh: opts.fresh === true,
41916
41903
  outputsDir,
41917
41904
  canvasPath: filePath,
41918
41905
  remote: client && creativeSlug ? { creativeSlug, canvasSha, getActiveRun: (slug, sha) => client.getActiveRun(slug, sha) } : void 0
41919
41906
  });
41920
- if (rendering) {
41921
- process.stderr.write(
41922
- `${JSON.stringify(
41923
- {
41924
- ok: false,
41925
- error: {
41926
- code: "CONFLICT",
41927
- message: `This canvas is already rendering in another process (run ${rendering.runId}, pid ${rendering.pid}).`,
41928
- fix: "Wait for that render to finish and use its result instead of starting a second one: two renders of one canvas share a run and overwrite each other. If you started it in the background, read its output when it completes."
41929
- }
41930
- },
41931
- null,
41932
- 2
41933
- )}
41934
- `
41935
- );
41936
- process.exit(2);
41937
- }
41938
41907
  if (resumed) {
41939
41908
  process.stdout.write(
41940
41909
  `[resume] continuing interrupted run ${runId}${source === "remote" ? " (adopted from run history)" : ""} \u2014 in-flight jobs re-attach, cached nodes skip
@@ -42872,12 +42841,12 @@ function fail3(code, message) {
42872
42841
  process.exit(2);
42873
42842
  }
42874
42843
  function resolveModels(args5) {
42875
- const pick = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel(kind, fallback);
42844
+ const pick2 = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel(kind, fallback);
42876
42845
  return {
42877
- describeModel: pick("describe-model", "image_describe", "~google/gemini-pro-latest"),
42878
- selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
42879
- layoutModel: pick("layout-model", "text_generate", "~google/gemini-flash-latest"),
42880
- genModel: pick("gen-model", "image_generate", "openai/gpt-image-2")
42846
+ describeModel: pick2("describe-model", "image_describe", "~google/gemini-pro-latest"),
42847
+ selectModel: pick2("select-model", "text_generate", "~google/gemini-flash-latest"),
42848
+ layoutModel: pick2("layout-model", "text_generate", "~google/gemini-flash-latest"),
42849
+ genModel: pick2("gen-model", "image_generate", "openai/gpt-image-2")
42881
42850
  };
42882
42851
  }
42883
42852
  var PLATFORM_PLACEMENTS = {
@@ -44897,18 +44866,18 @@ function parseBudget(raw) {
44897
44866
  throw new Error(`--budget must be one of ${VIDEO_BUDGETS.join(", ")} (got "${v}")`);
44898
44867
  }
44899
44868
  function resolveModels2(args5) {
44900
- const pick = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel2(kind, fallback);
44869
+ const pick2 = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel2(kind, fallback);
44901
44870
  return {
44902
44871
  // Flash by default: ~2-3× faster per call than Pro, which keeps each
44903
44872
  // per-scene deconstruct step well inside the action time budget and turns a
44904
44873
  // ~9 min run into ~3-4 min. Override with --deconstruct-model
44905
44874
  // ~google/gemini-pro-latest for the densest extraction when speed matters less.
44906
- deconstructModel: pick("deconstruct-model", "video_deconstruct", "~google/gemini-flash-latest"),
44907
- selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
44875
+ deconstructModel: pick2("deconstruct-model", "video_deconstruct", "~google/gemini-flash-latest"),
44876
+ selectModel: pick2("select-model", "text_generate", "~google/gemini-flash-latest"),
44908
44877
  // Default to the strongest image model (matches the static-ad scaffold); the
44909
44878
  // frame generators need the most faithful text/identity reproduction. Override
44910
44879
  // with --image-model for a cheaper/faster pass.
44911
- imageModel: pick("image-model", "image_generate", "openai/gpt-image-2.5-sunburst")
44880
+ imageModel: pick2("image-model", "image_generate", "openai/gpt-image-2.5-sunburst")
44912
44881
  };
44913
44882
  }
44914
44883
  function hasPhotorealCast(elements) {
@@ -48288,11 +48257,11 @@ var addSideEffectCommand = defineCommand125({
48288
48257
  });
48289
48258
 
48290
48259
  // src/commands/flows/map.ts
48291
- import { readFileSync as readFileSync16 } from "fs";
48260
+ import { readFileSync as readFileSync15 } from "fs";
48292
48261
  import { defineCommand as defineCommand126 } from "citty";
48293
48262
 
48294
48263
  // src/commands/flows/value-expression.ts
48295
- import { existsSync as existsSync6, readFileSync as readFileSync15 } from "fs";
48264
+ import { existsSync as existsSync6, readFileSync as readFileSync14 } from "fs";
48296
48265
  import { join as join4 } from "path";
48297
48266
  var PREFIXES2 = ["field", "tracking", "global", "code"];
48298
48267
  function splitParts(raw) {
@@ -48379,7 +48348,7 @@ function trackingFieldIds() {
48379
48348
  const path48 = join4(flowsDir(), "..", "tracking.ts");
48380
48349
  if (!existsSync6(path48)) return null;
48381
48350
  try {
48382
- const source = readFileSync15(path48, "utf-8");
48351
+ const source = readFileSync14(path48, "utf-8");
48383
48352
  const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
48384
48353
  if (!block2) return null;
48385
48354
  const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
@@ -48956,7 +48925,7 @@ function specsFromFile(parsed) {
48956
48925
  function readSpecFile(path48) {
48957
48926
  let raw;
48958
48927
  try {
48959
- raw = path48 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path48, "utf-8");
48928
+ raw = path48 === "-" ? readFileSync15(0, "utf-8") : readFileSync15(path48, "utf-8");
48960
48929
  } catch (error) {
48961
48930
  refuse(
48962
48931
  `Could not read ${path48 === "-" ? "the mapping from stdin" : `"${path48}"`}: ${error instanceof Error ? error.message : String(error)}`
@@ -49655,7 +49624,7 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
49655
49624
  });
49656
49625
 
49657
49626
  // src/commands/funnel/index.ts
49658
- import { readFileSync as readFileSync17 } from "fs";
49627
+ import { readFileSync as readFileSync16 } from "fs";
49659
49628
  import { defineCommand as defineCommand130 } from "citty";
49660
49629
 
49661
49630
  // src/commands/funnel/formMoments.ts
@@ -50451,7 +50420,7 @@ function workspaceForms() {
50451
50420
  const forms = [];
50452
50421
  for (const slug of listFlowSlugs()) {
50453
50422
  try {
50454
- forms.push({ slug, tree: JSON.parse(readFileSync17(flowDataPath(slug), "utf-8")) });
50423
+ forms.push({ slug, tree: JSON.parse(readFileSync16(flowDataPath(slug), "utf-8")) });
50455
50424
  } catch {
50456
50425
  }
50457
50426
  }
@@ -50586,7 +50555,7 @@ Examples:
50586
50555
  import { defineCommand as defineCommand132 } from "citty";
50587
50556
 
50588
50557
  // src/commands/ga4/shared.ts
50589
- import { readFileSync as readFileSync18 } from "fs";
50558
+ import { readFileSync as readFileSync17 } from "fs";
50590
50559
  function failValidation3(message) {
50591
50560
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
50592
50561
  process.exit(1);
@@ -50602,7 +50571,7 @@ function requireTarget5(args5, entity) {
50602
50571
  function readJsonSource(args5, flag) {
50603
50572
  const inline = args5[flag];
50604
50573
  const file = args5.file;
50605
- const raw = typeof file === "string" && file.length > 0 ? readFileSync18(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
50574
+ const raw = typeof file === "string" && file.length > 0 ? readFileSync17(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
50606
50575
  if (raw === void 0) {
50607
50576
  failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
50608
50577
  }
@@ -50953,7 +50922,7 @@ Examples:
50953
50922
  });
50954
50923
 
50955
50924
  // src/commands/ga4/query.ts
50956
- import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync19, writeFileSync as writeFileSync4 } from "fs";
50925
+ import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync18, writeFileSync as writeFileSync4 } from "fs";
50957
50926
  import { resolve as resolve2 } from "path";
50958
50927
  import { defineCommand as defineCommand135 } from "citty";
50959
50928
 
@@ -51044,7 +51013,7 @@ function writeRowsToFile2(filePath, rows, append) {
51044
51013
  writeFileSync4(filePath, content, "utf-8");
51045
51014
  }
51046
51015
  } else if (append && existsSync7(filePath)) {
51047
- const existing = JSON.parse(readFileSync19(filePath, "utf-8"));
51016
+ const existing = JSON.parse(readFileSync18(filePath, "utf-8"));
51048
51017
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
51049
51018
  } else {
51050
51019
  writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -51896,7 +51865,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
51896
51865
  import { defineCommand as defineCommand141 } from "citty";
51897
51866
 
51898
51867
  // src/commands/gsc/query.ts
51899
- import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync20, writeFileSync as writeFileSync5 } from "fs";
51868
+ import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync5 } from "fs";
51900
51869
  import { resolve as resolve3 } from "path";
51901
51870
  import { defineCommand as defineCommand138 } from "citty";
51902
51871
 
@@ -52044,7 +52013,7 @@ function writeRowsToFile3(filePath, rows, append) {
52044
52013
  writeFileSync5(filePath, content, "utf-8");
52045
52014
  }
52046
52015
  } else if (append && existsSync8(filePath)) {
52047
- const existing = JSON.parse(readFileSync20(filePath, "utf-8"));
52016
+ const existing = JSON.parse(readFileSync19(filePath, "utf-8"));
52048
52017
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
52049
52018
  } else {
52050
52019
  writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -65678,7 +65647,7 @@ import { defineCommand as defineCommand221 } from "citty";
65678
65647
  import { defineCommand as defineCommand218 } from "citty";
65679
65648
 
65680
65649
  // src/commands/tag-manager/shared.ts
65681
- import { readFileSync as readFileSync21 } from "fs";
65650
+ import { readFileSync as readFileSync20 } from "fs";
65682
65651
  function failValidation5(message) {
65683
65652
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
65684
65653
  process.exit(1);
@@ -65694,7 +65663,7 @@ function requireTarget6(args5, entity) {
65694
65663
  function loadJsonArg2(args5, flag = "json") {
65695
65664
  const inline = args5[flag];
65696
65665
  const file = args5.file;
65697
- const raw = typeof file === "string" && file.length > 0 ? readFileSync21(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
65666
+ const raw = typeof file === "string" && file.length > 0 ? readFileSync20(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
65698
65667
  if (raw === void 0) {
65699
65668
  failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
65700
65669
  }
@@ -69096,8 +69065,136 @@ function outputFlagForCommand(root, argv) {
69096
69065
  });
69097
69066
  }
69098
69067
 
69068
+ // src/field-mask.ts
69069
+ var FLAG2 = "--fields";
69070
+ function parseFields(value) {
69071
+ return value.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
69072
+ }
69073
+ function takeFieldsFlag(root, argv) {
69074
+ const end = argv.indexOf("--");
69075
+ const limit = end === -1 ? argv.length : end;
69076
+ const taken = /* @__PURE__ */ new Set();
69077
+ const fields = [];
69078
+ for (let index = 0; index < limit; index++) {
69079
+ const token = argv[index] ?? "";
69080
+ if (token.startsWith(`${FLAG2}=`)) {
69081
+ taken.add(index);
69082
+ fields.push(...parseFields(token.slice(FLAG2.length + 1)));
69083
+ } else if (token === FLAG2) {
69084
+ const value = argv[index + 1];
69085
+ if (value === void 0 || index + 1 >= limit || value.startsWith("-")) {
69086
+ return { argv, fields: null };
69087
+ }
69088
+ taken.add(index).add(index + 1);
69089
+ fields.push(...parseFields(value));
69090
+ index++;
69091
+ }
69092
+ }
69093
+ if (taken.size === 0 || fields.length === 0) {
69094
+ return { argv, fields: null };
69095
+ }
69096
+ const command = commandFor(root, argv);
69097
+ if (!command || declaredArg(command, "fields") || PRINTS_NO_ENVELOPE.has(commandPathOf(root, argv))) {
69098
+ return { argv, fields: null };
69099
+ }
69100
+ return { argv: argv.filter((_, index) => !taken.has(index)), fields };
69101
+ }
69102
+ function isRecord3(value) {
69103
+ return typeof value === "object" && value !== null && !Array.isArray(value);
69104
+ }
69105
+ function pick(record, fields) {
69106
+ return Object.fromEntries(fields.filter((field) => field in record).map((field) => [field, record[field]]));
69107
+ }
69108
+ function wrappedList(data, fields) {
69109
+ if (fields.some((field) => field in data)) {
69110
+ return null;
69111
+ }
69112
+ const lists = Object.entries(data).filter(
69113
+ ([, value]) => Array.isArray(value) && value.every((item) => isRecord3(item))
69114
+ );
69115
+ return lists.length === 1 ? lists[0]?.[0] ?? null : null;
69116
+ }
69117
+ function recordsOf(data, fields) {
69118
+ if (Array.isArray(data)) {
69119
+ return data;
69120
+ }
69121
+ if (!isRecord3(data)) {
69122
+ return [];
69123
+ }
69124
+ const list = wrappedList(data, fields);
69125
+ return list === null ? [data] : data[list];
69126
+ }
69127
+ function maskData(data, fields) {
69128
+ const mask = (item) => isRecord3(item) ? pick(item, fields) : item;
69129
+ if (Array.isArray(data)) {
69130
+ return data.map(mask);
69131
+ }
69132
+ if (!isRecord3(data)) {
69133
+ return data;
69134
+ }
69135
+ const list = wrappedList(data, fields);
69136
+ return list === null ? pick(data, fields) : { ...data, [list]: recordsOf(data, fields).map(mask) };
69137
+ }
69138
+ function unmatchedHint(data, fields) {
69139
+ const records = recordsOf(data, fields).filter(isRecord3);
69140
+ if (records.length === 0) {
69141
+ return null;
69142
+ }
69143
+ const carried = new Set(records.flatMap((record) => Object.keys(record)));
69144
+ const unmatched = fields.filter((field) => !carried.has(field));
69145
+ if (unmatched.length === 0) {
69146
+ return null;
69147
+ }
69148
+ return `--fields matched nothing for: ${unmatched.join(", ")}. The keys data carries are: ${[...carried].join(", ")}.`;
69149
+ }
69150
+ function maskPrintedEnvelope(text2, fields) {
69151
+ let parsed;
69152
+ try {
69153
+ parsed = JSON.parse(text2);
69154
+ } catch {
69155
+ return null;
69156
+ }
69157
+ if (!isRecord3(parsed) || typeof parsed.ok !== "boolean") {
69158
+ return null;
69159
+ }
69160
+ if (parsed.ok !== true || !("data" in parsed) || "dryRun" in parsed) {
69161
+ return text2;
69162
+ }
69163
+ const masked = { ...parsed, data: maskData(parsed.data, fields) };
69164
+ const miss = unmatchedHint(parsed.data, fields);
69165
+ if (miss) {
69166
+ masked.hints = [...Array.isArray(parsed.hints) ? parsed.hints : [], miss];
69167
+ }
69168
+ const indent = text2.trimStart().startsWith("{\n") ? 2 : void 0;
69169
+ return `${JSON.stringify(masked, null, indent)}${text2.endsWith("\n") ? "\n" : ""}`;
69170
+ }
69171
+ function maskWrites(stream, fields) {
69172
+ let applied = false;
69173
+ const write = stream.write.bind(stream);
69174
+ stream.write = (chunk, ...rest) => {
69175
+ const masked = typeof chunk === "string" ? maskPrintedEnvelope(chunk, fields) : null;
69176
+ if (masked === null) {
69177
+ return write(chunk, ...rest);
69178
+ }
69179
+ applied = true;
69180
+ return write(masked, ...rest);
69181
+ };
69182
+ return { sawEnvelope: () => applied };
69183
+ }
69184
+ function installFieldMask(fields, commandPath) {
69185
+ const mask = maskWrites(process.stdout, fields);
69186
+ process.on("exit", () => {
69187
+ if (!mask.sawEnvelope()) {
69188
+ process.stderr.write(
69189
+ `--fields was not applied: \`baker ${commandPath}\` printed no JSON envelope to narrow. Add --output json to get the envelope, or drop --fields.
69190
+ `
69191
+ );
69192
+ }
69193
+ });
69194
+ }
69195
+
69099
69196
  // src/version.ts
69100
- import { readFileSync as readFileSync22 } from "fs";
69197
+ import { readFileSync as readFileSync21 } from "fs";
69101
69198
  function packageJsonUrl() {
69102
69199
  return new URL("../package.json", import.meta.url);
69103
69200
  }
@@ -69109,7 +69206,7 @@ function parsePackageVersion(raw) {
69109
69206
  throw new Error("Invalid CLI package.json: missing version");
69110
69207
  }
69111
69208
  function getCliVersion() {
69112
- return parsePackageVersion(readFileSync22(packageJsonUrl(), "utf8"));
69209
+ return parsePackageVersion(readFileSync21(packageJsonUrl(), "utf8"));
69113
69210
  }
69114
69211
 
69115
69212
  // src/cli.ts
@@ -69122,6 +69219,7 @@ var main = defineCommand248({
69122
69219
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
69123
69220
  Chat: Set BAKER_CHAT_ID for action and scheduled-agent commands that stage changes against a chat.
69124
69221
  Output: All commands return JSON envelopes: { ok: true, data: ... } or { ok: false, error: { code, message } }.
69222
+ Fields: --fields a,b,c keeps only those keys of each record in data, on every command that prints the envelope.
69125
69223
  Formats: --output json works on every command that prints the envelope. --output md|files only where 'baker schema <command>' lists output. (The research commands additionally accept csv and jsonl.)
69126
69224
  Introspection: Run 'baker schema <command>' to inspect argument schemas.`
69127
69225
  },
@@ -69161,6 +69259,11 @@ installStreamTaps();
69161
69259
  logInvocation(process.argv.slice(2));
69162
69260
  installExitRecord();
69163
69261
  process.argv = [...process.argv.slice(0, 2), ...outputFlagForCommand(main, process.argv.slice(2))];
69262
+ var fieldsFlag = takeFieldsFlag(main, process.argv.slice(2));
69263
+ if (fieldsFlag.fields) {
69264
+ process.argv = [...process.argv.slice(0, 2), ...fieldsFlag.argv];
69265
+ installFieldMask(fieldsFlag.fields, commandPathOf(main, fieldsFlag.argv));
69266
+ }
69164
69267
  refuseUnknownFlags(main, process.argv.slice(2));
69165
69268
  process.argv = [...process.argv.slice(0, 2), ...cacheFlagForParser(process.argv.slice(2))];
69166
69269
  runMain(main);