@koda-sl/baker-cli 0.99.1 → 0.100.0-dev.63a14d2d
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 +2 -2
- package/dist/{chunk-3JVYU72O.js → chunk-26K7V346.js} +4 -4
- package/dist/chunk-26K7V346.js.map +1 -0
- package/dist/cli.js +216 -82
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3JVYU72O.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
defaultRegistry,
|
|
10
10
|
generateCatalog,
|
|
11
11
|
validateCanvasDeep
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-26K7V346.js";
|
|
13
13
|
|
|
14
14
|
// src/cli.ts
|
|
15
15
|
import { defineCommand as defineCommand152, runMain } from "citty";
|
|
@@ -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
|
|
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
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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 =
|
|
1530
|
+
import { join as join2 } from "path";
|
|
1531
|
+
var CACHE_DIR = join2(homedir(), ".baker", "cache", "ads");
|
|
1403
1532
|
function ensureDir(dir) {
|
|
1404
|
-
if (!
|
|
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 =
|
|
1541
|
+
const dir = join2(CACHE_DIR, category);
|
|
1413
1542
|
ensureDir(dir);
|
|
1414
|
-
return
|
|
1543
|
+
return join2(dir, `${hashKey(key)}.json`);
|
|
1415
1544
|
}
|
|
1416
1545
|
function cacheGet(category, key) {
|
|
1417
1546
|
const path11 = cachePath(category, key);
|
|
1418
|
-
if (!
|
|
1547
|
+
if (!existsSync2(path11)) {
|
|
1419
1548
|
return null;
|
|
1420
1549
|
}
|
|
1421
1550
|
try {
|
|
1422
|
-
const raw =
|
|
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
|
|
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 || !
|
|
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 &&
|
|
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 &&
|
|
3463
|
-
const existing = JSON.parse(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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 (
|
|
11019
|
-
const offset = Math.max(0, accLen -
|
|
11147
|
+
if (join5) {
|
|
11148
|
+
const offset = Math.max(0, accLen - join5.dur);
|
|
11020
11149
|
filt.push(
|
|
11021
|
-
`[${cur}][${next}]xfade=transition=${
|
|
11150
|
+
`[${cur}][${next}]xfade=transition=${join5.xfade}:duration=${join5.dur.toFixed(3)}:offset=${offset.toFixed(3)}[${out}]`
|
|
11022
11151
|
);
|
|
11023
|
-
accLen = accLen -
|
|
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
|
|
11589
|
+
import { existsSync as existsSync4 } from "fs";
|
|
11461
11590
|
import path6 from "path";
|
|
11462
|
-
function resolveShippedCanvasDir(name, startDir, exists =
|
|
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++) {
|
|
@@ -12015,8 +12144,8 @@ async function uploadLocalImage(args, deps = defaultImageApiDeps) {
|
|
|
12015
12144
|
function getImage(deps, imageId) {
|
|
12016
12145
|
return deps.get("/api/images/get", { id: imageId });
|
|
12017
12146
|
}
|
|
12018
|
-
function
|
|
12019
|
-
return deps.post("/api/
|
|
12147
|
+
function publishImageAsCreative(deps, args) {
|
|
12148
|
+
return deps.post("/api/creatives/publish", args);
|
|
12020
12149
|
}
|
|
12021
12150
|
async function waitForReadyImage(deps, imageId, opts = {}) {
|
|
12022
12151
|
const timeoutMs = opts.timeoutMs ?? imageProcessingTimeoutMs;
|
|
@@ -12038,15 +12167,19 @@ async function waitForReadyImage(deps, imageId, opts = {}) {
|
|
|
12038
12167
|
}
|
|
12039
12168
|
|
|
12040
12169
|
// src/commands/creatives/publish.ts
|
|
12041
|
-
var creativeTag = "creative";
|
|
12042
12170
|
var creativeContentTypes = ["image/png", "image/jpeg", "image/webp"];
|
|
12043
12171
|
registerSchema({
|
|
12044
12172
|
command: "creatives.publish",
|
|
12045
|
-
description: "Publish a final static creative image to Baker
|
|
12173
|
+
description: "Publish a final static creative image to Baker Creatives and return a creative reference.",
|
|
12046
12174
|
args: {
|
|
12047
12175
|
file: { type: "string", description: "Local PNG/JPG/WebP creative image path", required: true },
|
|
12048
12176
|
title: { type: "string", description: "Human title for the creative output", required: true },
|
|
12049
|
-
context: { type: "string", description: "Optional describe context for the image
|
|
12177
|
+
context: { type: "string", description: "Optional describe context for the image asset", required: false },
|
|
12178
|
+
sourceReferenceUrl: {
|
|
12179
|
+
type: "string",
|
|
12180
|
+
description: "Optional URL of the original reference ad",
|
|
12181
|
+
required: false
|
|
12182
|
+
}
|
|
12050
12183
|
}
|
|
12051
12184
|
});
|
|
12052
12185
|
function detectCreativeContentType(filePath) {
|
|
@@ -12055,29 +12188,22 @@ function detectCreativeContentType(filePath) {
|
|
|
12055
12188
|
unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
|
|
12056
12189
|
});
|
|
12057
12190
|
}
|
|
12058
|
-
function
|
|
12059
|
-
if (
|
|
12060
|
-
|
|
12191
|
+
function parseOptionalUrl(value) {
|
|
12192
|
+
if (value === void 0 || value.trim() === "") {
|
|
12193
|
+
return void 0;
|
|
12194
|
+
}
|
|
12195
|
+
try {
|
|
12196
|
+
return new URL(value).toString();
|
|
12197
|
+
} catch {
|
|
12198
|
+
throw new ApiError("VALIDATION_ERROR", "--source-reference-url must be a valid URL");
|
|
12061
12199
|
}
|
|
12062
|
-
return {
|
|
12063
|
-
type: "image",
|
|
12064
|
-
slug: image._id,
|
|
12065
|
-
title,
|
|
12066
|
-
tags: image.tags?.includes(creativeTag) ? image.tags : [...image.tags ?? [], creativeTag],
|
|
12067
|
-
imageUrl: image.imageUrl,
|
|
12068
|
-
thumbnailUrl: image.thumbnailUrl ?? image.imageUrl,
|
|
12069
|
-
storageKey: image.storageKey,
|
|
12070
|
-
width: image.width,
|
|
12071
|
-
height: image.height,
|
|
12072
|
-
aspectRatio: image.aspectRatio,
|
|
12073
|
-
source: image.source
|
|
12074
|
-
};
|
|
12075
12200
|
}
|
|
12076
12201
|
async function publishCreative(args, deps = defaultImageApiDeps) {
|
|
12077
12202
|
const title = args.title.trim();
|
|
12078
12203
|
if (!title) {
|
|
12079
12204
|
throw new ApiError("VALIDATION_ERROR", "--title is required");
|
|
12080
12205
|
}
|
|
12206
|
+
const sourceReferenceUrl = parseOptionalUrl(args.sourceReferenceUrl);
|
|
12081
12207
|
const contentType = detectCreativeContentType(args.file);
|
|
12082
12208
|
const upload = await uploadLocalImage(
|
|
12083
12209
|
{
|
|
@@ -12088,24 +12214,27 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
|
|
|
12088
12214
|
},
|
|
12089
12215
|
deps
|
|
12090
12216
|
);
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12217
|
+
await waitForReadyImage(deps, upload.imageId, { timeoutMs: imageProcessingTimeoutMs });
|
|
12218
|
+
return publishImageAsCreative(deps, {
|
|
12219
|
+
imageId: upload.imageId,
|
|
12220
|
+
title,
|
|
12221
|
+
sourceReferenceUrl
|
|
12096
12222
|
});
|
|
12097
|
-
const taggedImage = await getImage(deps, upload.imageId);
|
|
12098
|
-
return { imageId: upload.imageId, reference: imageToCreativeReference({ ...readyImage, ...taggedImage }, title) };
|
|
12099
12223
|
}
|
|
12100
12224
|
var publishCommand = defineCommand87({
|
|
12101
12225
|
meta: {
|
|
12102
12226
|
name: "publish",
|
|
12103
|
-
description: "Publish a final static creative image to Baker
|
|
12227
|
+
description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
|
|
12104
12228
|
},
|
|
12105
12229
|
args: {
|
|
12106
12230
|
file: { type: "positional", description: "Local PNG/JPG/WebP creative image path", required: false },
|
|
12107
12231
|
title: { type: "string", description: "Human title for the creative output", required: false },
|
|
12108
|
-
context: { type: "string", description: "Optional describe context for the image
|
|
12232
|
+
context: { type: "string", description: "Optional describe context for the image asset", required: false },
|
|
12233
|
+
sourceReferenceUrl: {
|
|
12234
|
+
type: "string",
|
|
12235
|
+
description: "Optional URL of the original reference ad",
|
|
12236
|
+
required: false
|
|
12237
|
+
}
|
|
12109
12238
|
},
|
|
12110
12239
|
run: async ({ args }) => {
|
|
12111
12240
|
try {
|
|
@@ -12119,7 +12248,12 @@ var publishCommand = defineCommand87({
|
|
|
12119
12248
|
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "--title is required" } });
|
|
12120
12249
|
process.exit(1);
|
|
12121
12250
|
}
|
|
12122
|
-
const data = await publishCreative({
|
|
12251
|
+
const data = await publishCreative({
|
|
12252
|
+
file,
|
|
12253
|
+
title,
|
|
12254
|
+
context: args.context,
|
|
12255
|
+
sourceReferenceUrl: args.sourceReferenceUrl
|
|
12256
|
+
});
|
|
12123
12257
|
writeJson({ ok: true, data });
|
|
12124
12258
|
} catch (err) {
|
|
12125
12259
|
if (err instanceof ApiError) {
|
|
@@ -12323,7 +12457,7 @@ Examples:
|
|
|
12323
12457
|
});
|
|
12324
12458
|
|
|
12325
12459
|
// src/commands/ga4/query.ts
|
|
12326
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
12460
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
12327
12461
|
import { resolve as resolve2 } from "path";
|
|
12328
12462
|
import { defineCommand as defineCommand91 } from "citty";
|
|
12329
12463
|
|
|
@@ -12397,7 +12531,7 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
12397
12531
|
const fields = extractFields2(rows);
|
|
12398
12532
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
12399
12533
|
if (ext === "csv") {
|
|
12400
|
-
if (!append || !
|
|
12534
|
+
if (!append || !existsSync5(filePath)) {
|
|
12401
12535
|
writeFileSync4(filePath, `${toCsvRow(fields)}
|
|
12402
12536
|
`, "utf-8");
|
|
12403
12537
|
}
|
|
@@ -12408,13 +12542,13 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
12408
12542
|
const lines = rows.map((row) => JSON.stringify(row));
|
|
12409
12543
|
const content = `${lines.join("\n")}
|
|
12410
12544
|
`;
|
|
12411
|
-
if (append &&
|
|
12545
|
+
if (append && existsSync5(filePath)) {
|
|
12412
12546
|
appendFileSync2(filePath, content, "utf-8");
|
|
12413
12547
|
} else {
|
|
12414
12548
|
writeFileSync4(filePath, content, "utf-8");
|
|
12415
12549
|
}
|
|
12416
|
-
} else if (append &&
|
|
12417
|
-
const existing = JSON.parse(
|
|
12550
|
+
} else if (append && existsSync5(filePath)) {
|
|
12551
|
+
const existing = JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
12418
12552
|
writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
12419
12553
|
} else {
|
|
12420
12554
|
writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -12554,7 +12688,7 @@ Examples:
|
|
|
12554
12688
|
import { defineCommand as defineCommand96 } from "citty";
|
|
12555
12689
|
|
|
12556
12690
|
// src/commands/gsc/query.ts
|
|
12557
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
12691
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
12558
12692
|
import { resolve as resolve3 } from "path";
|
|
12559
12693
|
import { defineCommand as defineCommand93 } from "citty";
|
|
12560
12694
|
|
|
@@ -12683,7 +12817,7 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
12683
12817
|
const fields = extractFields3(rows);
|
|
12684
12818
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
12685
12819
|
if (ext === "csv") {
|
|
12686
|
-
if (!append || !
|
|
12820
|
+
if (!append || !existsSync6(filePath)) {
|
|
12687
12821
|
writeFileSync5(filePath, `${toCsvRow(fields)}
|
|
12688
12822
|
`, "utf-8");
|
|
12689
12823
|
}
|
|
@@ -12693,13 +12827,13 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
12693
12827
|
} else if (ext === "jsonl") {
|
|
12694
12828
|
const content = `${rows.map((row) => JSON.stringify(row)).join("\n")}
|
|
12695
12829
|
`;
|
|
12696
|
-
if (append &&
|
|
12830
|
+
if (append && existsSync6(filePath)) {
|
|
12697
12831
|
appendFileSync3(filePath, content, "utf-8");
|
|
12698
12832
|
} else {
|
|
12699
12833
|
writeFileSync5(filePath, content, "utf-8");
|
|
12700
12834
|
}
|
|
12701
|
-
} else if (append &&
|
|
12702
|
-
const existing = JSON.parse(
|
|
12835
|
+
} else if (append && existsSync6(filePath)) {
|
|
12836
|
+
const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
|
|
12703
12837
|
writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
12704
12838
|
} else {
|
|
12705
12839
|
writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -12979,7 +13113,7 @@ function cropSprite(input, region) {
|
|
|
12979
13113
|
// src/lib/image/io.ts
|
|
12980
13114
|
import { randomBytes } from "crypto";
|
|
12981
13115
|
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
|
|
13116
|
+
import { dirname as dirname2, extname as extname2, join as join4, resolve as resolve4 } from "path";
|
|
12983
13117
|
var REMOTE_RE = /^https?:\/\//i;
|
|
12984
13118
|
var GLOB_RE = /[*?[\]{}]/;
|
|
12985
13119
|
function isRemoteUrl(value) {
|
|
@@ -13029,14 +13163,14 @@ async function resolveOutputPath(inputPath, outputArg, options) {
|
|
|
13029
13163
|
if (!outputArg) return base;
|
|
13030
13164
|
if (options.multipleInputs || await isDirectory(outputArg)) {
|
|
13031
13165
|
const filename = base.split("/").pop() ?? "out.png";
|
|
13032
|
-
return
|
|
13166
|
+
return join4(outputArg, filename);
|
|
13033
13167
|
}
|
|
13034
13168
|
return outputArg;
|
|
13035
13169
|
}
|
|
13036
13170
|
async function atomicWrite(targetPath, data) {
|
|
13037
13171
|
const absolute = resolve4(targetPath);
|
|
13038
|
-
const dir =
|
|
13039
|
-
const tmp =
|
|
13172
|
+
const dir = dirname2(absolute);
|
|
13173
|
+
const tmp = join4(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
|
|
13040
13174
|
await writeFile4(tmp, data);
|
|
13041
13175
|
await rename(tmp, absolute);
|
|
13042
13176
|
}
|
|
@@ -17761,7 +17895,7 @@ Examples:
|
|
|
17761
17895
|
});
|
|
17762
17896
|
|
|
17763
17897
|
// src/version.ts
|
|
17764
|
-
import { readFileSync as
|
|
17898
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
17765
17899
|
function packageJsonUrl() {
|
|
17766
17900
|
return new URL("../package.json", import.meta.url);
|
|
17767
17901
|
}
|
|
@@ -17773,7 +17907,7 @@ function parsePackageVersion(raw) {
|
|
|
17773
17907
|
throw new Error("Invalid CLI package.json: missing version");
|
|
17774
17908
|
}
|
|
17775
17909
|
function getCliVersion() {
|
|
17776
|
-
return parsePackageVersion(
|
|
17910
|
+
return parsePackageVersion(readFileSync9(packageJsonUrl(), "utf8"));
|
|
17777
17911
|
}
|
|
17778
17912
|
|
|
17779
17913
|
// src/cli.ts
|