@koda-sl/baker-cli 0.99.1 → 0.100.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 CHANGED
@@ -2354,7 +2354,7 @@ baker actions log --from 2026-06-01 --to 2026-06-15 # explicit ISO window (ove
2354
2354
  baker actions get <action-id>
2355
2355
  baker actions status temp_hero jx123 # batch resolve real IDs and temp_* refs
2356
2356
 
2357
- baker actions claim <action-id> # live — returns action details + skill-loading hints
2357
+ baker actions claim <action-id> # live — returns action details + a fast-model list of skills to load (recommendedSkills)
2358
2358
  baker actions release <action-id>
2359
2359
 
2360
2360
  baker actions create --name "Build hero" --priority high --tags landing,creative --description "..."
@@ -2417,7 +2417,7 @@ baker actions draft clear # drop everything staged in this cha
2417
2417
  Permissions enforced server-side:
2418
2418
 
2419
2419
  - Only `claim`/`release` mutate live state.
2420
- - `claim` returns action details (`id`, `name`, `description`) and a `hints` array recommending you review the action context and load relevant skills.
2420
+ - `claim` returns action details (`id`, `name`, `description`) plus `recommendedSkills` — a fast model reads the action's name/description/tags against the local `.claude/skills/` catalog and returns the skills (`{ name, reason }`) most worth loading for the work, echoed as `/skill — reason` lines in `hints`. It is best-effort: if the catalog is absent or the model call fails, the claim still succeeds and falls back to the generic "review and load relevant skills" hint.
2421
2421
  - `update`, `complete`, `discard`, `unlink` require the action to be claimed by the current chat — otherwise the API returns `FORBIDDEN` with a hint to claim first.
2422
2422
  - Claiming an action already claimed by another chat returns `CONFLICT` with the other chat's title — pick a different action.
2423
2423
  - All staged ops are reverted automatically when the chat is discarded.
