@koda-sl/baker-cli 0.200.0 → 0.201.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 +1 -1
- package/dist/cli.js +111 -91
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5280,7 +5280,7 @@ baker landing inspiration scrape <url> --out <dir> # capture any page now, syn
|
|
|
5280
5280
|
```
|
|
5281
5281
|
|
|
5282
5282
|
- **Hybrid search over three signals** — keywords, meaning, and *appearance* (the screenshot is embedded, so a query like "dark developer hero with a terminal" can match a section whose text never says "terminal"). Filters: `--type --composition --register --interaction --motion --media --device --theme --max-rank --min-craft --min-fidelity --domain --similar-to --scope --limit`.
|
|
5283
|
-
- **Screenshots are downloaded to `.baker/inspiration/`** so an agent can actually look at a result rather than read a description of it.
|
|
5283
|
+
- **Screenshots are downloaded to `.baker/inspiration/`** so an agent can actually look at a result rather than read a description of it — downscaled to the page's own design width (1440px, WebP) rather than the 2x archive capture R2 holds. A vision model bills by pixel area and downsamples past its own long-edge cap anyway, so the extra resolution bought no legibility and cost context on every one of the eight hits a default search returns.
|
|
5284
5284
|
- **`fidelity` says how much to trust the code.** A measured 0–1 match between the live section and our standalone re-render, always reported. Above ~0.95 the markup renders like the original; below ~0.75 the section is scroll- or JS-driven and it does not.
|
|
5285
5285
|
- **`used_on_pages`** appears when a section shows up on more than one of that site's pages — a nav or footer they ship everywhere, which is a stronger reference than a one-off.
|
|
5286
5286
|
- **The corpus is shared across companies; favorites are per-company**, and search defaults to this company's saved sections.
|
package/dist/cli.js
CHANGED
|
@@ -8746,11 +8746,11 @@ function rawTextEntries(value) {
|
|
|
8746
8746
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
8747
8747
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
8748
8748
|
}
|
|
8749
|
-
function rawFileEntries(
|
|
8750
|
-
if (typeof
|
|
8749
|
+
function rawFileEntries(path37) {
|
|
8750
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
8751
8751
|
return [];
|
|
8752
8752
|
}
|
|
8753
|
-
return readFileSync2(
|
|
8753
|
+
return readFileSync2(path37, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
8754
8754
|
}
|
|
8755
8755
|
function keywordEntries(args) {
|
|
8756
8756
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -8773,19 +8773,19 @@ function keywordEntries(args) {
|
|
|
8773
8773
|
}
|
|
8774
8774
|
return entries;
|
|
8775
8775
|
}
|
|
8776
|
-
function loadJsonFileArg(
|
|
8777
|
-
if (typeof
|
|
8776
|
+
function loadJsonFileArg(path37) {
|
|
8777
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
8778
8778
|
return {};
|
|
8779
8779
|
}
|
|
8780
8780
|
try {
|
|
8781
|
-
const parsed = JSON.parse(readFileSync2(
|
|
8781
|
+
const parsed = JSON.parse(readFileSync2(path37, "utf8"));
|
|
8782
8782
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8783
|
-
failWriteValidation(`${
|
|
8783
|
+
failWriteValidation(`${path37} must contain a JSON object`);
|
|
8784
8784
|
}
|
|
8785
8785
|
return parsed;
|
|
8786
8786
|
} catch (err) {
|
|
8787
8787
|
if (err instanceof SyntaxError) {
|
|
8788
|
-
failWriteValidation(`${
|
|
8788
|
+
failWriteValidation(`${path37} is not valid JSON: ${err.message}`);
|
|
8789
8789
|
}
|
|
8790
8790
|
throw err;
|
|
8791
8791
|
}
|
|
@@ -8915,10 +8915,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
|
|
|
8915
8915
|
async function stageTarget(kind, customerId, target, hints) {
|
|
8916
8916
|
await stageGoogleOp({ kind, customerId, target }, hints);
|
|
8917
8917
|
}
|
|
8918
|
-
async function draftAction(
|
|
8918
|
+
async function draftAction(path37, body, chat) {
|
|
8919
8919
|
try {
|
|
8920
8920
|
const chatId = resolveChatId(chat);
|
|
8921
|
-
const response = await apiPost(
|
|
8921
|
+
const response = await apiPost(path37, { chatId, ...body });
|
|
8922
8922
|
writeJsonEnvelope(response);
|
|
8923
8923
|
} catch (err) {
|
|
8924
8924
|
handleGoogleError(err);
|
|
@@ -11776,19 +11776,19 @@ function failWriteValidation2(message) {
|
|
|
11776
11776
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
11777
11777
|
process.exit(1);
|
|
11778
11778
|
}
|
|
11779
|
-
function loadJsonFileArg2(
|
|
11780
|
-
if (typeof
|
|
11779
|
+
function loadJsonFileArg2(path37) {
|
|
11780
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
11781
11781
|
return {};
|
|
11782
11782
|
}
|
|
11783
11783
|
try {
|
|
11784
|
-
const parsed = JSON.parse(readFileSync4(
|
|
11784
|
+
const parsed = JSON.parse(readFileSync4(path37, "utf8"));
|
|
11785
11785
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11786
|
-
failWriteValidation2(`${
|
|
11786
|
+
failWriteValidation2(`${path37} must contain a JSON object`);
|
|
11787
11787
|
}
|
|
11788
11788
|
return parsed;
|
|
11789
11789
|
} catch (err) {
|
|
11790
11790
|
if (err instanceof SyntaxError) {
|
|
11791
|
-
failWriteValidation2(`${
|
|
11791
|
+
failWriteValidation2(`${path37} is not valid JSON: ${err.message}`);
|
|
11792
11792
|
}
|
|
11793
11793
|
throw err;
|
|
11794
11794
|
}
|
|
@@ -11873,15 +11873,15 @@ function parseLocaleFlag(value) {
|
|
|
11873
11873
|
}
|
|
11874
11874
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
11875
11875
|
}
|
|
11876
|
-
function loadTargetingFileArg(
|
|
11877
|
-
if (typeof
|
|
11876
|
+
function loadTargetingFileArg(path37) {
|
|
11877
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
11878
11878
|
return void 0;
|
|
11879
11879
|
}
|
|
11880
|
-
const parsed = loadJsonFileArg2(
|
|
11880
|
+
const parsed = loadJsonFileArg2(path37);
|
|
11881
11881
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
11882
11882
|
if (!criteria.include) {
|
|
11883
11883
|
failWriteValidation2(
|
|
11884
|
-
`${
|
|
11884
|
+
`${path37} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
11885
11885
|
);
|
|
11886
11886
|
}
|
|
11887
11887
|
return criteria;
|
|
@@ -11916,14 +11916,14 @@ function parseCsvLine(line) {
|
|
|
11916
11916
|
cells.push(current);
|
|
11917
11917
|
return cells.map((cell) => cell.trim());
|
|
11918
11918
|
}
|
|
11919
|
-
function parseListFileArg(
|
|
11920
|
-
if (typeof
|
|
11919
|
+
function parseListFileArg(path37, maxRows) {
|
|
11920
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
11921
11921
|
return void 0;
|
|
11922
11922
|
}
|
|
11923
|
-
const raw = readFileSync4(
|
|
11923
|
+
const raw = readFileSync4(path37, "utf8");
|
|
11924
11924
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
11925
11925
|
if (lines.length < 2) {
|
|
11926
|
-
failWriteValidation2(`${
|
|
11926
|
+
failWriteValidation2(`${path37} needs a header row and at least one data row`);
|
|
11927
11927
|
}
|
|
11928
11928
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
11929
11929
|
const rows = [];
|
|
@@ -11942,7 +11942,7 @@ function parseListFileArg(path36, maxRows) {
|
|
|
11942
11942
|
}
|
|
11943
11943
|
}
|
|
11944
11944
|
if (rows.length > maxRows) {
|
|
11945
|
-
failWriteValidation2(`${
|
|
11945
|
+
failWriteValidation2(`${path37} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
11946
11946
|
}
|
|
11947
11947
|
return { columns, rows };
|
|
11948
11948
|
}
|
|
@@ -12038,11 +12038,11 @@ function readPositionals(args) {
|
|
|
12038
12038
|
function splitIdList(raw) {
|
|
12039
12039
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
12040
12040
|
}
|
|
12041
|
-
function idsFileEntries(
|
|
12042
|
-
if (typeof
|
|
12041
|
+
function idsFileEntries(path37) {
|
|
12042
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
12043
12043
|
return [];
|
|
12044
12044
|
}
|
|
12045
|
-
return readFileSync4(
|
|
12045
|
+
return readFileSync4(path37, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
12046
12046
|
}
|
|
12047
12047
|
function requireTargets(args, entity) {
|
|
12048
12048
|
const positionals = readPositionals(args);
|
|
@@ -14665,9 +14665,9 @@ function compactRow(row) {
|
|
|
14665
14665
|
...destination.postUrn ? { postUrn: destination.postUrn } : {}
|
|
14666
14666
|
};
|
|
14667
14667
|
}
|
|
14668
|
-
function readPath(row,
|
|
14668
|
+
function readPath(row, path37) {
|
|
14669
14669
|
let current = row;
|
|
14670
|
-
for (const segment of
|
|
14670
|
+
for (const segment of path37.split(".")) {
|
|
14671
14671
|
const record = asRecord2(current);
|
|
14672
14672
|
if (!record) return void 0;
|
|
14673
14673
|
current = record[segment];
|
|
@@ -14677,10 +14677,10 @@ function readPath(row, path36) {
|
|
|
14677
14677
|
function projectFields(rows, paths) {
|
|
14678
14678
|
return rows.map((row) => {
|
|
14679
14679
|
const projected = {};
|
|
14680
|
-
for (const
|
|
14681
|
-
const value = readPath(row,
|
|
14680
|
+
for (const path37 of paths) {
|
|
14681
|
+
const value = readPath(row, path37);
|
|
14682
14682
|
if (value !== void 0) {
|
|
14683
|
-
projected[
|
|
14683
|
+
projected[path37] = value;
|
|
14684
14684
|
}
|
|
14685
14685
|
}
|
|
14686
14686
|
return projected;
|
|
@@ -15974,11 +15974,11 @@ var updateStatusSchema = z21.enum(UPDATE_STATUSES);
|
|
|
15974
15974
|
function currencyMinimums2(currencyCode) {
|
|
15975
15975
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
15976
15976
|
}
|
|
15977
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
15977
|
+
function validateDailyBudgetFloor(money, ctx, path37) {
|
|
15978
15978
|
if (money?.currencyCode) {
|
|
15979
15979
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
15980
15980
|
if (Number(money.amount) < min) {
|
|
15981
|
-
ctx.addIssue({ code: "custom", path:
|
|
15981
|
+
ctx.addIssue({ code: "custom", path: path37, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
15982
15982
|
}
|
|
15983
15983
|
}
|
|
15984
15984
|
}
|
|
@@ -16640,19 +16640,19 @@ function failWriteValidation3(message) {
|
|
|
16640
16640
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
16641
16641
|
process.exit(1);
|
|
16642
16642
|
}
|
|
16643
|
-
function loadJsonFileArg3(
|
|
16644
|
-
if (typeof
|
|
16643
|
+
function loadJsonFileArg3(path37) {
|
|
16644
|
+
if (typeof path37 !== "string" || path37.length === 0) {
|
|
16645
16645
|
return {};
|
|
16646
16646
|
}
|
|
16647
16647
|
try {
|
|
16648
|
-
const parsed = JSON.parse(readFileSync8(
|
|
16648
|
+
const parsed = JSON.parse(readFileSync8(path37, "utf8"));
|
|
16649
16649
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16650
|
-
failWriteValidation3(`${
|
|
16650
|
+
failWriteValidation3(`${path37} must contain a JSON object`);
|
|
16651
16651
|
}
|
|
16652
16652
|
return parsed;
|
|
16653
16653
|
} catch (err) {
|
|
16654
16654
|
if (err instanceof SyntaxError) {
|
|
16655
|
-
failWriteValidation3(`${
|
|
16655
|
+
failWriteValidation3(`${path37} is not valid JSON: ${err.message}`);
|
|
16656
16656
|
}
|
|
16657
16657
|
throw err;
|
|
16658
16658
|
}
|
|
@@ -27823,12 +27823,12 @@ function listFlowSlugs() {
|
|
|
27823
27823
|
return readdirSync2(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_") && entry.name !== ".gitkeep").map((entry) => entry.name).sort();
|
|
27824
27824
|
}
|
|
27825
27825
|
function readFlowTree(slug) {
|
|
27826
|
-
const
|
|
27827
|
-
if (!existsSync5(
|
|
27826
|
+
const path37 = join3(flowsDir(), slug, "_data.json");
|
|
27827
|
+
if (!existsSync5(path37)) {
|
|
27828
27828
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
27829
27829
|
}
|
|
27830
27830
|
try {
|
|
27831
|
-
return JSON.parse(readFileSync9(
|
|
27831
|
+
return JSON.parse(readFileSync9(path37, "utf-8"));
|
|
27832
27832
|
} catch (error) {
|
|
27833
27833
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
27834
27834
|
}
|
|
@@ -28241,10 +28241,10 @@ async function stageOps(ops) {
|
|
|
28241
28241
|
handleError(err);
|
|
28242
28242
|
}
|
|
28243
28243
|
}
|
|
28244
|
-
async function draftAction2(
|
|
28244
|
+
async function draftAction2(path37, body, chat) {
|
|
28245
28245
|
const chatId = resolveChatId(chat);
|
|
28246
28246
|
try {
|
|
28247
|
-
const data = await apiPost(
|
|
28247
|
+
const data = await apiPost(path37, { chatId, ...body });
|
|
28248
28248
|
writeJsonEnvelope({ ok: true, data });
|
|
28249
28249
|
return data;
|
|
28250
28250
|
} catch (err) {
|
|
@@ -30265,9 +30265,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
30265
30265
|
}
|
|
30266
30266
|
return readFile19(pathOrUrl);
|
|
30267
30267
|
}
|
|
30268
|
-
async function isDirectory(
|
|
30268
|
+
async function isDirectory(path37) {
|
|
30269
30269
|
try {
|
|
30270
|
-
const s = await stat4(
|
|
30270
|
+
const s = await stat4(path37);
|
|
30271
30271
|
return s.isDirectory();
|
|
30272
30272
|
} catch {
|
|
30273
30273
|
return false;
|
|
@@ -30551,13 +30551,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
30551
30551
|
}
|
|
30552
30552
|
function disambiguate(paths) {
|
|
30553
30553
|
const taken = /* @__PURE__ */ new Set();
|
|
30554
|
-
return paths.map((
|
|
30555
|
-
if (!taken.has(
|
|
30556
|
-
taken.add(
|
|
30557
|
-
return
|
|
30554
|
+
return paths.map((path37) => {
|
|
30555
|
+
if (!taken.has(path37)) {
|
|
30556
|
+
taken.add(path37);
|
|
30557
|
+
return path37;
|
|
30558
30558
|
}
|
|
30559
|
-
const ext = extname3(
|
|
30560
|
-
const stem =
|
|
30559
|
+
const ext = extname3(path37);
|
|
30560
|
+
const stem = path37.slice(0, path37.length - ext.length);
|
|
30561
30561
|
let n = 2;
|
|
30562
30562
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
30563
30563
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -30684,10 +30684,10 @@ async function runDownloads(plan) {
|
|
|
30684
30684
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
30685
30685
|
const downloaded = [];
|
|
30686
30686
|
for (const [index, item] of fetched.entries()) {
|
|
30687
|
-
const
|
|
30687
|
+
const path37 = paths[index] ?? item.path;
|
|
30688
30688
|
try {
|
|
30689
|
-
await atomicWrite(
|
|
30690
|
-
downloaded.push({ input: item.input, output:
|
|
30689
|
+
await atomicWrite(path37, item.buffer);
|
|
30690
|
+
downloaded.push({ input: item.input, output: path37, bytes: item.buffer.length, contentType: item.contentType });
|
|
30691
30691
|
} catch (err) {
|
|
30692
30692
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
30693
30693
|
}
|
|
@@ -37803,9 +37803,46 @@ var scrapeCommand = defineCommand152({
|
|
|
37803
37803
|
});
|
|
37804
37804
|
|
|
37805
37805
|
// src/commands/landing/inspiration/search.ts
|
|
37806
|
+
import path35 from "path";
|
|
37807
|
+
import { defineCommand as defineCommand153 } from "citty";
|
|
37808
|
+
|
|
37809
|
+
// src/commands/landing/inspiration/shot.ts
|
|
37806
37810
|
import { mkdir as mkdir12, writeFile as writeFile17 } from "fs/promises";
|
|
37807
37811
|
import path34 from "path";
|
|
37808
|
-
import
|
|
37812
|
+
import sharp6 from "sharp";
|
|
37813
|
+
var READABLE_SHOT = {
|
|
37814
|
+
maxWidth: 1440,
|
|
37815
|
+
maxHeight: 4e3,
|
|
37816
|
+
quality: 82,
|
|
37817
|
+
extension: "webp"
|
|
37818
|
+
};
|
|
37819
|
+
async function toReadableShot(original) {
|
|
37820
|
+
try {
|
|
37821
|
+
return await sharp6(original).resize({
|
|
37822
|
+
width: READABLE_SHOT.maxWidth,
|
|
37823
|
+
height: READABLE_SHOT.maxHeight,
|
|
37824
|
+
fit: "inside",
|
|
37825
|
+
withoutEnlargement: true
|
|
37826
|
+
}).webp({ quality: READABLE_SHOT.quality }).toBuffer();
|
|
37827
|
+
} catch {
|
|
37828
|
+
return original;
|
|
37829
|
+
}
|
|
37830
|
+
}
|
|
37831
|
+
async function downloadReadableShot(url, file) {
|
|
37832
|
+
if (!url) return null;
|
|
37833
|
+
try {
|
|
37834
|
+
const response = await fetch(url);
|
|
37835
|
+
if (!response.ok) return null;
|
|
37836
|
+
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
37837
|
+
await mkdir12(path34.dirname(file), { recursive: true });
|
|
37838
|
+
await writeFile17(file, shot);
|
|
37839
|
+
return path34.relative(process.cwd(), file);
|
|
37840
|
+
} catch {
|
|
37841
|
+
return null;
|
|
37842
|
+
}
|
|
37843
|
+
}
|
|
37844
|
+
|
|
37845
|
+
// src/commands/landing/inspiration/search.ts
|
|
37809
37846
|
registerSchema({
|
|
37810
37847
|
command: "landing.inspiration.search",
|
|
37811
37848
|
description: "Search the shared library of real landing-page sections for reference before you design. Start here: baker landing inspiration search 'pricing with a monthly/annual toggle'. Returns the idea behind each section plus a downloaded screenshot you can Read. Defaults to this company's saved sections; pass --scope all for the whole library.",
|
|
@@ -37891,20 +37928,15 @@ function buildSearchBody(args) {
|
|
|
37891
37928
|
return body;
|
|
37892
37929
|
}
|
|
37893
37930
|
async function downloadShots(results) {
|
|
37894
|
-
const dir =
|
|
37895
|
-
await mkdir12(dir, { recursive: true });
|
|
37931
|
+
const dir = path35.join(process.cwd(), ".baker", "inspiration");
|
|
37896
37932
|
const saved = /* @__PURE__ */ new Map();
|
|
37897
37933
|
await Promise.all(
|
|
37898
37934
|
results.map(async (result) => {
|
|
37899
|
-
|
|
37900
|
-
|
|
37901
|
-
|
|
37902
|
-
|
|
37903
|
-
|
|
37904
|
-
await writeFile17(file, Buffer.from(await response.arrayBuffer()));
|
|
37905
|
-
saved.set(result.id, path34.relative(process.cwd(), file));
|
|
37906
|
-
} catch {
|
|
37907
|
-
}
|
|
37935
|
+
const file = await downloadReadableShot(
|
|
37936
|
+
result.desktopShotUrl,
|
|
37937
|
+
path35.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
37938
|
+
);
|
|
37939
|
+
if (file) saved.set(result.id, file);
|
|
37908
37940
|
})
|
|
37909
37941
|
);
|
|
37910
37942
|
return saved;
|
|
@@ -38130,8 +38162,7 @@ var sequencesCommand = defineCommand154({
|
|
|
38130
38162
|
});
|
|
38131
38163
|
|
|
38132
38164
|
// src/commands/landing/inspiration/view.ts
|
|
38133
|
-
import
|
|
38134
|
-
import path35 from "path";
|
|
38165
|
+
import path36 from "path";
|
|
38135
38166
|
import { defineCommand as defineCommand155 } from "citty";
|
|
38136
38167
|
registerSchema({
|
|
38137
38168
|
command: "landing.inspiration.view",
|
|
@@ -38145,18 +38176,6 @@ registerSchema({
|
|
|
38145
38176
|
}
|
|
38146
38177
|
}
|
|
38147
38178
|
});
|
|
38148
|
-
async function download(url, file) {
|
|
38149
|
-
if (!url) return null;
|
|
38150
|
-
try {
|
|
38151
|
-
const response = await fetch(url);
|
|
38152
|
-
if (!response.ok) return null;
|
|
38153
|
-
await mkdir13(path35.dirname(file), { recursive: true });
|
|
38154
|
-
await writeFile18(file, Buffer.from(await response.arrayBuffer()));
|
|
38155
|
-
return path35.relative(process.cwd(), file);
|
|
38156
|
-
} catch {
|
|
38157
|
-
return null;
|
|
38158
|
-
}
|
|
38159
|
-
}
|
|
38160
38179
|
var viewCommand2 = defineCommand155({
|
|
38161
38180
|
meta: {
|
|
38162
38181
|
name: "view",
|
|
@@ -38176,11 +38195,12 @@ var viewCommand2 = defineCommand155({
|
|
|
38176
38195
|
const id = args.id;
|
|
38177
38196
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
38178
38197
|
const section = data.section;
|
|
38179
|
-
const dir =
|
|
38198
|
+
const dir = path36.join(process.cwd(), ".baker", "inspiration", id);
|
|
38199
|
+
const ext = READABLE_SHOT.extension;
|
|
38180
38200
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
38181
|
-
|
|
38182
|
-
|
|
38183
|
-
|
|
38201
|
+
downloadReadableShot(section.desktopShotUrl, path36.join(dir, `desktop.${ext}`)),
|
|
38202
|
+
downloadReadableShot(section.mobileShotUrl, path36.join(dir, `mobile.${ext}`)),
|
|
38203
|
+
downloadReadableShot(section.motionFilmstripUrl, path36.join(dir, `motion-filmstrip.${ext}`))
|
|
38184
38204
|
]);
|
|
38185
38205
|
const full = args.full;
|
|
38186
38206
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -38190,7 +38210,7 @@ var viewCommand2 = defineCommand155({
|
|
|
38190
38210
|
if (fidelity) hints.push(fidelity);
|
|
38191
38211
|
if (filmstrip) {
|
|
38192
38212
|
hints.push(
|
|
38193
|
-
|
|
38213
|
+
`${filmstrip} shows this section animating in, six frames left-to-right then top-to-bottom, with the elapsed time on each. Read it if you want the motion, not just the layout.`
|
|
38194
38214
|
);
|
|
38195
38215
|
}
|
|
38196
38216
|
writeJson({
|
|
@@ -40398,7 +40418,7 @@ function parseImageRefs(spec) {
|
|
|
40398
40418
|
}
|
|
40399
40419
|
var defaultDeps = {
|
|
40400
40420
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
40401
|
-
upload: (
|
|
40421
|
+
upload: (path37) => uploadLocalImage({ file: path37, contentType: detectImageContentType(path37), source: "uploaded" })
|
|
40402
40422
|
};
|
|
40403
40423
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
40404
40424
|
const refs = parseImageRefs(spec);
|
|
@@ -40418,10 +40438,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
40418
40438
|
}
|
|
40419
40439
|
return { imageIds, added };
|
|
40420
40440
|
}
|
|
40421
|
-
function uploadFailure(
|
|
40441
|
+
function uploadFailure(path37) {
|
|
40422
40442
|
return (error) => {
|
|
40423
40443
|
if (error instanceof ApiError) throw error;
|
|
40424
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
40444
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path37}" as an image.`);
|
|
40425
40445
|
};
|
|
40426
40446
|
}
|
|
40427
40447
|
|
|
@@ -41471,10 +41491,10 @@ async function stageOp4(op) {
|
|
|
41471
41491
|
handleError4(err);
|
|
41472
41492
|
}
|
|
41473
41493
|
}
|
|
41474
|
-
async function draftAction3(
|
|
41494
|
+
async function draftAction3(path37, body, chat) {
|
|
41475
41495
|
const chatId = resolveChatId(chat);
|
|
41476
41496
|
try {
|
|
41477
|
-
const data = await apiPost(
|
|
41497
|
+
const data = await apiPost(path37, { chatId, ...body });
|
|
41478
41498
|
writeJsonEnvelope({ ok: true, data });
|
|
41479
41499
|
return data;
|
|
41480
41500
|
} catch (err) {
|