@koda-sl/baker-cli 0.239.0 → 0.240.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 +2 -1
- package/dist/cli.js +149 -103
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5601,7 +5601,7 @@ baker landing inspiration page <source id> # a whole page as a section sequ
|
|
|
5601
5601
|
baker landing inspiration sequences "b2b saas pricing page" --scope all # what follows what, across many pages
|
|
5602
5602
|
baker landing inspiration add https://linear.app --note "client likes this density"
|
|
5603
5603
|
baker landing inspiration favorites # what this company has saved
|
|
5604
|
-
baker landing inspiration scrape <url> --out
|
|
5604
|
+
baker landing inspiration scrape <url> --out .baker/<dir> # capture any page now, synchronously
|
|
5605
5605
|
```
|
|
5606
5606
|
|
|
5607
5607
|
- **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`.
|
|
@@ -5618,6 +5618,7 @@ baker landing inspiration scrape <url> --out <dir> # capture any page now, syn
|
|
|
5618
5618
|
- **Filming is the expensive pass, and it runs three sections at a time.** Every moving section is filmed in its own fresh page load — the only way to catch an entrance animation before it fires — so a page with ten moving sections pays for ten full loads. Measured on one heavy page, filming was 74% of the capture. The takes are independent, so they overlap; a page that cannot be captured inside the library's budget now says so instead of timing out silently.
|
|
5619
5619
|
- **A page we can't open says why.** A dead certificate, an address that doesn't resolve, a site that won't answer or one that is simply too slow each produce their own plain-language reason rather than a browser error.
|
|
5620
5620
|
- **Inspiration, never a clipboard.** Both `code` and `scrape` record what was consulted, and `critique`'s `originality` family blocks a publish that reuses a reference's copy verbatim.
|
|
5621
|
+
- **A capture has to land in `.baker/`, and `scrape` refuses anywhere else in a workspace.** `--out` is free-form and the directory is the agent's choice, but a capture is tens of MB of lossless PNG whose individual files clear every size gate — written to a tracked directory it becomes a permanent part of the client's repo, force-cloned into every later session. `.baker/` is gitignored precisely so a capture costs nothing. The refusal is scoped to the workspace: outside a git work tree — a local run against `/tmp` — any path is allowed, because there is no history to bloat.
|
|
5621
5622
|
|
|
5622
5623
|
### `baker landing critique`
|
|
5623
5624
|
|
package/dist/cli.js
CHANGED
|
@@ -9763,11 +9763,11 @@ function rawTextEntries(value) {
|
|
|
9763
9763
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
9764
9764
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
9765
9765
|
}
|
|
9766
|
-
function rawFileEntries(
|
|
9767
|
-
if (typeof
|
|
9766
|
+
function rawFileEntries(path40) {
|
|
9767
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
9768
9768
|
return [];
|
|
9769
9769
|
}
|
|
9770
|
-
return readFileSync2(
|
|
9770
|
+
return readFileSync2(path40, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
9771
9771
|
}
|
|
9772
9772
|
function keywordEntries(args) {
|
|
9773
9773
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -9790,19 +9790,19 @@ function keywordEntries(args) {
|
|
|
9790
9790
|
}
|
|
9791
9791
|
return entries;
|
|
9792
9792
|
}
|
|
9793
|
-
function loadJsonFileArg(
|
|
9794
|
-
if (typeof
|
|
9793
|
+
function loadJsonFileArg(path40) {
|
|
9794
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
9795
9795
|
return {};
|
|
9796
9796
|
}
|
|
9797
9797
|
try {
|
|
9798
|
-
const parsed = JSON.parse(readFileSync2(
|
|
9798
|
+
const parsed = JSON.parse(readFileSync2(path40, "utf8"));
|
|
9799
9799
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9800
|
-
failWriteValidation(`${
|
|
9800
|
+
failWriteValidation(`${path40} must contain a JSON object`);
|
|
9801
9801
|
}
|
|
9802
9802
|
return parsed;
|
|
9803
9803
|
} catch (err) {
|
|
9804
9804
|
if (err instanceof SyntaxError) {
|
|
9805
|
-
failWriteValidation(`${
|
|
9805
|
+
failWriteValidation(`${path40} is not valid JSON: ${err.message}`);
|
|
9806
9806
|
}
|
|
9807
9807
|
throw err;
|
|
9808
9808
|
}
|
|
@@ -9932,10 +9932,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
|
|
|
9932
9932
|
async function stageTarget(kind, customerId, target, hints) {
|
|
9933
9933
|
await stageGoogleOp({ kind, customerId, target }, hints);
|
|
9934
9934
|
}
|
|
9935
|
-
async function draftAction(
|
|
9935
|
+
async function draftAction(path40, body, chat) {
|
|
9936
9936
|
try {
|
|
9937
9937
|
const chatId = resolveChatId(chat);
|
|
9938
|
-
const response = await apiPost(
|
|
9938
|
+
const response = await apiPost(path40, { chatId, ...body });
|
|
9939
9939
|
writeJsonEnvelope(response);
|
|
9940
9940
|
} catch (err) {
|
|
9941
9941
|
handleGoogleError(err);
|
|
@@ -14869,19 +14869,19 @@ function failWriteValidation2(message) {
|
|
|
14869
14869
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
14870
14870
|
process.exit(1);
|
|
14871
14871
|
}
|
|
14872
|
-
function loadJsonFileArg2(
|
|
14873
|
-
if (typeof
|
|
14872
|
+
function loadJsonFileArg2(path40) {
|
|
14873
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
14874
14874
|
return {};
|
|
14875
14875
|
}
|
|
14876
14876
|
try {
|
|
14877
|
-
const parsed = JSON.parse(readFileSync4(
|
|
14877
|
+
const parsed = JSON.parse(readFileSync4(path40, "utf8"));
|
|
14878
14878
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
14879
|
-
failWriteValidation2(`${
|
|
14879
|
+
failWriteValidation2(`${path40} must contain a JSON object`);
|
|
14880
14880
|
}
|
|
14881
14881
|
return parsed;
|
|
14882
14882
|
} catch (err) {
|
|
14883
14883
|
if (err instanceof SyntaxError) {
|
|
14884
|
-
failWriteValidation2(`${
|
|
14884
|
+
failWriteValidation2(`${path40} is not valid JSON: ${err.message}`);
|
|
14885
14885
|
}
|
|
14886
14886
|
throw err;
|
|
14887
14887
|
}
|
|
@@ -14966,15 +14966,15 @@ function parseLocaleFlag(value) {
|
|
|
14966
14966
|
}
|
|
14967
14967
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
14968
14968
|
}
|
|
14969
|
-
function loadTargetingFileArg(
|
|
14970
|
-
if (typeof
|
|
14969
|
+
function loadTargetingFileArg(path40) {
|
|
14970
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
14971
14971
|
return void 0;
|
|
14972
14972
|
}
|
|
14973
|
-
const parsed = loadJsonFileArg2(
|
|
14973
|
+
const parsed = loadJsonFileArg2(path40);
|
|
14974
14974
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
14975
14975
|
if (!criteria.include) {
|
|
14976
14976
|
failWriteValidation2(
|
|
14977
|
-
`${
|
|
14977
|
+
`${path40} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
14978
14978
|
);
|
|
14979
14979
|
}
|
|
14980
14980
|
return criteria;
|
|
@@ -15009,14 +15009,14 @@ function parseCsvLine(line) {
|
|
|
15009
15009
|
cells.push(current);
|
|
15010
15010
|
return cells.map((cell2) => cell2.trim());
|
|
15011
15011
|
}
|
|
15012
|
-
function parseListFileArg(
|
|
15013
|
-
if (typeof
|
|
15012
|
+
function parseListFileArg(path40, maxRows) {
|
|
15013
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
15014
15014
|
return void 0;
|
|
15015
15015
|
}
|
|
15016
|
-
const raw = readFileSync4(
|
|
15016
|
+
const raw = readFileSync4(path40, "utf8");
|
|
15017
15017
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
15018
15018
|
if (lines.length < 2) {
|
|
15019
|
-
failWriteValidation2(`${
|
|
15019
|
+
failWriteValidation2(`${path40} needs a header row and at least one data row`);
|
|
15020
15020
|
}
|
|
15021
15021
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
15022
15022
|
const rows = [];
|
|
@@ -15035,7 +15035,7 @@ function parseListFileArg(path39, maxRows) {
|
|
|
15035
15035
|
}
|
|
15036
15036
|
}
|
|
15037
15037
|
if (rows.length > maxRows) {
|
|
15038
|
-
failWriteValidation2(`${
|
|
15038
|
+
failWriteValidation2(`${path40} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
15039
15039
|
}
|
|
15040
15040
|
return { columns, rows };
|
|
15041
15041
|
}
|
|
@@ -15131,11 +15131,11 @@ function readPositionals(args) {
|
|
|
15131
15131
|
function splitIdList(raw) {
|
|
15132
15132
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
15133
15133
|
}
|
|
15134
|
-
function idsFileEntries(
|
|
15135
|
-
if (typeof
|
|
15134
|
+
function idsFileEntries(path40) {
|
|
15135
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
15136
15136
|
return [];
|
|
15137
15137
|
}
|
|
15138
|
-
return readFileSync4(
|
|
15138
|
+
return readFileSync4(path40, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
15139
15139
|
}
|
|
15140
15140
|
function requireTargets(args, entity) {
|
|
15141
15141
|
const positionals = readPositionals(args);
|
|
@@ -17756,9 +17756,9 @@ function compactRow(row) {
|
|
|
17756
17756
|
...destination.postUrn ? { postUrn: destination.postUrn } : {}
|
|
17757
17757
|
};
|
|
17758
17758
|
}
|
|
17759
|
-
function readPath(row,
|
|
17759
|
+
function readPath(row, path40) {
|
|
17760
17760
|
let current = row;
|
|
17761
|
-
for (const segment of
|
|
17761
|
+
for (const segment of path40.split(".")) {
|
|
17762
17762
|
const record = asRecord2(current);
|
|
17763
17763
|
if (!record) return void 0;
|
|
17764
17764
|
current = record[segment];
|
|
@@ -17768,10 +17768,10 @@ function readPath(row, path39) {
|
|
|
17768
17768
|
function projectFields(rows, paths) {
|
|
17769
17769
|
return rows.map((row) => {
|
|
17770
17770
|
const projected = {};
|
|
17771
|
-
for (const
|
|
17772
|
-
const value = readPath(row,
|
|
17771
|
+
for (const path40 of paths) {
|
|
17772
|
+
const value = readPath(row, path40);
|
|
17773
17773
|
if (value !== void 0) {
|
|
17774
|
-
projected[
|
|
17774
|
+
projected[path40] = value;
|
|
17775
17775
|
}
|
|
17776
17776
|
}
|
|
17777
17777
|
return projected;
|
|
@@ -19071,11 +19071,11 @@ var updateStatusSchema = z25.enum(UPDATE_STATUSES);
|
|
|
19071
19071
|
function currencyMinimums2(currencyCode) {
|
|
19072
19072
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
19073
19073
|
}
|
|
19074
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
19074
|
+
function validateDailyBudgetFloor(money, ctx, path40) {
|
|
19075
19075
|
if (money?.currencyCode) {
|
|
19076
19076
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
19077
19077
|
if (Number(money.amount) < min) {
|
|
19078
|
-
ctx.addIssue({ code: "custom", path:
|
|
19078
|
+
ctx.addIssue({ code: "custom", path: path40, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
19079
19079
|
}
|
|
19080
19080
|
}
|
|
19081
19081
|
}
|
|
@@ -19737,19 +19737,19 @@ function failWriteValidation3(message) {
|
|
|
19737
19737
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
19738
19738
|
process.exit(1);
|
|
19739
19739
|
}
|
|
19740
|
-
function loadJsonFileArg3(
|
|
19741
|
-
if (typeof
|
|
19740
|
+
function loadJsonFileArg3(path40) {
|
|
19741
|
+
if (typeof path40 !== "string" || path40.length === 0) {
|
|
19742
19742
|
return {};
|
|
19743
19743
|
}
|
|
19744
19744
|
try {
|
|
19745
|
-
const parsed = JSON.parse(readFileSync8(
|
|
19745
|
+
const parsed = JSON.parse(readFileSync8(path40, "utf8"));
|
|
19746
19746
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
19747
|
-
failWriteValidation3(`${
|
|
19747
|
+
failWriteValidation3(`${path40} must contain a JSON object`);
|
|
19748
19748
|
}
|
|
19749
19749
|
return parsed;
|
|
19750
19750
|
} catch (err) {
|
|
19751
19751
|
if (err instanceof SyntaxError) {
|
|
19752
|
-
failWriteValidation3(`${
|
|
19752
|
+
failWriteValidation3(`${path40} is not valid JSON: ${err.message}`);
|
|
19753
19753
|
}
|
|
19754
19754
|
throw err;
|
|
19755
19755
|
}
|
|
@@ -24327,11 +24327,11 @@ function unwrap(response) {
|
|
|
24327
24327
|
}
|
|
24328
24328
|
return response.data;
|
|
24329
24329
|
}
|
|
24330
|
-
async function readAvatars(
|
|
24331
|
-
return unwrap(await apiGet(
|
|
24330
|
+
async function readAvatars(path40, params) {
|
|
24331
|
+
return unwrap(await apiGet(path40, params));
|
|
24332
24332
|
}
|
|
24333
|
-
async function writeAvatars(
|
|
24334
|
-
return unwrap(await apiPost(
|
|
24333
|
+
async function writeAvatars(path40, body) {
|
|
24334
|
+
return unwrap(await apiPost(path40, body));
|
|
24335
24335
|
}
|
|
24336
24336
|
|
|
24337
24337
|
// src/commands/avatars/create.ts
|
|
@@ -25165,12 +25165,12 @@ function missingFontFiles(urls, available) {
|
|
|
25165
25165
|
function planFontAdoption(sources, families) {
|
|
25166
25166
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
25167
25167
|
const byFamily = /* @__PURE__ */ new Map();
|
|
25168
|
-
for (const { path:
|
|
25169
|
-
const dir = posix.dirname(
|
|
25168
|
+
for (const { path: path40, source } of sources) {
|
|
25169
|
+
const dir = posix.dirname(path40);
|
|
25170
25170
|
for (const face of declaredFontFaces(source)) {
|
|
25171
25171
|
if (!wanted.has(face.family)) continue;
|
|
25172
25172
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
25173
|
-
perFile.set(
|
|
25173
|
+
perFile.set(path40, [...perFile.get(path40) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
25174
25174
|
byFamily.set(face.family, perFile);
|
|
25175
25175
|
}
|
|
25176
25176
|
}
|
|
@@ -33365,12 +33365,12 @@ function collectSideEffects(tree) {
|
|
|
33365
33365
|
);
|
|
33366
33366
|
}
|
|
33367
33367
|
function readFlowTree(slug) {
|
|
33368
|
-
const
|
|
33369
|
-
if (!existsSync5(
|
|
33368
|
+
const path40 = join3(flowsDir(), slug, "_data.json");
|
|
33369
|
+
if (!existsSync5(path40)) {
|
|
33370
33370
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
33371
33371
|
}
|
|
33372
33372
|
try {
|
|
33373
|
-
return JSON.parse(readFileSync9(
|
|
33373
|
+
return JSON.parse(readFileSync9(path40, "utf-8"));
|
|
33374
33374
|
} catch (error) {
|
|
33375
33375
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
33376
33376
|
}
|
|
@@ -33762,10 +33762,10 @@ function parseValueExpression(raw) {
|
|
|
33762
33762
|
return parts.map(parsePart);
|
|
33763
33763
|
}
|
|
33764
33764
|
function trackingFieldIds() {
|
|
33765
|
-
const
|
|
33766
|
-
if (!existsSync6(
|
|
33765
|
+
const path40 = join4(flowsDir(), "..", "tracking.ts");
|
|
33766
|
+
if (!existsSync6(path40)) return null;
|
|
33767
33767
|
try {
|
|
33768
|
-
const source = readFileSync10(
|
|
33768
|
+
const source = readFileSync10(path40, "utf-8");
|
|
33769
33769
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
33770
33770
|
if (!block2) return null;
|
|
33771
33771
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -34317,13 +34317,13 @@ function specsFromFile(parsed) {
|
|
|
34317
34317
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
34318
34318
|
});
|
|
34319
34319
|
}
|
|
34320
|
-
function readSpecFile(
|
|
34320
|
+
function readSpecFile(path40) {
|
|
34321
34321
|
let raw;
|
|
34322
34322
|
try {
|
|
34323
|
-
raw =
|
|
34323
|
+
raw = path40 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path40, "utf-8");
|
|
34324
34324
|
} catch (error) {
|
|
34325
34325
|
refuse(
|
|
34326
|
-
`Could not read ${
|
|
34326
|
+
`Could not read ${path40 === "-" ? "the mapping from stdin" : `"${path40}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
34327
34327
|
);
|
|
34328
34328
|
}
|
|
34329
34329
|
let parsed;
|
|
@@ -34331,7 +34331,7 @@ function readSpecFile(path39) {
|
|
|
34331
34331
|
parsed = JSON.parse(raw);
|
|
34332
34332
|
} catch (error) {
|
|
34333
34333
|
refuse(
|
|
34334
|
-
`${
|
|
34334
|
+
`${path40 === "-" ? "stdin" : `"${path40}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
34335
34335
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
34336
34336
|
);
|
|
34337
34337
|
}
|
|
@@ -34585,18 +34585,18 @@ var ARRAY_FIELDS = [
|
|
|
34585
34585
|
"tagIds"
|
|
34586
34586
|
];
|
|
34587
34587
|
var ARRAY_OWNERS = ["", "body"];
|
|
34588
|
-
function dropUnsetOptionals(sideEffect,
|
|
34588
|
+
function dropUnsetOptionals(sideEffect, path40) {
|
|
34589
34589
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
34590
34590
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
34591
34591
|
delete sideEffect[key];
|
|
34592
|
-
return [{ path:
|
|
34592
|
+
return [{ path: path40, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
34593
34593
|
});
|
|
34594
34594
|
}
|
|
34595
|
-
function fillNulledArrays(target, prefix,
|
|
34595
|
+
function fillNulledArrays(target, prefix, path40) {
|
|
34596
34596
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
34597
34597
|
if (!(key in target) || target[key] !== null) return [];
|
|
34598
34598
|
target[key] = [];
|
|
34599
|
-
return [{ path:
|
|
34599
|
+
return [{ path: path40, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
34600
34600
|
});
|
|
34601
34601
|
}
|
|
34602
34602
|
function sideEffectsOf(node) {
|
|
@@ -34606,13 +34606,13 @@ function sideEffectsOf(node) {
|
|
|
34606
34606
|
);
|
|
34607
34607
|
}
|
|
34608
34608
|
function normalizeSideEffect(sideEffect, where) {
|
|
34609
|
-
const
|
|
34609
|
+
const path40 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
34610
34610
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
34611
34611
|
const target = owner ? sideEffect[owner] : sideEffect;
|
|
34612
34612
|
if (!target || typeof target !== "object") return [];
|
|
34613
|
-
return fillNulledArrays(target, owner ? `${owner}.` : "",
|
|
34613
|
+
return fillNulledArrays(target, owner ? `${owner}.` : "", path40);
|
|
34614
34614
|
});
|
|
34615
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
34615
|
+
return [...dropUnsetOptionals(sideEffect, path40), ...arrays];
|
|
34616
34616
|
}
|
|
34617
34617
|
function normalizeFlowTree(tree) {
|
|
34618
34618
|
const changes = [];
|
|
@@ -35150,10 +35150,10 @@ async function stageOps(ops) {
|
|
|
35150
35150
|
handleError2(err);
|
|
35151
35151
|
}
|
|
35152
35152
|
}
|
|
35153
|
-
async function draftAction2(
|
|
35153
|
+
async function draftAction2(path40, body, chat) {
|
|
35154
35154
|
const chatId = resolveChatId(chat);
|
|
35155
35155
|
try {
|
|
35156
|
-
const data = await apiPost(
|
|
35156
|
+
const data = await apiPost(path40, { chatId, ...body });
|
|
35157
35157
|
writeJsonEnvelope({ ok: true, data });
|
|
35158
35158
|
return data;
|
|
35159
35159
|
} catch (err) {
|
|
@@ -37585,9 +37585,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
37585
37585
|
}
|
|
37586
37586
|
return readFile20(pathOrUrl);
|
|
37587
37587
|
}
|
|
37588
|
-
async function isDirectory(
|
|
37588
|
+
async function isDirectory(path40) {
|
|
37589
37589
|
try {
|
|
37590
|
-
const s = await stat4(
|
|
37590
|
+
const s = await stat4(path40);
|
|
37591
37591
|
return s.isDirectory();
|
|
37592
37592
|
} catch {
|
|
37593
37593
|
return false;
|
|
@@ -37889,13 +37889,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
37889
37889
|
}
|
|
37890
37890
|
function disambiguate(paths) {
|
|
37891
37891
|
const taken = /* @__PURE__ */ new Set();
|
|
37892
|
-
return paths.map((
|
|
37893
|
-
if (!taken.has(
|
|
37894
|
-
taken.add(
|
|
37895
|
-
return
|
|
37892
|
+
return paths.map((path40) => {
|
|
37893
|
+
if (!taken.has(path40)) {
|
|
37894
|
+
taken.add(path40);
|
|
37895
|
+
return path40;
|
|
37896
37896
|
}
|
|
37897
|
-
const ext = extname3(
|
|
37898
|
-
const stem =
|
|
37897
|
+
const ext = extname3(path40);
|
|
37898
|
+
const stem = path40.slice(0, path40.length - ext.length);
|
|
37899
37899
|
let n = 2;
|
|
37900
37900
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
37901
37901
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -38022,10 +38022,10 @@ async function runDownloads(plan) {
|
|
|
38022
38022
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
38023
38023
|
const downloaded = [];
|
|
38024
38024
|
for (const [index, item] of fetched.entries()) {
|
|
38025
|
-
const
|
|
38025
|
+
const path40 = paths[index] ?? item.path;
|
|
38026
38026
|
try {
|
|
38027
|
-
await atomicWrite(
|
|
38028
|
-
downloaded.push({ input: item.input, output:
|
|
38027
|
+
await atomicWrite(path40, item.buffer);
|
|
38028
|
+
downloaded.push({ input: item.input, output: path40, bytes: item.buffer.length, contentType: item.contentType });
|
|
38029
38029
|
} catch (err) {
|
|
38030
38030
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
38031
38031
|
}
|
|
@@ -42706,7 +42706,7 @@ var pageCommand2 = defineCommand160({
|
|
|
42706
42706
|
|
|
42707
42707
|
// src/commands/landing/inspiration/scrape.ts
|
|
42708
42708
|
import { readFile as readFile23 } from "fs/promises";
|
|
42709
|
-
import
|
|
42709
|
+
import path34 from "path";
|
|
42710
42710
|
import { defineCommand as defineCommand161 } from "citty";
|
|
42711
42711
|
|
|
42712
42712
|
// src/engine/landing/lib/capturedReferences.ts
|
|
@@ -44773,6 +44773,44 @@ async function scrapeLanding(options) {
|
|
|
44773
44773
|
}
|
|
44774
44774
|
}
|
|
44775
44775
|
|
|
44776
|
+
// src/commands/landing/inspiration/captureOut.ts
|
|
44777
|
+
import { existsSync as existsSync9 } from "fs";
|
|
44778
|
+
import path33 from "path";
|
|
44779
|
+
var SCRATCH_DIR = ".baker";
|
|
44780
|
+
function isWithin(parent, target) {
|
|
44781
|
+
const relative = path33.relative(parent, target);
|
|
44782
|
+
return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
|
|
44783
|
+
}
|
|
44784
|
+
function findRepoRoot(from) {
|
|
44785
|
+
let dir = path33.resolve(from);
|
|
44786
|
+
for (; ; ) {
|
|
44787
|
+
if (existsSync9(path33.join(dir, ".git"))) return dir;
|
|
44788
|
+
const parent = path33.dirname(dir);
|
|
44789
|
+
if (parent === dir) return null;
|
|
44790
|
+
dir = parent;
|
|
44791
|
+
}
|
|
44792
|
+
}
|
|
44793
|
+
function checkCaptureOut(out, options) {
|
|
44794
|
+
const { cwd, repoRoot } = options;
|
|
44795
|
+
const resolved = path33.resolve(cwd, out);
|
|
44796
|
+
if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
|
|
44797
|
+
const scratch = path33.join(repoRoot, SCRATCH_DIR);
|
|
44798
|
+
if (isWithin(scratch, resolved)) return { ok: true };
|
|
44799
|
+
const suggestion = path33.posix.join(SCRATCH_DIR, "teardowns", path33.basename(resolved) || "capture");
|
|
44800
|
+
return {
|
|
44801
|
+
ok: false,
|
|
44802
|
+
error: {
|
|
44803
|
+
code: "CAPTURE_OUT_NOT_SCRATCH",
|
|
44804
|
+
message: `A capture has to be written to ${SCRATCH_DIR}/ inside this workspace. It is reference material for this turn, and anywhere else it becomes a permanent part of the client's files.`,
|
|
44805
|
+
fix: {
|
|
44806
|
+
action: "retry_with_changes",
|
|
44807
|
+
explanation: `Re-run with --out ${suggestion}.`
|
|
44808
|
+
},
|
|
44809
|
+
retryable: false
|
|
44810
|
+
}
|
|
44811
|
+
};
|
|
44812
|
+
}
|
|
44813
|
+
|
|
44776
44814
|
// src/commands/landing/inspiration/scrape.ts
|
|
44777
44815
|
var RETRYABLE_FAILURES = /* @__PURE__ */ new Set([
|
|
44778
44816
|
"SITE_TOO_SLOW",
|
|
@@ -44787,7 +44825,7 @@ async function recordCapture(manifest, outDir) {
|
|
|
44787
44825
|
for (const section of manifest.sections) {
|
|
44788
44826
|
if (!section.bundle) continue;
|
|
44789
44827
|
try {
|
|
44790
|
-
const markup = await readFile23(
|
|
44828
|
+
const markup = await readFile23(path34.join(outDir, section.bundle), "utf8");
|
|
44791
44829
|
const copyStrings = capturedCopyStrings(markup);
|
|
44792
44830
|
if (copyStrings.length === 0) continue;
|
|
44793
44831
|
references.push({
|
|
@@ -44833,7 +44871,7 @@ registerSchema({
|
|
|
44833
44871
|
description: "Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots. Also records every captured section for the originality check.",
|
|
44834
44872
|
args: {
|
|
44835
44873
|
url: { type: "string", description: "Page to capture", required: true },
|
|
44836
|
-
out: { type: "string", description: "Output directory", required: true },
|
|
44874
|
+
out: { type: "string", description: "Output directory under .baker/", required: true },
|
|
44837
44875
|
mobile: { type: "boolean", description: "Phone-viewport pass. `--no-mobile` to skip", required: false },
|
|
44838
44876
|
code: {
|
|
44839
44877
|
type: "boolean",
|
|
@@ -44855,7 +44893,7 @@ var scrapeCommand = defineCommand161({
|
|
|
44855
44893
|
},
|
|
44856
44894
|
args: {
|
|
44857
44895
|
url: { type: "positional", description: "Page to capture", required: true },
|
|
44858
|
-
out: { type: "string", description: "Output directory", required: true },
|
|
44896
|
+
out: { type: "string", description: "Output directory, under .baker/", required: true },
|
|
44859
44897
|
mobile: {
|
|
44860
44898
|
type: "boolean",
|
|
44861
44899
|
description: "Phone-viewport pass (--no-mobile to skip)",
|
|
@@ -44872,6 +44910,14 @@ var scrapeCommand = defineCommand161({
|
|
|
44872
44910
|
report: { type: "boolean", description: "Write report.html (--no-report to skip)", required: false, default: true }
|
|
44873
44911
|
},
|
|
44874
44912
|
run: async ({ args }) => {
|
|
44913
|
+
const location2 = checkCaptureOut(args.out, {
|
|
44914
|
+
cwd: process.cwd(),
|
|
44915
|
+
repoRoot: findRepoRoot(process.cwd())
|
|
44916
|
+
});
|
|
44917
|
+
if (!location2.ok) {
|
|
44918
|
+
writeJson({ ok: false, error: location2.error });
|
|
44919
|
+
process.exit(1);
|
|
44920
|
+
}
|
|
44875
44921
|
try {
|
|
44876
44922
|
const manifest = await scrapeLanding({
|
|
44877
44923
|
url: args.url,
|
|
@@ -44949,12 +44995,12 @@ var scrapeCommand = defineCommand161({
|
|
|
44949
44995
|
});
|
|
44950
44996
|
|
|
44951
44997
|
// src/commands/landing/inspiration/search.ts
|
|
44952
|
-
import
|
|
44998
|
+
import path36 from "path";
|
|
44953
44999
|
import { defineCommand as defineCommand162 } from "citty";
|
|
44954
45000
|
|
|
44955
45001
|
// src/commands/landing/inspiration/shot.ts
|
|
44956
45002
|
import { mkdir as mkdir12, writeFile as writeFile17 } from "fs/promises";
|
|
44957
|
-
import
|
|
45003
|
+
import path35 from "path";
|
|
44958
45004
|
import sharp6 from "sharp";
|
|
44959
45005
|
var READABLE_SHOT = {
|
|
44960
45006
|
maxWidth: 1440,
|
|
@@ -44980,9 +45026,9 @@ async function downloadReadableShot(url, file) {
|
|
|
44980
45026
|
const response = await fetch(url);
|
|
44981
45027
|
if (!response.ok) return null;
|
|
44982
45028
|
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
44983
|
-
await mkdir12(
|
|
45029
|
+
await mkdir12(path35.dirname(file), { recursive: true });
|
|
44984
45030
|
await writeFile17(file, shot);
|
|
44985
|
-
return
|
|
45031
|
+
return path35.relative(process.cwd(), file);
|
|
44986
45032
|
} catch {
|
|
44987
45033
|
return null;
|
|
44988
45034
|
}
|
|
@@ -45074,13 +45120,13 @@ function buildSearchBody(args) {
|
|
|
45074
45120
|
return body;
|
|
45075
45121
|
}
|
|
45076
45122
|
async function downloadShots(results) {
|
|
45077
|
-
const dir =
|
|
45123
|
+
const dir = path36.join(process.cwd(), ".baker", "inspiration");
|
|
45078
45124
|
const saved = /* @__PURE__ */ new Map();
|
|
45079
45125
|
await Promise.all(
|
|
45080
45126
|
results.map(async (result) => {
|
|
45081
45127
|
const file = await downloadReadableShot(
|
|
45082
45128
|
result.desktopShotUrl,
|
|
45083
|
-
|
|
45129
|
+
path36.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
45084
45130
|
);
|
|
45085
45131
|
if (file) saved.set(result.id, file);
|
|
45086
45132
|
})
|
|
@@ -45308,7 +45354,7 @@ var sequencesCommand = defineCommand163({
|
|
|
45308
45354
|
});
|
|
45309
45355
|
|
|
45310
45356
|
// src/commands/landing/inspiration/view.ts
|
|
45311
|
-
import
|
|
45357
|
+
import path37 from "path";
|
|
45312
45358
|
import { defineCommand as defineCommand164 } from "citty";
|
|
45313
45359
|
registerSchema({
|
|
45314
45360
|
command: "landing.inspiration.view",
|
|
@@ -45341,12 +45387,12 @@ var viewCommand2 = defineCommand164({
|
|
|
45341
45387
|
const id = args.id;
|
|
45342
45388
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
45343
45389
|
const section = data.section;
|
|
45344
|
-
const dir =
|
|
45390
|
+
const dir = path37.join(process.cwd(), ".baker", "inspiration", id);
|
|
45345
45391
|
const ext = READABLE_SHOT.extension;
|
|
45346
45392
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
45347
|
-
downloadReadableShot(section.desktopShotUrl,
|
|
45348
|
-
downloadReadableShot(section.mobileShotUrl,
|
|
45349
|
-
downloadReadableShot(section.motionFilmstripUrl,
|
|
45393
|
+
downloadReadableShot(section.desktopShotUrl, path37.join(dir, `desktop.${ext}`)),
|
|
45394
|
+
downloadReadableShot(section.mobileShotUrl, path37.join(dir, `mobile.${ext}`)),
|
|
45395
|
+
downloadReadableShot(section.motionFilmstripUrl, path37.join(dir, `motion-filmstrip.${ext}`))
|
|
45350
45396
|
]);
|
|
45351
45397
|
const full = args.full;
|
|
45352
45398
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -47196,7 +47242,7 @@ var listCommand15 = defineCommand183({
|
|
|
47196
47242
|
|
|
47197
47243
|
// src/commands/scheduled-actions/templates.ts
|
|
47198
47244
|
import { readFile as readFile24 } from "fs/promises";
|
|
47199
|
-
import
|
|
47245
|
+
import path38 from "path";
|
|
47200
47246
|
import { defineCommand as defineCommand184 } from "citty";
|
|
47201
47247
|
registerSchema({
|
|
47202
47248
|
command: "scheduled-actions.templates",
|
|
@@ -47299,7 +47345,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
|
|
|
47299
47345
|
}
|
|
47300
47346
|
if (save.length > 0) {
|
|
47301
47347
|
const briefFile = flag("brief-file");
|
|
47302
|
-
const brief = briefFile.length > 0 ? await readFile24(
|
|
47348
|
+
const brief = briefFile.length > 0 ? await readFile24(path38.resolve(briefFile), "utf8") : flag("brief");
|
|
47303
47349
|
if (brief.trim().length === 0) {
|
|
47304
47350
|
failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
|
|
47305
47351
|
}
|
|
@@ -47770,7 +47816,7 @@ function parseImageRefs(spec) {
|
|
|
47770
47816
|
}
|
|
47771
47817
|
var defaultDeps = {
|
|
47772
47818
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
47773
|
-
upload: (
|
|
47819
|
+
upload: (path40) => uploadLocalImage({ file: path40, contentType: detectImageContentType(path40), source: "uploaded" })
|
|
47774
47820
|
};
|
|
47775
47821
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
47776
47822
|
const refs = parseImageRefs(spec);
|
|
@@ -47790,10 +47836,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
47790
47836
|
}
|
|
47791
47837
|
return { imageIds, added };
|
|
47792
47838
|
}
|
|
47793
|
-
function uploadFailure(
|
|
47839
|
+
function uploadFailure(path40) {
|
|
47794
47840
|
return (error) => {
|
|
47795
47841
|
if (error instanceof ApiError) throw error;
|
|
47796
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
47842
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path40}" as an image.`);
|
|
47797
47843
|
};
|
|
47798
47844
|
}
|
|
47799
47845
|
|
|
@@ -48855,10 +48901,10 @@ async function stageOp4(op) {
|
|
|
48855
48901
|
handleError5(err);
|
|
48856
48902
|
}
|
|
48857
48903
|
}
|
|
48858
|
-
async function draftAction3(
|
|
48904
|
+
async function draftAction3(path40, body, chat) {
|
|
48859
48905
|
const chatId = resolveChatId(chat);
|
|
48860
48906
|
try {
|
|
48861
|
-
const data = await apiPost(
|
|
48907
|
+
const data = await apiPost(path40, { chatId, ...body });
|
|
48862
48908
|
writeJsonEnvelope({ ok: true, data });
|
|
48863
48909
|
return data;
|
|
48864
48910
|
} catch (err) {
|
|
@@ -49965,7 +50011,7 @@ var groupCommand2 = defineCommand209({
|
|
|
49965
50011
|
// src/commands/videos/ingest.ts
|
|
49966
50012
|
import { mkdtemp as mkdtemp2, rm as rm7, stat as stat7 } from "fs/promises";
|
|
49967
50013
|
import { tmpdir as tmpdir3 } from "os";
|
|
49968
|
-
import
|
|
50014
|
+
import path39 from "path";
|
|
49969
50015
|
import { defineCommand as defineCommand210 } from "citty";
|
|
49970
50016
|
|
|
49971
50017
|
// src/lib/streamUpload.ts
|
|
@@ -50316,7 +50362,7 @@ function ingestUrl(args) {
|
|
|
50316
50362
|
}
|
|
50317
50363
|
async function downloadThenIngest(args, country) {
|
|
50318
50364
|
const vimeoCookie = captureVimeoCookie();
|
|
50319
|
-
const workDir = await mkdtemp2(
|
|
50365
|
+
const workDir = await mkdtemp2(path39.join(tmpdir3(), "videos-ingest-"));
|
|
50320
50366
|
try {
|
|
50321
50367
|
const probe = await probeYtDlp({ url: args.url, country, vimeoCookie, cookieDir: workDir });
|
|
50322
50368
|
if (isAudioOnly(probe.info)) {
|
|
@@ -51936,7 +51982,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion) {
|
|
|
51936
51982
|
};
|
|
51937
51983
|
}
|
|
51938
51984
|
function commandPathOf(root, argv) {
|
|
51939
|
-
const
|
|
51985
|
+
const path40 = [];
|
|
51940
51986
|
let command = root;
|
|
51941
51987
|
for (const token of argv) {
|
|
51942
51988
|
if (token === "--" || token.startsWith("-")) {
|
|
@@ -51947,10 +51993,10 @@ function commandPathOf(root, argv) {
|
|
|
51947
51993
|
if (next === void 0 || typeof next !== "object") {
|
|
51948
51994
|
break;
|
|
51949
51995
|
}
|
|
51950
|
-
|
|
51996
|
+
path40.push(token);
|
|
51951
51997
|
command = next;
|
|
51952
51998
|
}
|
|
51953
|
-
return
|
|
51999
|
+
return path40.join(" ");
|
|
51954
52000
|
}
|
|
51955
52001
|
function refuseUnknownFlags(root, argv) {
|
|
51956
52002
|
const unknown = findUnknownFlags(root, argv);
|