package/dist/cli.js CHANGED
@@ -516,14 +516,140 @@ ${description}`;
516
516
  return SCHEDULE_SIGNALS.some((re) => re.test(haystack));
517
517
  }
518
518
 
519
+ // src/commands/actions/skillCatalog.ts
520
+ import { existsSync, readdirSync, readFileSync } from "fs";
521
+ import { dirname, join } from "path";
522
+ var DESCRIPTION_MAX = 600;
523
+ var SKILLS_SUBPATH = join(".claude", "skills");
524
+ var EXCLUDED_SKILLS = /* @__PURE__ */ new Set(["actions"]);
525
+ function stripQuotes(value) {
526
+ const trimmed = value.trim();
527
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
528
+ return trimmed.slice(1, -1).replace(/\\"/g, '"').replace(/\\n/g, "\n");
529
+ }
530
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
531
+ return trimmed.slice(1, -1).replace(/''/g, "'");
532
+ }
533
+ return trimmed;
534
+ }
535
+ function extractFrontmatterLines(md) {
536
+ if (!md.startsWith("---")) return null;
537
+ const end = md.indexOf("\n---", 3);
538
+ if (end === -1) return null;
539
+ return md.slice(md.indexOf("\n", 3) + 1, end).split("\n");
540
+ }
541
+ var BLOCK_SCALAR = /^([|>])[+-]?$/;
542
+ function collectBlockLines(lines, start) {
543
+ const collected = [];
544
+ for (let i = start; i < lines.length; i++) {
545
+ const line = lines[i] ?? "";
546
+ if (line.trim() === "") {
547
+ collected.push("");
548
+ } else if (/^\s/.test(line)) {
549
+ collected.push(line.trim());
550
+ } else {
551
+ break;
552
+ }
553
+ }
554
+ while (collected.length > 0 && collected.at(-1) === "") collected.pop();
555
+ return collected;
556
+ }
557
+ function foldLines(collected) {
558
+ const paragraphs = [];
559
+ let buffer = [];
560
+ for (const line of collected) {
561
+ if (line === "") {
562
+ if (buffer.length > 0) paragraphs.push(buffer.join(" "));
563
+ buffer = [];
564
+ } else {
565
+ buffer.push(line);
566
+ }
567
+ }
568
+ if (buffer.length > 0) paragraphs.push(buffer.join(" "));
569
+ return paragraphs.join("\n");
570
+ }
571
+ function readBlockScalar(lines, start, style) {
572
+ const collected = collectBlockLines(lines, start);
573
+ return style === "|" ? collected.join("\n") : foldLines(collected);
574
+ }
575
+ function readField(lines, field) {
576
+ for (let i = 0; i < lines.length; i++) {
577
+ const match = (lines[i] ?? "").match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
578
+ if (!match || match[1] !== field) continue;
579
+ const inline = (match[2] ?? "").trim();
580
+ const scalar = inline.match(BLOCK_SCALAR);
581
+ if (scalar) {
582
+ return readBlockScalar(lines, i + 1, scalar[1]);
583
+ }
584
+ return stripQuotes(inline);
585
+ }
586
+ return null;
587
+ }
588
+ function parseSkillFrontmatter(md) {
589
+ const lines = extractFrontmatterLines(md);
590
+ if (!lines) return null;
591
+ const name = readField(lines, "name");
592
+ const description = readField(lines, "description");
593
+ if (!name || !description) return null;
594
+ const trimmed = description.length > DESCRIPTION_MAX ? `${description.slice(0, DESCRIPTION_MAX)}\u2026` : description;
595
+ return { name, description: trimmed };
596
+ }
597
+ function findSkillsDir(startDir) {
598
+ let dir = startDir;
599
+ for (; ; ) {
600
+ const candidate = join(dir, SKILLS_SUBPATH);
601
+ if (existsSync(candidate)) return candidate;
602
+ const parent = dirname(dir);
603
+ if (parent === dir) return null;
604
+ dir = parent;
605
+ }
606
+ }
607
+ function readSkillCatalog(startDir) {
608
+ const skillsDir = findSkillsDir(startDir);
609
+ if (!skillsDir) return [];
610
+ const entries = [];
611
+ for (const dirent of readdirSync(skillsDir, { withFileTypes: true })) {
612
+ if (!dirent.isDirectory() || EXCLUDED_SKILLS.has(dirent.name)) continue;
613
+ const skillFile = join(skillsDir, dirent.name, "SKILL.md");
614
+ if (!existsSync(skillFile)) continue;
615
+ try {
616
+ const parsed = parseSkillFrontmatter(readFileSync(skillFile, "utf8"));
617
+ if (parsed) entries.push(parsed);
618
+ } catch {
619
+ }
620
+ }
621
+ return entries.sort((a, b) => a.name.localeCompare(b.name));
622
+ }
623
+
519
624
  // src/commands/actions/claim.ts
520
625
  registerSchema({
521
626
  command: "actions.claim",
522
- description: "Claim an action for the current chat (live \u2014 visible to other chats immediately). Returns action details with tags and description to help decide which skills to load.",
627
+ description: "Claim an action for the current chat (live \u2014 visible to other chats immediately). Returns action details plus a fast-model recommendation of which skills to load for the work (`recommendedSkills`).",
523
628
  args: {
524
629
  id: { type: "string", description: "Action ID", required: true }
525
630
  }
526
631
  });
632
+ async function recommendSkills(actionId) {
633
+ const skills = readSkillCatalog(process.cwd());
634
+ if (skills.length === 0) return [];
635
+ const response = await apiPost(
636
+ "/api/actions/recommend-skills",
637
+ { actionId, skills }
638
+ );
639
+ return response.data?.recommendations ?? [];
640
+ }
641
+ function buildHints(recommendations) {
642
+ if (recommendations.length === 0) {
643
+ return [
644
+ "Review the action name, description, and tags above \u2014 then load any skills that would help you complete this work."
645
+ ];
646
+ }
647
+ return [
648
+ "Recommended skills for this action (load the ones you'll use):",
649
+ ...recommendations.map((r) => ` /${r.name} \u2014 ${r.reason}`),
650
+ "Suggestions from the action's name/description/tags \u2014 load others if the work needs them."
651
+ ];
652
+ }
527
653
  var claimCommand = defineCommand({
528
654
  meta: {
529
655
  name: "claim",
@@ -545,10 +671,13 @@ var claimCommand = defineCommand({
545
671
  actionId: id,
546
672
  chatId
547
673
  });
548
- const hints = [
549
- "Review the action name, description, and tags above \u2014 then load any skills that would help you complete this work."
550
- ];
551
- writeJson({ ...response, hints });
674
+ let recommendedSkills = [];
675
+ try {
676
+ recommendedSkills = await recommendSkills(id);
677
+ } catch {
678
+ }
679
+ const data = response.data ? { ...response.data, recommendedSkills } : response.data;
680
+ writeJson({ ok: response.ok, data, hints: buildHints(recommendedSkills) });
552
681
  } catch (err) {
553
682
  failApi(err);
554
683
  }
@@ -1396,12 +1525,12 @@ import { defineCommand as defineCommand19 } from "citty";
1396
1525
 
1397
1526
  // src/commands/ads/cache.ts
1398
1527
  import { createHash } from "crypto";
1399
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
1528
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
1400
1529
  import { homedir } from "os";
1401
- import { join } from "path";
1402
- var CACHE_DIR = join(homedir(), ".baker", "cache", "ads");
1530
+ import { join as join2 } from "path";
1531
+ var CACHE_DIR = join2(homedir(), ".baker", "cache", "ads");
1403
1532
  function ensureDir(dir) {
1404
- if (!existsSync(dir)) {
1533
+ if (!existsSync2(dir)) {
1405
1534
  mkdirSync(dir, { recursive: true });
1406
1535
  }
1407
1536
  }
@@ -1409,17 +1538,17 @@ function hashKey(key) {
1409
1538
  return createHash("sha256").update(key).digest("hex").slice(0, 16);
1410
1539
  }
1411
1540
  function cachePath(category, key) {
1412
- const dir = join(CACHE_DIR, category);
1541
+ const dir = join2(CACHE_DIR, category);
1413
1542
  ensureDir(dir);
1414
- return join(dir, `${hashKey(key)}.json`);
1543
+ return join2(dir, `${hashKey(key)}.json`);
1415
1544
  }
1416
1545
  function cacheGet(category, key) {
1417
1546
  const path11 = cachePath(category, key);
1418
- if (!existsSync(path11)) {
1547
+ if (!existsSync2(path11)) {
1419
1548
  return null;
1420
1549
  }
1421
1550
  try {
1422
- const raw = readFileSync(path11, "utf-8");
1551
+ const raw = readFileSync2(path11, "utf-8");
1423
1552
  const entry = JSON.parse(raw);
1424
1553
  if (entry.expiresAt < Date.now()) {
1425
1554
  rmSync(path11, { force: true });
@@ -3166,7 +3295,7 @@ var library = defineCommand27({
3166
3295
  });
3167
3296
 
3168
3297
  // src/commands/ads/google/query.ts
3169
- import { appendFileSync, existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
3298
+ import { appendFileSync, existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
3170
3299
  import { resolve } from "path";
3171
3300
  import { defineCommand as defineCommand28 } from "citty";
3172
3301
 
@@ -3443,7 +3572,7 @@ function extractFields(rows) {
3443
3572
  function writeRowsToFile(filePath, rows, fields, append) {
3444
3573
  const ext = filePath.split(".").pop()?.toLowerCase();
3445
3574
  if (ext === "csv") {
3446
- if (!append || !existsSync2(filePath)) {
3575
+ if (!append || !existsSync3(filePath)) {
3447
3576
  writeFileSync2(filePath, `${toCsvRow(fields)}
