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

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
@@ -3567,7 +3567,6 @@ See everything a chat can reach — managed integrations, custom servers, and co
3567
3567
  baker mcp connected
3568
3568
  baker mcp list
3569
3569
  baker mcp add --name weather --url https://mcp.example.com/mcp
3570
- baker mcp add --name acme --url https://acme.dev/mcp --header "Authorization: Bearer sk-…"
3571
3570
  baker mcp add --name mine --url https://my.dev/mcp --scope user
3572
3571
  baker mcp remove --name weather
3573
3572
  ```
@@ -3579,7 +3578,7 @@ baker mcp remove --name weather
3579
3578
  - `--scope org` — everyone across the org; needs an admin API key.
3580
3579
  - `--scope user` — only you, in this company; binds to the current message sender (requires a chat turn — the bridge supplies the sender via `BAKER_ACTING_USER_ID`).
3581
3580
  - `--scope user_org` — only you, across every company in the org; also binds to the sender (no admin needed — it only affects your own turns).
3582
- - Repeat `--header "Key: Value"` for multiple auth headers. Header values are stored server-side and ride the MCP transport — `list` returns only the header keys, never the values.
3581
+ - Repeat `--header "Key: Value"` for extra request headers. Never pass a key, token or password with it, and never ask the user for one in chat: a server that needs a key is added by the user in the dashboard (Brain → Integrations → MCPs → Add custom server), where the model never sees it. Header values are stored server-side and ride the MCP transport — `list` returns only the header keys, never the values.
3583
3582
 
3584
3583
  ---
3585
3584
 
@@ -5420,7 +5419,7 @@ Validate, then execute the graph. Blocks until done. Logs one line per node. Ret
5420
5419
 
5421
5420
  **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
5421
 
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).
5422
+ **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
5423
 
5425
5424
  #### `baker canvas scaffold-video <video> [flags]`
5426
5425
 
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
@@ -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");
@@ -61827,7 +61796,7 @@ A tool or platform the user names that is NOT listed anywhere here is simply not
61827
61796
  );
61828
61797
  }
61829
61798
  hints2.push(
61830
- "Not listed anywhere = not connected. Managed app (Slack, Attio, \u2026) or platform (HubSpot, Google Ads, GA4, \u2026) \u2192 the user connects it in the dashboard: Brain \u2192 Integrations \u2192 Tools. Custom HTTPS MCP endpoint \u2192 `baker mcp add`."
61799
+ 'Not listed anywhere = not connected. Ask for it in the chat with the `request_connection` tool: { app: "Google Sheets", reason } for an app (Slack, Attio, Gmail, \u2026), { platform, reason } for a platform (HubSpot, Google Ads, GA4, \u2026), { server, url?, headerName?, reason } for a custom tool server \u2014 the user connects it on the card, key included. Never send them to the dashboard, and never ask for a key in chat.'
61831
61800
  );
61832
61801
  writeJson({
61833
61802
  ok: true,
@@ -61867,9 +61836,10 @@ var listCommand16 = defineCommand183({
61867
61836
  }
61868
61837
  }
61869
61838
  });
61839
+ var HEADER_DESCRIPTION = 'Extra request header "Key: Value" (repeatable). Never a key, token or password: never ask the user for one in chat \u2014 a server that needs a key is added by the user on the `request_connection` card ({ server, url, headerName, reason }).';
61870
61840
  registerSchema({
61871
61841
  command: "mcp.add",
61872
- description: "Register a custom MCP server. Tools appear as mcp__<name>__* on the next message. URL must be HTTPS. Scope: company (default, all chats) | org (org admin key) | user (only the current sender).",
61842
+ description: "Register a custom MCP server. To connect one FOR the user, call the `request_connection` tool with { server, url?, headerName?, reason } instead \u2014 they add it on the card, key included. Tools appear as mcp__<name>__* on the next message. URL must be HTTPS. Scope: company (default, all chats) | org (org admin key) | user (only the current sender).",
61873
61843
  args: {
61874
61844
  name: { type: "string", description: "Server name \u2192 tools appear as mcp__<name>__*", required: true },
61875
61845
  url: {
@@ -61878,7 +61848,7 @@ registerSchema({
61878
61848
  required: true
61879
61849
  },
61880
61850
  scope: { type: "string", description: "user | user_org | company | org (default company)", required: false },
61881
- header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
61851
+ header: { type: "string", description: HEADER_DESCRIPTION, required: false }
61882
61852
  }
61883
61853
  });
61884
61854
  var addCommand2 = defineCommand183({
@@ -61886,11 +61856,13 @@ var addCommand2 = defineCommand183({
61886
61856
  name: "add",
61887
61857
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
61888
61858
 
61859
+ To connect a server FOR the user, call the \`request_connection\` tool with { server, url?, headerName?, reason }
61860
+ instead: they add it on the card in the chat, key included, and you never see the key.
61861
+
61889
61862
  Scope: company (default \u2014 every chat in the company) | org (all companies in the org; needs an admin key) | user (only the current message sender).
61890
61863
 
61891
61864
  Examples:
61892
61865
  baker mcp add --name weather --url https://mcp.example.com/mcp
61893
- baker mcp add --name acme --url https://acme.dev/mcp --header "Authorization: Bearer sk-\u2026"
61894
61866
  baker mcp add --name mine --url https://my.dev/mcp --scope user`