3448
3577
  `, "utf-8");
3449
3578
  }
@@ -3452,15 +3581,15 @@ function writeRowsToFile(filePath, rows, fields, append) {
3452
3581
  `, "utf-8");
3453
3582
  } else if (ext === "jsonl") {
3454
3583
  const lines = rows.map((row) => JSON.stringify(row));
3455
- if (append && existsSync2(filePath)) {
3584
+ if (append && existsSync3(filePath)) {
3456
3585
  appendFileSync(filePath, `${lines.join("\n")}
3457
3586
  `, "utf-8");
3458
3587
  } else {
3459
3588
  writeFileSync2(filePath, `${lines.join("\n")}
3460
3589
  `, "utf-8");
3461
3590
  }
3462
- } else if (append && existsSync2(filePath)) {
3463
- const existing = JSON.parse(readFileSync2(filePath, "utf-8"));
3591
+ } else if (append && existsSync3(filePath)) {
3592
+ const existing = JSON.parse(readFileSync3(filePath, "utf-8"));
3464
3593
  writeFileSync2(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
3465
3594
  } else {
3466
3595
  writeFileSync2(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -4596,7 +4725,7 @@ Examples \u2014 common AI questions:
4596
4725
  });
4597
4726
 
4598
4727
  // src/commands/ads/linkedin/audience-size.ts
4599
- import { readFileSync as readFileSync3 } from "fs";
4728
+ import { readFileSync as readFileSync4 } from "fs";
4600
4729
  import { defineCommand as defineCommand33 } from "citty";
4601
4730
  function loadTargeting(args) {
4602
4731
  const inline = args.targeting;
@@ -4610,7 +4739,7 @@ function loadTargeting(args) {
4610
4739
  const file = args["targeting-file"];
4611
4740
  if (file) {
4612
4741
  try {
4613
- return JSON.parse(readFileSync3(file, "utf-8"));
4742
+ return JSON.parse(readFileSync4(file, "utf-8"));
4614
4743
  } catch (e) {
4615
4744
  handleLinkedinError(
4616
4745
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -4789,7 +4918,7 @@ Examples:
4789
4918
  });
4790
4919
 
4791
4920
  // src/commands/ads/linkedin/bid-pricing.ts
4792
- import { readFileSync as readFileSync4 } from "fs";
4921
+ import { readFileSync as readFileSync5 } from "fs";
4793
4922
  import { defineCommand as defineCommand35 } from "citty";
4794
4923
  function loadTargeting2(args) {
4795
4924
  const inline = args.targeting;
@@ -4803,7 +4932,7 @@ function loadTargeting2(args) {
4803
4932
  const file = args["targeting-file"];
4804
4933
  if (file) {
4805
4934
  try {
4806
- return JSON.parse(readFileSync4(file, "utf-8"));
4935
+ return JSON.parse(readFileSync5(file, "utf-8"));
4807
4936
  } catch (e) {
4808
4937
  handleLinkedinError(
4809
4938
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -5367,7 +5496,7 @@ Subcommands:
5367
5496
  });
5368
5497
 
5369
5498
  // src/commands/ads/linkedin/forecast.ts
5370
- import { readFileSync as readFileSync5 } from "fs";
5499
+ import { readFileSync as readFileSync6 } from "fs";
5371
5500
  import { defineCommand as defineCommand43 } from "citty";
5372
5501
  function loadTargeting3(args) {
5373
5502
  const inline = args.targeting;
@@ -5381,7 +5510,7 @@ function loadTargeting3(args) {
5381
5510
  const file = args["targeting-file"];
5382
5511
  if (file) {
5383
5512
  try {
5384
- return JSON.parse(readFileSync5(file, "utf-8"));
5513
+ return JSON.parse(readFileSync6(file, "utf-8"));
5385
5514
  } catch (e) {
5386
5515
  handleLinkedinError(
5387
5516
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -8849,7 +8978,7 @@ import { defineCommand as defineCommand83 } from "citty";
8849
8978
  import { execFile as execFile2 } from "child_process";
8850
8979
  import { mkdtemp, readdir as readdir2, readFile as readFile4, rm as rm2 } from "fs/promises";
8851
8980
  import { tmpdir } from "os";
8852
- import { join as join2 } from "path";
8981
+ import { join as join3 } from "path";
8853
8982
  import { promisify as promisify2 } from "util";
8854
8983
  var execFileAsync2 = promisify2(execFile2);
8855
8984
  var PYSCENEDETECT_THRESHOLD = 18;
@@ -8892,7 +9021,7 @@ function parsePySceneDetectCsvCuts(csv) {
8892
9021
  return [...new Set(cuts)].sort((a, b) => a - b);
8893
9022
  }
8894
9023
  async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs) {
8895
- const outDir = await mkdtemp(join2(tmpdir(), "baker-scenedetect-"));
9024
+ const outDir = await mkdtemp(join3(tmpdir(), "baker-scenedetect-"));
8896
9025
  try {
8897
9026
  await execFileAsync2(
8898
9027
  "scenedetect",
@@ -8913,7 +9042,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
8913
9042
  );
8914
9043
  const csvName = (await readdir2(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
8915
9044
  if (!csvName) return [];
8916
- return parsePySceneDetectCsvCuts(await readFile4(join2(outDir, csvName), "utf-8"));
9045
+ return parsePySceneDetectCsvCuts(await readFile4(join3(outDir, csvName), "utf-8"));
8917
9046
  } finally {
8918
9047
  await rm2(outDir, { recursive: true, force: true });
8919
9048
  }
@@ -11012,15 +11141,15 @@ function xfadeSpineArgs(clips) {
11012
11141
  let cur = "c0";
11013
11142
  let accLen = clipInputLen(clips[0]);
11014
11143
  for (let k = 0; k < n - 1; k++) {
11015
- const join4 = clips[k].out;
11144
+ const join5 = clips[k].out;
11016
11145
  const next = `c${k + 1}`;
11017
11146
  const out = k === n - 2 ? "v" : `j${k + 1}`;
11018
- if (join4) {
11019
- const offset = Math.max(0, accLen - join4.dur);
11147
+ if (join5) {
11148
+ const offset = Math.max(0, accLen - join5.dur);
11020
11149
  filt.push(
11021
- `[${cur}][${next}]xfade=transition=${join4.xfade}:duration=${join4.dur.toFixed(3)}:offset=${offset.toFixed(3)}[${out}]`
11150
+ `[${cur}][${next}]xfade=transition=${join5.xfade}:duration=${join5.dur.toFixed(3)}:offset=${offset.toFixed(3)}[${out}]`
11022
11151
  );
11023
- accLen = accLen - join4.dur + clipInputLen(clips[k + 1]);
11152
+ accLen = accLen - join5.dur + clipInputLen(clips[k + 1]);
11024
11153
  } else {
11025
11154
  filt.push(`[${cur}][${next}]concat=n=2:v=1[${out}]`);
11026
11155
  accLen += clipInputLen(clips[k + 1]);
@@ -11457,9 +11586,9 @@ function videoReport(input, elementsInput) {
11457
11586
  }
11458
11587
 
11459
11588
  // src/commands/canvas/composition-path.ts
11460
- import { existsSync as existsSync3 } from "fs";
11589
+ import { existsSync as existsSync4 } from "fs";
11461
11590
  import path6 from "path";
11462
- function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
11591
+ function resolveShippedCanvasDir(name, startDir, exists = existsSync4, maxDepth = 8) {
11463
11592
  const rel = path6.join("canvas", name);
11464
11593
  let dir = startDir;
11465
11594
  for (let i = 0; i < maxDepth; i++) {
@@ -12323,7 +12452,7 @@ Examples:
12323
12452
  });
12324
12453
 
12325
12454
  // src/commands/ga4/query.ts
12326
- import { appendFileSync as appendFileSync2, existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
12455
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
12327
12456
  import { resolve as resolve2 } from "path";
12328
12457
  import { defineCommand as defineCommand91 } from "citty";
12329
12458
 
@@ -12397,7 +12526,7 @@ function writeRowsToFile2(filePath, rows, append) {
12397
12526
  const fields = extractFields2(rows);
12398
12527
  const ext = filePath.split(".").pop()?.toLowerCase();
12399
12528
  if (ext === "csv") {
12400
- if (!append || !existsSync4(filePath)) {
12529
+ if (!append || !existsSync5(filePath)) {
12401
12530
  writeFileSync4(filePath, `${toCsvRow(fields)}
12402
12531
  `, "utf-8");
12403
12532
  }
@@ -12408,13 +12537,13 @@ function writeRowsToFile2(filePath, rows, append) {
12408
12537
  const lines = rows.map((row) => JSON.stringify(row));
12409
12538
  const content = `${lines.join("\n")}
12410
12539
  `;
12411
- if (append && existsSync4(filePath)) {
12540
+ if (append && existsSync5(filePath)) {
12412
12541
  appendFileSync2(filePath, content, "utf-8");
12413
12542
  } else {
12414
12543
  writeFileSync4(filePath, content, "utf-8");
12415
12544
  }
12416
- } else if (append && existsSync4(filePath)) {
12417
- const existing = JSON.parse(readFileSync6(filePath, "utf-8"));
12545
+ } else if (append && existsSync5(filePath)) {
12546
+ const existing = JSON.parse(readFileSync7(filePath, "utf-8"));
12418
12547
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
12419
12548
  } else {
12420
12549
  writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -12554,7 +12683,7 @@ Examples:
12554
12683
  import { defineCommand as defineCommand96 } from "citty";
12555
12684
 
12556
12685
  // src/commands/gsc/query.ts
12557
- import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
12686
+ import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
12558
12687
  import { resolve as resolve3 } from "path";
12559
12688
  import { defineCommand as defineCommand93 } from "citty";
12560
12689
 
@@ -12683,7 +12812,7 @@ function writeRowsToFile3(filePath, rows, append) {
12683
12812
  const fields = extractFields3(rows);
12684
12813
  const ext = filePath.split(".").pop()?.toLowerCase();
12685
12814
  if (ext === "csv") {
12686
- if (!append || !existsSync5(filePath)) {
12815
+ if (!append || !existsSync6(filePath)) {
12687
12816
  writeFileSync5(filePath, `${toCsvRow(fields)}
12688
12817
  `, "utf-8");
12689
12818
  }
@@ -12693,13 +12822,13 @@ function writeRowsToFile3(filePath, rows, append) {
12693
12822
  } else if (ext === "jsonl") {
12694
12823
  const content = `${rows.map((row) => JSON.stringify(row)).join("\n")}
12695
12824
  `;
12696
- if (append && existsSync5(filePath)) {
12825
+ if (append && existsSync6(filePath)) {
12697
12826
  appendFileSync3(filePath, content, "utf-8");
12698
12827
  } else {
12699
12828
  writeFileSync5(filePath, content, "utf-8");
12700
12829
  }
12701
- } else if (append && existsSync5(filePath)) {
12702
- const existing = JSON.parse(readFileSync7(filePath, "utf-8"));
12830
+ } else if (append && existsSync6(filePath)) {
12831
+ const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
12703
12832
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
12704
12833
  } else {
12705
12834
  writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -12979,7 +13108,7 @@ function cropSprite(input, region) {
12979
13108
  // src/lib/image/io.ts
12980
13109
  import { randomBytes } from "crypto";
12981
13110
  import { glob as fsGlob, readFile as readFile10, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
12982
- import { dirname, extname as extname2, join as join3, resolve as resolve4 } from "path";
13111
+ import { dirname as dirname2, extname as extname2, join as join4, resolve as resolve4 } from "path";
12983
13112
  var REMOTE_RE = /^https?:\/\//i;
12984
13113
  var GLOB_RE = /[*?[\]{}]/;
12985
13114
  function isRemoteUrl(value) {
@@ -13029,14 +13158,14 @@ async function resolveOutputPath(inputPath, outputArg, options) {
13029
13158
  if (!outputArg) return base;
13030
13159
  if (options.multipleInputs || await isDirectory(outputArg)) {
13031
13160
  const filename = base.split("/").pop() ?? "out.png";
13032
- return join3(outputArg, filename);
13161
+ return join4(outputArg, filename);
13033
13162
  }
13034
13163
  return outputArg;
13035
13164
  }
13036
13165
  async function atomicWrite(targetPath, data) {
13037
13166
  const absolute = resolve4(targetPath);
13038
- const dir = dirname(absolute);
13039
- const tmp = join3(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
13167
+ const dir = dirname2(absolute);
13168
+ const tmp = join4(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
13040
13169
  await writeFile4(tmp, data);
13041
13170
  await rename(tmp, absolute);
13042
13171
  }
@@ -17761,7 +17890,7 @@ Examples:
17761
17890
  });
17762
17891
 
17763
17892
  // src/version.ts
17764
- import { readFileSync as readFileSync8 } from "fs";
17893
+ import { readFileSync as readFileSync9 } from "fs";
17765
17894
  function packageJsonUrl() {
17766
17895
  return new URL("../package.json", import.meta.url);
17767
17896
  }
@@ -17773,7 +17902,7 @@ function parsePackageVersion(raw) {
17773
17902
  throw new Error("Invalid CLI package.json: missing version");
17774
17903
  }
17775
17904
  function getCliVersion() {
17776
- return parsePackageVersion(readFileSync8(packageJsonUrl(), "utf8"));
17905
+ return parsePackageVersion(readFileSync9(packageJsonUrl(), "utf8"));
17777
17906
  }
17778
17907
 
17779
17908
  // src/cli.ts