61895
61867
  },
61896
61868
  args: {
@@ -61901,7 +61873,7 @@ Examples:
61901
61873
  required: true
61902
61874
  },
61903
61875
  scope: { type: "string", description: "user | user_org | company | org (default company)", required: false },
61904
- header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
61876
+ header: { type: "string", description: HEADER_DESCRIPTION, required: false }
61905
61877
  },
61906
61878
  run: async ({ args: args5, rawArgs }) => {
61907
61879
  try {
@@ -61968,7 +61940,6 @@ Start here:
61968
61940
 
61969
61941
  Examples:
61970
61942
  baker mcp add --name weather --url https://mcp.example.com/mcp
61971
- baker mcp add --name acme --url https://acme.dev/mcp --header "Authorization: Bearer sk-\u2026"
61972
61943
  baker mcp remove --name weather
61973
61944
  Full guide: __tooling__/docs/tools/baker/mcp.md`
61974
61945
  },
@@ -65678,7 +65649,7 @@ import { defineCommand as defineCommand221 } from "citty";
65678
65649
  import { defineCommand as defineCommand218 } from "citty";
65679
65650
 
65680
65651
  // src/commands/tag-manager/shared.ts
65681
- import { readFileSync as readFileSync21 } from "fs";
65652
+ import { readFileSync as readFileSync20 } from "fs";
65682
65653
  function failValidation5(message) {
65683
65654
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
65684
65655
  process.exit(1);
@@ -65694,7 +65665,7 @@ function requireTarget6(args5, entity) {
65694
65665
  function loadJsonArg2(args5, flag = "json") {
65695
65666
  const inline = args5[flag];
65696
65667
  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;
65668
+ const raw = typeof file === "string" && file.length > 0 ? readFileSync20(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
65698
65669
  if (raw === void 0) {
65699
65670
  failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
65700
65671
  }
@@ -69097,7 +69068,7 @@ function outputFlagForCommand(root, argv) {
69097
69068
  }
69098
69069
 
69099
69070
  // src/version.ts
69100
- import { readFileSync as readFileSync22 } from "fs";
69071
+ import { readFileSync as readFileSync21 } from "fs";
69101
69072
  function packageJsonUrl() {
69102
69073
  return new URL("../package.json", import.meta.url);
69103
69074
  }
@@ -69109,7 +69080,7 @@ function parsePackageVersion(raw) {
69109
69080
  throw new Error("Invalid CLI package.json: missing version");
69110
69081
  }
69111
69082
  function getCliVersion() {
69112
- return parsePackageVersion(readFileSync22(packageJsonUrl(), "utf8"));
69083
+ return parsePackageVersion(readFileSync21(packageJsonUrl(), "utf8"));
69113
69084
  }
69114
69085
 
69115
69086
  // src/cli.ts