@koda-sl/baker-cli 0.449.0-dev.b6179c7f5 → 0.454.0-dev.c94fef7ea
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 +4 -4
- package/dist/{chunk-Y33XAZ5M.js → chunk-MYOTW5GV.js} +39 -6
- package/dist/chunk-MYOTW5GV.js.map +1 -0
- package/dist/cli.js +434 -321
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-Y33XAZ5M.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -201,7 +201,7 @@ import {
|
|
|
201
201
|
withoutCastName,
|
|
202
202
|
wordCount,
|
|
203
203
|
ytDlpBlockSignal
|
|
204
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-MYOTW5GV.js";
|
|
205
205
|
import {
|
|
206
206
|
NAME_CONTAINS_ARG,
|
|
207
207
|
csvOrJson,
|
|
@@ -35514,16 +35514,16 @@ async function runChatgptRead(reference, read, hintsFor4) {
|
|
|
35514
35514
|
}
|
|
35515
35515
|
}
|
|
35516
35516
|
var TRUNCATED_HINT = "These rows are the first 2,000, not the whole account \u2014 narrow the read (--campaign-id, --ad-group-id) before counting them or concluding something is missing.";
|
|
35517
|
-
async function getChatgptList(
|
|
35518
|
-
const { data, headers } = await apiGetWithHeaders(
|
|
35517
|
+
async function getChatgptList(path69, params) {
|
|
35518
|
+
const { data, headers } = await apiGetWithHeaders(path69, params);
|
|
35519
35519
|
return { data, truncated: headers.get(CHATGPT_ADS_TRUNCATED_HEADER) === "true" };
|
|
35520
35520
|
}
|
|
35521
|
-
async function runChatgptListRead(reference,
|
|
35521
|
+
async function runChatgptListRead(reference, path69, params, hintsFor4) {
|
|
35522
35522
|
let truncated = false;
|
|
35523
35523
|
await runChatgptRead(
|
|
35524
35524
|
reference,
|
|
35525
35525
|
async () => {
|
|
35526
|
-
const read = await getChatgptList(
|
|
35526
|
+
const read = await getChatgptList(path69, params);
|
|
35527
35527
|
truncated = read.truncated;
|
|
35528
35528
|
return read.data;
|
|
35529
35529
|
},
|
|
@@ -36328,7 +36328,7 @@ var MEMBER_ARGS = {
|
|
|
36328
36328
|
},
|
|
36329
36329
|
country: { type: "string", description: "Country of phones written without a +code, e.g. ES" }
|
|
36330
36330
|
};
|
|
36331
|
-
function membersFromArgs(args8, readFile52 = (
|
|
36331
|
+
function membersFromArgs(args8, readFile52 = (path69) => readFileSync2(path69, "utf8")) {
|
|
36332
36332
|
const fromFile = typeof args8.file === "string" && args8.file ? membersFromFile(readFile52(args8.file)) : { emails: [], phones: [] };
|
|
36333
36333
|
const given = [...csvArg(args8.emails) ?? [], ...fromFile.emails];
|
|
36334
36334
|
const givenPhones = [...csvArg(args8.phones) ?? [], ...fromFile.phones];
|
|
@@ -39721,9 +39721,9 @@ var COPY_LIST_FLAG = {
|
|
|
39721
39721
|
descriptions: "--descriptions",
|
|
39722
39722
|
longHeadlines: "--long-headlines"
|
|
39723
39723
|
};
|
|
39724
|
-
function valueAt(root,
|
|
39724
|
+
function valueAt(root, path69) {
|
|
39725
39725
|
let node = root;
|
|
39726
|
-
for (const key of
|
|
39726
|
+
for (const key of path69) {
|
|
39727
39727
|
if (node === null || typeof node !== "object") return void 0;
|
|
39728
39728
|
node = node[key];
|
|
39729
39729
|
}
|
|
@@ -39956,11 +39956,11 @@ function parseKeywordEntry(raw, defaultMatch) {
|
|
|
39956
39956
|
function rawTextEntries(value2, rawArgs) {
|
|
39957
39957
|
return repeatedValues(rawArgs, "text", value2).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
39958
39958
|
}
|
|
39959
|
-
function rawFileEntries(
|
|
39960
|
-
if (typeof
|
|
39959
|
+
function rawFileEntries(path69) {
|
|
39960
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
39961
39961
|
return [];
|
|
39962
39962
|
}
|
|
39963
|
-
return readFileSync4(
|
|
39963
|
+
return readFileSync4(path69, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
39964
39964
|
}
|
|
39965
39965
|
function keywordEntries(args8, rawArgs) {
|
|
39966
39966
|
const defaultMatch = typeof args8["match-type"] === "string" ? args8["match-type"].toUpperCase() : void 0;
|
|
@@ -39983,14 +39983,14 @@ function keywordEntries(args8, rawArgs) {
|
|
|
39983
39983
|
}
|
|
39984
39984
|
return entries;
|
|
39985
39985
|
}
|
|
39986
|
-
function loadJsonFileArg(
|
|
39987
|
-
if (typeof
|
|
39986
|
+
function loadJsonFileArg(path69) {
|
|
39987
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
39988
39988
|
return {};
|
|
39989
39989
|
}
|
|
39990
|
-
const inline =
|
|
39991
|
-
const source = inline ? "inline JSON" :
|
|
39990
|
+
const inline = path69.trimStart().startsWith("{");
|
|
39991
|
+
const source = inline ? "inline JSON" : path69;
|
|
39992
39992
|
try {
|
|
39993
|
-
const parsed = JSON.parse(inline ?
|
|
39993
|
+
const parsed = JSON.parse(inline ? path69 : readFileSync4(path69, "utf8"));
|
|
39994
39994
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
39995
39995
|
failWriteValidation2(`${source} must contain a JSON object`);
|
|
39996
39996
|
}
|
|
@@ -40127,10 +40127,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
|
|
|
40127
40127
|
async function stageTarget(kind, customerId, target2, hints2) {
|
|
40128
40128
|
await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
|
|
40129
40129
|
}
|
|
40130
|
-
async function draftAction(
|
|
40130
|
+
async function draftAction(path69, body, chat) {
|
|
40131
40131
|
try {
|
|
40132
40132
|
const chatId = resolveChatId(chat);
|
|
40133
|
-
const response = await apiPost(
|
|
40133
|
+
const response = await apiPost(path69, { chatId, ...body });
|
|
40134
40134
|
writeJsonEnvelope(response);
|
|
40135
40135
|
} catch (err) {
|
|
40136
40136
|
handleGoogleError(err);
|
|
@@ -42550,14 +42550,14 @@ function mappingRowProblem(row2) {
|
|
|
42550
42550
|
|
|
42551
42551
|
// ../api/src/event-sources/template.ts
|
|
42552
42552
|
var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
42553
|
-
function mentionOf(
|
|
42554
|
-
return `{{${
|
|
42553
|
+
function mentionOf(path69) {
|
|
42554
|
+
return `{{${path69}}}`;
|
|
42555
42555
|
}
|
|
42556
42556
|
function templateMentions(template) {
|
|
42557
42557
|
const seen = [];
|
|
42558
42558
|
for (const match of template.matchAll(MENTION)) {
|
|
42559
|
-
const
|
|
42560
|
-
if (
|
|
42559
|
+
const path69 = (match[1] ?? "").trim();
|
|
42560
|
+
if (path69 !== "" && !seen.includes(path69)) seen.push(path69);
|
|
42561
42561
|
}
|
|
42562
42562
|
return seen;
|
|
42563
42563
|
}
|
|
@@ -45954,17 +45954,17 @@ function ignoredColumnHints(columns) {
|
|
|
45954
45954
|
`Ignored ${columns.length} column(s) that are not part of a conversion: ${columns.join(", ")}. A conversion carries an order id, a date, and something to match on: a click id (gclid / gbraid / wbraid), an email, a phone, or all four of givenName + familyName + country + postalCode. Optionally a value + currency, conversionCount, and eventSource (WEB / APP / IN_STORE / PHONE / OTHER). A column named just \`Name\` is ignored on purpose \u2014 Google needs the first and last name separately, so split it before re-running.`
|
|
45955
45955
|
];
|
|
45956
45956
|
}
|
|
45957
|
-
function readRowsFile(
|
|
45958
|
-
const inline =
|
|
45957
|
+
function readRowsFile(path69) {
|
|
45958
|
+
const inline = path69.trimStart().startsWith("[") || path69.trimStart().startsWith("{");
|
|
45959
45959
|
let text3;
|
|
45960
45960
|
try {
|
|
45961
|
-
text3 = inline ?
|
|
45961
|
+
text3 = inline ? path69 : readFileSync6(path69, "utf8");
|
|
45962
45962
|
} catch (err) {
|
|
45963
|
-
failWriteValidation2(`could not read ${
|
|
45963
|
+
failWriteValidation2(`could not read ${path69}: ${err instanceof Error ? err.message : String(err)}`);
|
|
45964
45964
|
}
|
|
45965
45965
|
const parsed = parseConversionRowsText(text3);
|
|
45966
45966
|
if (!parsed.ok) {
|
|
45967
|
-
failWriteValidation2(`${inline ? "the conversions passed inline" :
|
|
45967
|
+
failWriteValidation2(`${inline ? "the conversions passed inline" : path69}: ${parsed.error}`);
|
|
45968
45968
|
}
|
|
45969
45969
|
return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
|
|
45970
45970
|
}
|
|
@@ -47865,19 +47865,19 @@ function failWriteValidation3(message) {
|
|
|
47865
47865
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
47866
47866
|
process.exit(1);
|
|
47867
47867
|
}
|
|
47868
|
-
function loadJsonFileArg2(
|
|
47869
|
-
if (typeof
|
|
47868
|
+
function loadJsonFileArg2(path69) {
|
|
47869
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
47870
47870
|
return {};
|
|
47871
47871
|
}
|
|
47872
47872
|
try {
|
|
47873
|
-
const parsed = JSON.parse(readFileSync7(
|
|
47873
|
+
const parsed = JSON.parse(readFileSync7(path69, "utf8"));
|
|
47874
47874
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
47875
|
-
failWriteValidation3(`${
|
|
47875
|
+
failWriteValidation3(`${path69} must contain a JSON object`);
|
|
47876
47876
|
}
|
|
47877
47877
|
return parsed;
|
|
47878
47878
|
} catch (err) {
|
|
47879
47879
|
if (err instanceof SyntaxError) {
|
|
47880
|
-
failWriteValidation3(`${
|
|
47880
|
+
failWriteValidation3(`${path69} is not valid JSON: ${err.message}`);
|
|
47881
47881
|
}
|
|
47882
47882
|
throw err;
|
|
47883
47883
|
}
|
|
@@ -47962,15 +47962,15 @@ function parseLocaleFlag(value2) {
|
|
|
47962
47962
|
}
|
|
47963
47963
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
47964
47964
|
}
|
|
47965
|
-
function loadTargetingFileArg(
|
|
47966
|
-
if (typeof
|
|
47965
|
+
function loadTargetingFileArg(path69) {
|
|
47966
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
47967
47967
|
return void 0;
|
|
47968
47968
|
}
|
|
47969
|
-
const parsed = loadJsonFileArg2(
|
|
47969
|
+
const parsed = loadJsonFileArg2(path69);
|
|
47970
47970
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
47971
47971
|
if (!criteria.include) {
|
|
47972
47972
|
failWriteValidation3(
|
|
47973
|
-
`${
|
|
47973
|
+
`${path69} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
47974
47974
|
);
|
|
47975
47975
|
}
|
|
47976
47976
|
return criteria;
|
|
@@ -48005,14 +48005,14 @@ function parseCsvLine(line) {
|
|
|
48005
48005
|
cells.push(current);
|
|
48006
48006
|
return cells.map((cell3) => cell3.trim());
|
|
48007
48007
|
}
|
|
48008
|
-
function parseListFileArg(
|
|
48009
|
-
if (typeof
|
|
48008
|
+
function parseListFileArg(path69, maxRows) {
|
|
48009
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
48010
48010
|
return void 0;
|
|
48011
48011
|
}
|
|
48012
|
-
const raw = readFileSync7(
|
|
48012
|
+
const raw = readFileSync7(path69, "utf8");
|
|
48013
48013
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
48014
48014
|
if (lines.length < 2) {
|
|
48015
|
-
failWriteValidation3(`${
|
|
48015
|
+
failWriteValidation3(`${path69} needs a header row and at least one data row`);
|
|
48016
48016
|
}
|
|
48017
48017
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
48018
48018
|
const rows = [];
|
|
@@ -48031,7 +48031,7 @@ function parseListFileArg(path68, maxRows) {
|
|
|
48031
48031
|
}
|
|
48032
48032
|
}
|
|
48033
48033
|
if (rows.length > maxRows) {
|
|
48034
|
-
failWriteValidation3(`${
|
|
48034
|
+
failWriteValidation3(`${path69} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
48035
48035
|
}
|
|
48036
48036
|
return { columns, rows };
|
|
48037
48037
|
}
|
|
@@ -48127,11 +48127,11 @@ function readPositionals(args8) {
|
|
|
48127
48127
|
function splitIdList(raw) {
|
|
48128
48128
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
48129
48129
|
}
|
|
48130
|
-
function idsFileEntries(
|
|
48131
|
-
if (typeof
|
|
48130
|
+
function idsFileEntries(path69) {
|
|
48131
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
48132
48132
|
return [];
|
|
48133
48133
|
}
|
|
48134
|
-
return readFileSync7(
|
|
48134
|
+
return readFileSync7(path69, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
48135
48135
|
}
|
|
48136
48136
|
function requireTargets2(args8, entity) {
|
|
48137
48137
|
const positionals = readPositionals(args8);
|
|
@@ -52233,54 +52233,54 @@ function ruleFields(node) {
|
|
|
52233
52233
|
([key, value2]) => (key === "and" || key === "or") && Array.isArray(value2) ? value2.flatMap(ruleFields) : [key]
|
|
52234
52234
|
);
|
|
52235
52235
|
}
|
|
52236
|
-
function branchRefusal(key, value2,
|
|
52236
|
+
function branchRefusal(key, value2, path69) {
|
|
52237
52237
|
if (!Array.isArray(value2) || value2.length === 0) {
|
|
52238
|
-
return `${
|
|
52238
|
+
return `${path69}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
|
|
52239
52239
|
}
|
|
52240
52240
|
for (const [index, child] of value2.entries()) {
|
|
52241
|
-
const refusal = ruleNodeRefusal(child, `${
|
|
52241
|
+
const refusal = ruleNodeRefusal(child, `${path69}.${key}[${index}]`);
|
|
52242
52242
|
if (refusal) {
|
|
52243
52243
|
return refusal;
|
|
52244
52244
|
}
|
|
52245
52245
|
}
|
|
52246
52246
|
return void 0;
|
|
52247
52247
|
}
|
|
52248
|
-
function conditionRefusal(key, value2,
|
|
52249
|
-
return key === "and" || key === "or" ? branchRefusal(key, value2,
|
|
52248
|
+
function conditionRefusal(key, value2, path69) {
|
|
52249
|
+
return key === "and" || key === "or" ? branchRefusal(key, value2, path69) : leafRefusal(key, value2, path69);
|
|
52250
52250
|
}
|
|
52251
|
-
function ruleNodeRefusal(node,
|
|
52251
|
+
function ruleNodeRefusal(node, path69) {
|
|
52252
52252
|
if (!isRecord2(node)) {
|
|
52253
|
-
return `${
|
|
52253
|
+
return `${path69} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
|
|
52254
52254
|
}
|
|
52255
52255
|
const entries = Object.entries(node);
|
|
52256
52256
|
if (entries.length === 0) {
|
|
52257
|
-
return `${
|
|
52257
|
+
return `${path69} is empty \u2014 a rule with no condition counts every event the pixel sends`;
|
|
52258
52258
|
}
|
|
52259
52259
|
if (entries.length > 1) {
|
|
52260
|
-
return `${
|
|
52260
|
+
return `${path69} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
|
|
52261
52261
|
}
|
|
52262
52262
|
for (const [key, value2] of entries) {
|
|
52263
|
-
const refusal = conditionRefusal(key, value2,
|
|
52263
|
+
const refusal = conditionRefusal(key, value2, path69);
|
|
52264
52264
|
if (refusal) {
|
|
52265
52265
|
return refusal;
|
|
52266
52266
|
}
|
|
52267
52267
|
}
|
|
52268
52268
|
return void 0;
|
|
52269
52269
|
}
|
|
52270
|
-
function leafRefusal(field, condition,
|
|
52270
|
+
function leafRefusal(field, condition, path69) {
|
|
52271
52271
|
if (!isRecord2(condition)) {
|
|
52272
|
-
return `${
|
|
52272
|
+
return `${path69}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
|
|
52273
52273
|
}
|
|
52274
52274
|
const tests = Object.entries(condition);
|
|
52275
52275
|
if (tests.length === 0) {
|
|
52276
|
-
return `${
|
|
52276
|
+
return `${path69}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
|
|
52277
52277
|
}
|
|
52278
52278
|
if (tests.length > 1) {
|
|
52279
|
-
return `${
|
|
52279
|
+
return `${path69}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
|
|
52280
52280
|
}
|
|
52281
52281
|
for (const [operator] of tests) {
|
|
52282
52282
|
if (!RULE_OPERATORS[operator]) {
|
|
52283
|
-
return `${
|
|
52283
|
+
return `${path69}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
|
|
52284
52284
|
}
|
|
52285
52285
|
}
|
|
52286
52286
|
return void 0;
|
|
@@ -52996,11 +52996,11 @@ var updateStatusSchema2 = z52.enum(UPDATE_STATUSES);
|
|
|
52996
52996
|
function currencyMinimums2(currencyCode) {
|
|
52997
52997
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
52998
52998
|
}
|
|
52999
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
52999
|
+
function validateDailyBudgetFloor(money, ctx, path69) {
|
|
53000
53000
|
if (money?.currencyCode) {
|
|
53001
53001
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
53002
53002
|
if (Number(money.amount) < min) {
|
|
53003
|
-
ctx.addIssue({ code: "custom", path:
|
|
53003
|
+
ctx.addIssue({ code: "custom", path: path69, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
53004
53004
|
}
|
|
53005
53005
|
}
|
|
53006
53006
|
}
|
|
@@ -53918,19 +53918,19 @@ function refuseDeleteByUpdate(payload, group) {
|
|
|
53918
53918
|
);
|
|
53919
53919
|
}
|
|
53920
53920
|
}
|
|
53921
|
-
function loadJsonFileArg3(
|
|
53922
|
-
if (typeof
|
|
53921
|
+
function loadJsonFileArg3(path69) {
|
|
53922
|
+
if (typeof path69 !== "string" || path69.length === 0) {
|
|
53923
53923
|
return {};
|
|
53924
53924
|
}
|
|
53925
53925
|
try {
|
|
53926
|
-
const parsed = JSON.parse(readFileSync11(
|
|
53926
|
+
const parsed = JSON.parse(readFileSync11(path69, "utf8"));
|
|
53927
53927
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
53928
|
-
failWriteValidation4(`${
|
|
53928
|
+
failWriteValidation4(`${path69} must contain a JSON object`);
|
|
53929
53929
|
}
|
|
53930
53930
|
return parsed;
|
|
53931
53931
|
} catch (err) {
|
|
53932
53932
|
if (err instanceof SyntaxError) {
|
|
53933
|
-
failWriteValidation4(`${
|
|
53933
|
+
failWriteValidation4(`${path69} is not valid JSON: ${err.message}`);
|
|
53934
53934
|
}
|
|
53935
53935
|
throw err;
|
|
53936
53936
|
}
|
|
@@ -54832,9 +54832,9 @@ var listArgs6 = {
|
|
|
54832
54832
|
},
|
|
54833
54833
|
...META_LIST_SHAPE_ARGS
|
|
54834
54834
|
};
|
|
54835
|
-
async function readOrEmpty(
|
|
54835
|
+
async function readOrEmpty(path69, params, label, hints2) {
|
|
54836
54836
|
try {
|
|
54837
|
-
return await apiGet(
|
|
54837
|
+
return await apiGet(path69, params);
|
|
54838
54838
|
} catch (err) {
|
|
54839
54839
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
54840
54840
|
hints2.push(`Could not read the account's ${label} (${message}); the viewer was read without them.`);
|
|
@@ -59777,12 +59777,12 @@ function flowExists(slug) {
|
|
|
59777
59777
|
return existsSync3(join2(flowsDir(), slug, "_data.json"));
|
|
59778
59778
|
}
|
|
59779
59779
|
function readFlowTree(slug) {
|
|
59780
|
-
const
|
|
59781
|
-
if (!existsSync3(
|
|
59780
|
+
const path69 = join2(flowsDir(), slug, "_data.json");
|
|
59781
|
+
if (!existsSync3(path69)) {
|
|
59782
59782
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
59783
59783
|
}
|
|
59784
59784
|
try {
|
|
59785
|
-
return JSON.parse(readFileSync13(
|
|
59785
|
+
return JSON.parse(readFileSync13(path69, "utf-8"));
|
|
59786
59786
|
} catch (error) {
|
|
59787
59787
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
59788
59788
|
}
|
|
@@ -60759,12 +60759,12 @@ function readPeopleFile(args8) {
|
|
|
60759
60759
|
}
|
|
60760
60760
|
function unreadablePeopleFile(args8) {
|
|
60761
60761
|
if (!args8["people-file"]) return void 0;
|
|
60762
|
-
const
|
|
60762
|
+
const path69 = String(args8["people-file"]);
|
|
60763
60763
|
try {
|
|
60764
|
-
readFileSync14(
|
|
60764
|
+
readFileSync14(path69, "utf8");
|
|
60765
60765
|
return void 0;
|
|
60766
60766
|
} catch {
|
|
60767
|
-
return `Couldn't read --people-file ${
|
|
60767
|
+
return `Couldn't read --people-file ${path69}. Check the path, or pass the people inline with --person.`;
|
|
60768
60768
|
}
|
|
60769
60769
|
}
|
|
60770
60770
|
function peopleLimitError(args8) {
|
|
@@ -61736,11 +61736,11 @@ function parseFieldArgs(argv) {
|
|
|
61736
61736
|
for (const pair of parseRepeated(argv, "--field")) {
|
|
61737
61737
|
const eq = pair.indexOf("=");
|
|
61738
61738
|
const field = eq === -1 ? pair : pair.slice(0, eq);
|
|
61739
|
-
const
|
|
61739
|
+
const path69 = eq === -1 ? "" : pair.slice(eq + 1).trim();
|
|
61740
61740
|
const problem = mappingRowProblem(field);
|
|
61741
61741
|
if (problem !== null) throw new ConversionArgsError(problem);
|
|
61742
|
-
if (
|
|
61743
|
-
mapping[field] =
|
|
61742
|
+
if (path69 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
|
|
61743
|
+
mapping[field] = path69;
|
|
61744
61744
|
}
|
|
61745
61745
|
return mapping;
|
|
61746
61746
|
}
|
|
@@ -63413,11 +63413,11 @@ function unwrap(response) {
|
|
|
63413
63413
|
}
|
|
63414
63414
|
return response.data;
|
|
63415
63415
|
}
|
|
63416
|
-
async function readAvatars(
|
|
63417
|
-
return unwrap(await apiGet(
|
|
63416
|
+
async function readAvatars(path69, params) {
|
|
63417
|
+
return unwrap(await apiGet(path69, params));
|
|
63418
63418
|
}
|
|
63419
|
-
async function writeAvatars(
|
|
63420
|
-
return unwrap(await apiPost(
|
|
63419
|
+
async function writeAvatars(path69, body, opts) {
|
|
63420
|
+
return unwrap(await apiPost(path69, body, opts));
|
|
63421
63421
|
}
|
|
63422
63422
|
|
|
63423
63423
|
// src/commands/avatars/create.ts
|
|
@@ -64531,12 +64531,12 @@ function missingFontFiles(urls, available) {
|
|
|
64531
64531
|
function planFontAdoption(sources, families) {
|
|
64532
64532
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
64533
64533
|
const byFamily = /* @__PURE__ */ new Map();
|
|
64534
|
-
for (const { path:
|
|
64535
|
-
const dir = posix.dirname(
|
|
64534
|
+
for (const { path: path69, source } of sources) {
|
|
64535
|
+
const dir = posix.dirname(path69);
|
|
64536
64536
|
for (const face of declaredFontFaces(source)) {
|
|
64537
64537
|
if (!wanted.has(face.family)) continue;
|
|
64538
64538
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
64539
|
-
perFile.set(
|
|
64539
|
+
perFile.set(path69, [...perFile.get(path69) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
64540
64540
|
byFamily.set(face.family, perFile);
|
|
64541
64541
|
}
|
|
64542
64542
|
}
|
|
@@ -67205,8 +67205,8 @@ function logoComposited(opts) {
|
|
|
67205
67205
|
}
|
|
67206
67206
|
var MAX_TAKES = 3;
|
|
67207
67207
|
var UNCOMPILED = "compiled from prompt.json";
|
|
67208
|
-
function ingestNode(id,
|
|
67209
|
-
return { id, type: "ingest", params: { source: "path", path:
|
|
67208
|
+
function ingestNode(id, path69, expect) {
|
|
67209
|
+
return { id, type: "ingest", params: { source: "path", path: path69, expect } };
|
|
67210
67210
|
}
|
|
67211
67211
|
function aspectRatio(blueprint, opts) {
|
|
67212
67212
|
const requested = opts.aspectRatio ?? blueprint.meta?.estimated_aspect_ratio;
|
|
@@ -67496,19 +67496,32 @@ function variantStage(canvas) {
|
|
|
67496
67496
|
const template = [...variants, ...calls].find((n) => n.type === "image_generate");
|
|
67497
67497
|
const master = nodesWithRole(canvas, STATIC_MASTER_ROLE)[0];
|
|
67498
67498
|
if (!template || !master) throw new Error("not a static ad canvas: it renders no variants to correct");
|
|
67499
|
+
const masterInputs = JSON.stringify(master.inputs ?? {});
|
|
67500
|
+
const prefilter = nodesWithRole(canvas, VARIANT_PREFILTER_ROLE).find((n) => masterInputs.includes(`$ref:${n.id}.`));
|
|
67499
67501
|
const removed = new Set(
|
|
67500
67502
|
[
|
|
67501
67503
|
...variants,
|
|
67502
67504
|
...calls,
|
|
67503
|
-
...nodesWithRole(canvas, VARIANT_PREFILTER_ROLE),
|
|
67505
|
+
...nodesWithRole(canvas, VARIANT_PREFILTER_ROLE).filter((n) => n !== prefilter),
|
|
67504
67506
|
...nodesWithRole(canvas, STATIC_PICK_ROLE)
|
|
67505
67507
|
].map((n) => n.id)
|
|
67506
67508
|
);
|
|
67507
|
-
return {
|
|
67509
|
+
return {
|
|
67510
|
+
removed,
|
|
67511
|
+
template,
|
|
67512
|
+
masterId: master.id,
|
|
67513
|
+
...prefilter ? { prefilterId: prefilter.id } : {}
|
|
67514
|
+
};
|
|
67508
67515
|
}
|
|
67509
67516
|
function withMasterSource(canvas, stage, source, ref2, opts) {
|
|
67510
|
-
const kept = canvas.nodes.filter((n) => !stage.removed.has(n.id)).map((n) =>
|
|
67511
|
-
|
|
67517
|
+
const kept = canvas.nodes.filter((n) => !stage.removed.has(n.id)).map((n) => {
|
|
67518
|
+
if (n.id === stage.prefilterId) {
|
|
67519
|
+
const { judge_model: _judge, judge_prompt: _prompt, ...params } = n.params ?? {};
|
|
67520
|
+
return { ...n, inputs: { ...n.inputs, images: [ref2] }, params };
|
|
67521
|
+
}
|
|
67522
|
+
return n.id === stage.masterId && !stage.prefilterId ? { ...n, inputs: { ...n.inputs, image: ref2 } } : n;
|
|
67523
|
+
});
|
|
67524
|
+
const at = kept.findIndex((n) => n.id === (stage.prefilterId ?? stage.masterId));
|
|
67512
67525
|
const description = `${canvas.metadata?.description ?? ""} ${opts.note}`;
|
|
67513
67526
|
return {
|
|
67514
67527
|
...canvas,
|
|
@@ -67690,11 +67703,15 @@ function unsourcedFigureLines(spec, knowledge2) {
|
|
|
67690
67703
|
const records = withDigits(knowledge2);
|
|
67691
67704
|
const lower = knowledge2.toLowerCase();
|
|
67692
67705
|
return spec.copy.flatMap((line) => {
|
|
67693
|
-
const
|
|
67694
|
-
const
|
|
67695
|
-
|
|
67706
|
+
const figures = [...withDigits(line.text).matchAll(CLAIMED_FIGURE)].filter((m) => !figureSourced(m, records));
|
|
67707
|
+
const superlatives = [...line.text.matchAll(SUPERLATIVE)].filter((m) => !lower.includes(m[0].toLowerCase()));
|
|
67708
|
+
const claims = [...new Set([...superlatives, ...figures].map((m) => m[0].trim()))];
|
|
67709
|
+
return claims.length > 0 ? [{ text: line.text, claims }] : [];
|
|
67696
67710
|
});
|
|
67697
67711
|
}
|
|
67712
|
+
function claimsWithoutSource(spec, knowledge2) {
|
|
67713
|
+
return [...new Set(unsourcedFigureLines(spec, knowledge2).flatMap((l) => l.claims))];
|
|
67714
|
+
}
|
|
67698
67715
|
function proofProblems(spec, knowledge2) {
|
|
67699
67716
|
const problems = [];
|
|
67700
67717
|
const named = /* @__PURE__ */ new Set();
|
|
@@ -67713,9 +67730,10 @@ function proofProblems(spec, knowledge2) {
|
|
|
67713
67730
|
);
|
|
67714
67731
|
}
|
|
67715
67732
|
}
|
|
67716
|
-
for (const text3 of unsourcedFigureLines(spec, knowledge2)) {
|
|
67733
|
+
for (const { text: text3, claims } of unsourcedFigureLines(spec, knowledge2)) {
|
|
67734
|
+
const named2 = claims.map((c) => `"${c}"`).join(", ");
|
|
67717
67735
|
problems.push(
|
|
67718
|
-
|
|
67736
|
+
`${claims.length === 1 && claims[0] === text3.trim() ? named2 : `${named2} in "${text3}"`}: the company's records (src/content, COMPANY.md) do not hold it, so the line promises what nobody wrote. Say only what they record, or drop ${claims.length === 1 ? "it" : "them"}.`
|
|
67719
67737
|
);
|
|
67720
67738
|
}
|
|
67721
67739
|
return problems;
|
|
@@ -71253,11 +71271,28 @@ function repeatedFailure(idea, failed) {
|
|
|
71253
71271
|
);
|
|
71254
71272
|
return lost ? [`says what "${lost.id}" said, and that idea failed in the account: change the message, not just the picture`] : [];
|
|
71255
71273
|
}
|
|
71274
|
+
function likelyMeant(id, insights) {
|
|
71275
|
+
const words2 = (text3) => new Set(
|
|
71276
|
+
text3.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((w) => w.length >= 3)
|
|
71277
|
+
);
|
|
71278
|
+
const wanted = words2(id);
|
|
71279
|
+
let best;
|
|
71280
|
+
for (const insight of insights.values()) {
|
|
71281
|
+
const said = words2(`${insight.id} ${insight.quote}`);
|
|
71282
|
+
const shared = [...wanted].filter((w) => said.has(w)).length;
|
|
71283
|
+
if (shared > 0 && shared > (best?.shared ?? 0)) best = { id: insight.id, shared };
|
|
71284
|
+
}
|
|
71285
|
+
return best?.id;
|
|
71286
|
+
}
|
|
71256
71287
|
function backingOf(idea, insights, problems) {
|
|
71257
71288
|
const backing = idea.evidence.flatMap((id) => {
|
|
71258
71289
|
const insight = insights.get(id);
|
|
71259
|
-
if (!insight)
|
|
71260
|
-
|
|
71290
|
+
if (!insight) {
|
|
71291
|
+
const meant = likelyMeant(id, insights);
|
|
71292
|
+
problems.push(
|
|
71293
|
+
`evidence "${id}" is not in src/content/insights/: ${meant ? `did you mean "${meant}"? ` : ""}name an insight on file by its id, or leave it out`
|
|
71294
|
+
);
|
|
71295
|
+
}
|
|
71261
71296
|
return insight ? [insight] : [];
|
|
71262
71297
|
});
|
|
71263
71298
|
return [...backing].sort((a, b) => EVIDENCE_WEIGHT[b.status] - EVIDENCE_WEIGHT[a.status])[0];
|
|
@@ -71761,11 +71796,15 @@ async function staticSpecGate(canvas, canvasDir) {
|
|
|
71761
71796
|
{
|
|
71762
71797
|
code: "proof_without_source",
|
|
71763
71798
|
problems: proofProblems(spec, records),
|
|
71764
|
-
fix:
|
|
71799
|
+
fix: proofFix(claimsWithoutSource(spec, records))
|
|
71765
71800
|
}
|
|
71766
71801
|
];
|
|
71767
71802
|
return oneRefusal(gates.filter((g) => g.problems.length > 0));
|
|
71768
71803
|
}
|
|
71804
|
+
function proofFix(claims) {
|
|
71805
|
+
const named = claims.length > 0 ? `drop ${claims.map((c) => `"${c}"`).join(", ")} or source it in the Knowledge, and ` : "";
|
|
71806
|
+
return `In prompt.json, ${named}wire the badge or drop any other claim named above, everywhere it appears (copy and scene).`;
|
|
71807
|
+
}
|
|
71769
71808
|
function oneRefusal(gates) {
|
|
71770
71809
|
const first = gates[0];
|
|
71771
71810
|
if (!first) return null;
|
|
@@ -72289,6 +72328,9 @@ async function readRenderState(canvasRoot, slug) {
|
|
|
72289
72328
|
return {};
|
|
72290
72329
|
}
|
|
72291
72330
|
}
|
|
72331
|
+
async function latestVersion(canvasRoot, slug) {
|
|
72332
|
+
return (await readRenderState(canvasRoot, slug)).rendered?.runId ?? null;
|
|
72333
|
+
}
|
|
72292
72334
|
async function updateRenderState(canvasRoot, slug, patch) {
|
|
72293
72335
|
try {
|
|
72294
72336
|
const next = { ...await readRenderState(canvasRoot, slug), ...patch };
|
|
@@ -72751,6 +72793,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
|
72751
72793
|
|
|
72752
72794
|
// src/commands/canvas/run-resume.ts
|
|
72753
72795
|
import { randomUUID } from "crypto";
|
|
72796
|
+
import { rmSync } from "fs";
|
|
72754
72797
|
import { mkdir as mkdir4, readFile as readFile17, rm as rm4, writeFile as writeFile9 } from "fs/promises";
|
|
72755
72798
|
import path22 from "path";
|
|
72756
72799
|
function markerKey(canvasPath) {
|
|
@@ -72854,6 +72897,40 @@ async function markRunInFlight(outputsDir, canvasPath, runId, sourceSha) {
|
|
|
72854
72897
|
timer.unref();
|
|
72855
72898
|
return { token, stop: () => clearInterval(timer) };
|
|
72856
72899
|
}
|
|
72900
|
+
function busyFile(outputsDir, canvasPath) {
|
|
72901
|
+
return path22.join(outputsDir, ".inflight", `${markerKey(canvasPath)}.busy.json`);
|
|
72902
|
+
}
|
|
72903
|
+
async function markCanvasBusy(outputsDir, canvasPath, runId, pid = process.pid) {
|
|
72904
|
+
const file = busyFile(outputsDir, canvasPath);
|
|
72905
|
+
const write = () => writeFile9(file, JSON.stringify({ runId, pid, heartbeatAt: Date.now() }));
|
|
72906
|
+
try {
|
|
72907
|
+
await mkdir4(path22.dirname(file), { recursive: true });
|
|
72908
|
+
await write();
|
|
72909
|
+
} catch {
|
|
72910
|
+
}
|
|
72911
|
+
const timer = setInterval(() => void write().catch(() => void 0), HEARTBEAT_MS);
|
|
72912
|
+
timer.unref();
|
|
72913
|
+
let released = false;
|
|
72914
|
+
const release = () => {
|
|
72915
|
+
if (released) return;
|
|
72916
|
+
released = true;
|
|
72917
|
+
clearInterval(timer);
|
|
72918
|
+
try {
|
|
72919
|
+
rmSync(file, { force: true });
|
|
72920
|
+
} catch {
|
|
72921
|
+
}
|
|
72922
|
+
};
|
|
72923
|
+
return { release };
|
|
72924
|
+
}
|
|
72925
|
+
async function canvasBusyElsewhere(outputsDir, canvasPath, now = Date.now()) {
|
|
72926
|
+
try {
|
|
72927
|
+
const held = JSON.parse(await readFile17(busyFile(outputsDir, canvasPath), "utf8"));
|
|
72928
|
+
if (typeof held.runId !== "string" || held.pid === void 0 || held.pid === process.pid) return null;
|
|
72929
|
+
return isLiveRender(held, now) ? { runId: held.runId, pid: held.pid } : null;
|
|
72930
|
+
} catch {
|
|
72931
|
+
return null;
|
|
72932
|
+
}
|
|
72933
|
+
}
|
|
72857
72934
|
async function clearRunMarker(outputsDir, canvasPath, token) {
|
|
72858
72935
|
try {
|
|
72859
72936
|
if (token !== void 0) {
|
|
@@ -73573,7 +73650,7 @@ var sizesOf = (what) => what.match(/^(\d+(?:\.\d+)?:\d+(?:\.\d+)?(?:,\s*\d+(?:\.
|
|
|
73573
73650
|
function carryUnchanged(now, prior, unchanged) {
|
|
73574
73651
|
const settled = (f) => {
|
|
73575
73652
|
const sizes = sizesOf(f.what);
|
|
73576
|
-
return sizes.length > 0 && sizes.every((s) => unchanged.includes(s));
|
|
73653
|
+
return sizes.length > 0 && sizes.every((s) => unchanged.includes(s)) && !SIZES_FINDING.test(withoutSize(f.what));
|
|
73577
73654
|
};
|
|
73578
73655
|
return [...now.filter((f) => !settled(f)), ...prior.filter(settled)];
|
|
73579
73656
|
}
|
|
@@ -73657,7 +73734,12 @@ function autoFixStep(canvas, review, opts = {}) {
|
|
|
73657
73734
|
if (ids2.length > 0) return { kind: "relayout", ids: ids2, edits, ...placing };
|
|
73658
73735
|
return extend.length > 0 ? { kind: "extend", sizes: extend } : null;
|
|
73659
73736
|
};
|
|
73660
|
-
const
|
|
73737
|
+
const onSeveralSizes = (f) => {
|
|
73738
|
+
const what = withoutSize(f.what);
|
|
73739
|
+
return new Set(rest.filter((g) => withoutSize(g.what) === what).flatMap((g) => sizesOf(g.what))).size >= 2;
|
|
73740
|
+
};
|
|
73741
|
+
const settledPicture = opts.previous === "relayout" || opts.previous === "extend";
|
|
73742
|
+
const pictureFindings = rest.filter((f) => !at(f) && (!settledPicture || onSeveralSizes(f)));
|
|
73661
73743
|
const onPicture = unique(pictureFindings.map((f) => withoutSize(f.what)));
|
|
73662
73744
|
if (onPicture.length === 0) return sizesOnly();
|
|
73663
73745
|
const every = unique([...extend, ...deliveredSizes(canvas)]);
|
|
@@ -75183,8 +75265,8 @@ var Answer = z67.object({
|
|
|
75183
75265
|
changed: z67.string().min(1),
|
|
75184
75266
|
set: z67.array(z67.object({ path: z67.string().min(1), value: z67.unknown() }))
|
|
75185
75267
|
});
|
|
75186
|
-
function withValueAt(root,
|
|
75187
|
-
const [key, ...rest] =
|
|
75268
|
+
function withValueAt(root, path69, value2) {
|
|
75269
|
+
const [key, ...rest] = path69;
|
|
75188
75270
|
if (key === void 0) return value2;
|
|
75189
75271
|
if (Array.isArray(root)) {
|
|
75190
75272
|
const at = Number(key);
|
|
@@ -75202,7 +75284,7 @@ function printedWords(spec) {
|
|
|
75202
75284
|
function acceptRepair(before, answer) {
|
|
75203
75285
|
const parsed = Answer.safeParse(answer);
|
|
75204
75286
|
if (!parsed.success || !isAdSpec(before)) return null;
|
|
75205
|
-
const spec = parsed.data.set.reduce((at, { path:
|
|
75287
|
+
const spec = parsed.data.set.reduce((at, { path: path69, value: value2 }) => withValueAt(at, path69.split("."), value2), before);
|
|
75206
75288
|
if (!isAdSpec(spec)) return null;
|
|
75207
75289
|
const was = AdSpecSchema.safeParse(before);
|
|
75208
75290
|
const now = AdSpecSchema.safeParse(spec);
|
|
@@ -75390,6 +75472,7 @@ async function canvasFileFor(opts) {
|
|
|
75390
75472
|
throw e;
|
|
75391
75473
|
}
|
|
75392
75474
|
}
|
|
75475
|
+
var canvasHeld = false;
|
|
75393
75476
|
async function executeCanvasRun(opts) {
|
|
75394
75477
|
const { canvasPath: filePath, adoptRunId } = await canvasFileFor(opts);
|
|
75395
75478
|
const canvasRoot = canvasOutputsRoot(filePath);
|
|
@@ -75509,8 +75592,8 @@ ${describeRewrites(prepared.rewrites)}
|
|
|
75509
75592
|
});
|
|
75510
75593
|
const last = Object.fromEntries(
|
|
75511
75594
|
nodesWithRole(parsed, STATIC_ADAPT_FORMAT_ROLE).flatMap((n) => {
|
|
75512
|
-
const
|
|
75513
|
-
return
|
|
75595
|
+
const path69 = delivered.find((d) => d.format === formatOfAdaptId(n.id))?.path;
|
|
75596
|
+
return path69 ? [[n.id, path69]] : [];
|
|
75514
75597
|
})
|
|
75515
75598
|
);
|
|
75516
75599
|
parsed = withSizesFollowingFix(parsed, {
|
|
@@ -75647,14 +75730,15 @@ ${describeRewrites(prepared.rewrites)}
|
|
|
75647
75730
|
sourceSha,
|
|
75648
75731
|
remote: client && creativeSlug && sourceSha ? { creativeSlug, sourceSha, getActiveRun: (slug, sha) => client.getActiveRun(slug, sha) } : void 0
|
|
75649
75732
|
});
|
|
75650
|
-
|
|
75733
|
+
const holder = rendering ?? await canvasBusyElsewhere(outputsDir, filePath);
|
|
75734
|
+
if (holder) {
|
|
75651
75735
|
process.stderr.write(
|
|
75652
75736
|
`${JSON.stringify(
|
|
75653
75737
|
{
|
|
75654
75738
|
ok: false,
|
|
75655
75739
|
error: {
|
|
75656
75740
|
code: "CONFLICT",
|
|
75657
|
-
message: `This canvas is already rendering in another process (run ${
|
|
75741
|
+
message: `This canvas is already rendering in another process (run ${holder.runId}, pid ${holder.pid}).`,
|
|
75658
75742
|
fix: "Wait for that render to finish and use its result instead of starting a second one: two renders of one canvas share a run and overwrite each other. If you started it in the background, read its output when it completes."
|
|
75659
75743
|
}
|
|
75660
75744
|
},
|
|
@@ -75717,6 +75801,11 @@ ${describeRewrites(prepared.rewrites)}
|
|
|
75717
75801
|
});
|
|
75718
75802
|
}
|
|
75719
75803
|
const inFlight = await markRunInFlight(outputsDir, filePath, runId, sourceSha);
|
|
75804
|
+
if (!canvasHeld) {
|
|
75805
|
+
const held = await markCanvasBusy(outputsDir, filePath, runId);
|
|
75806
|
+
canvasHeld = true;
|
|
75807
|
+
process.once("exit", held.release);
|
|
75808
|
+
}
|
|
75720
75809
|
const clearMarker = () => {
|
|
75721
75810
|
inFlight.stop();
|
|
75722
75811
|
return clearRunMarker(outputsDir, filePath, inFlight.token);
|
|
@@ -80704,8 +80793,8 @@ var FLAG_FOR_FIELD = {
|
|
|
80704
80793
|
first_seen_after: "--first-seen-after",
|
|
80705
80794
|
first_seen_before: "--first-seen-before"
|
|
80706
80795
|
};
|
|
80707
|
-
function flagFor(
|
|
80708
|
-
const field = String(
|
|
80796
|
+
function flagFor(path69) {
|
|
80797
|
+
const field = String(path69[0] === "hard_filters" ? path69[1] : path69[0]);
|
|
80709
80798
|
return FLAG_FOR_FIELD[field] ?? field;
|
|
80710
80799
|
}
|
|
80711
80800
|
function schemaRejection(body) {
|
|
@@ -81381,10 +81470,12 @@ async function readViewer(root, adSet) {
|
|
|
81381
81470
|
}
|
|
81382
81471
|
var MARKET_ADS = 40;
|
|
81383
81472
|
var MARKET_FALLBACK_ADS = 15;
|
|
81384
|
-
var MARKET_SEARCH_MS =
|
|
81473
|
+
var MARKET_SEARCH_MS = 12e3;
|
|
81474
|
+
var MARKET_QUERY_WORDS = 6;
|
|
81385
81475
|
function marketQuery(companyDoc) {
|
|
81386
|
-
const
|
|
81387
|
-
|
|
81476
|
+
const first = companyDoc.split("\n").find((line) => line.trim() && !line.trim().startsWith("#")) ?? "";
|
|
81477
|
+
const what = first.replace(/^\s*[-*]\s+/, "").replace(/^\*\*[^*]+\*\*\s*[—–:-]?\s*/, "").split(/\s+for\s+|[,.;:(]|\s[—–-]\s/)[0];
|
|
81478
|
+
return (what ?? "").trim().split(/\s+/).filter(Boolean).slice(0, MARKET_QUERY_WORDS).join(" ");
|
|
81388
81479
|
}
|
|
81389
81480
|
async function readMarket(root) {
|
|
81390
81481
|
const query = marketQuery(await readFile36(path44.join(root, "COMPANY.md"), "utf8").catch(() => ""));
|
|
@@ -81397,14 +81488,14 @@ async function readMarket(root) {
|
|
|
81397
81488
|
}
|
|
81398
81489
|
throw err;
|
|
81399
81490
|
});
|
|
81400
|
-
const followed = await
|
|
81401
|
-
buildSearchBody({ scope: "followed", platform: "meta", limit: MARKET_ADS, maxPerAdvertiser: 8 })
|
|
81402
|
-
|
|
81403
|
-
|
|
81404
|
-
|
|
81405
|
-
|
|
81406
|
-
);
|
|
81407
|
-
return all.results.length > 0 ? marketMap(all.results, "library") : null;
|
|
81491
|
+
const [followed, all] = await Promise.allSettled([
|
|
81492
|
+
search(buildSearchBody({ scope: "followed", platform: "meta", limit: MARKET_ADS, maxPerAdvertiser: 8 })),
|
|
81493
|
+
search(buildSearchBody({ query, scope: "all", platform: "meta", limit: MARKET_FALLBACK_ADS, maxPerAdvertiser: 3 }))
|
|
81494
|
+
]);
|
|
81495
|
+
if (followed.status === "fulfilled" && followed.value.results.length > 0)
|
|
81496
|
+
return marketMap(followed.value.results, "followed");
|
|
81497
|
+
if (all.status === "rejected") throw all.reason;
|
|
81498
|
+
return all.value.results.length > 0 ? marketMap(all.value.results, "library") : null;
|
|
81408
81499
|
}
|
|
81409
81500
|
async function metaAccountId(given) {
|
|
81410
81501
|
if (given) return given.startsWith("act_") ? given : `act_${given}`;
|
|
@@ -81596,12 +81687,26 @@ import { defineCommand as defineCommand157 } from "citty";
|
|
|
81596
81687
|
|
|
81597
81688
|
// src/commands/creatives/feedback-record.ts
|
|
81598
81689
|
import { defineCommand as defineCommand156 } from "citty";
|
|
81690
|
+
|
|
81691
|
+
// src/commands/creatives/version-of.ts
|
|
81692
|
+
import path45 from "path";
|
|
81693
|
+
async function versionOf(slug, run3) {
|
|
81694
|
+
if (typeof run3 === "string" && run3.trim()) return run3.trim();
|
|
81695
|
+
const canvas = path45.join("src", "creatives", slug, `${slug}.canvas.json`);
|
|
81696
|
+
return await latestVersion(canvasOutputsRoot(canvas), slug) ?? void 0;
|
|
81697
|
+
}
|
|
81698
|
+
|
|
81699
|
+
// src/commands/creatives/feedback-record.ts
|
|
81599
81700
|
var DESCRIPTION7 = `Record what the user said about one version of a creative in this chat: Approve, or Not this one with reasons. Saved as their verdict (the person who wrote the latest message here), exactly like reviewing it in Baker, and read back by baker creatives feedback. One verdict per person per version or option: a later one replaces it.
|
|
81600
|
-
Start here: baker creatives feedback record --slug spring-offer --
|
|
81701
|
+
Start here: baker creatives feedback record --slug spring-offer --verdict rejected --reasons text_mistakes --note "<their words>"
|
|
81601
81702
|
Only record what the user said, never your own judgment. Picking one of several concepts is not a rejection of the others.`;
|
|
81602
81703
|
var ARGS10 = {
|
|
81603
81704
|
slug: { type: "string", description: "The creative: its folder name under src/creatives/.", required: true },
|
|
81604
|
-
run: {
|
|
81705
|
+
run: {
|
|
81706
|
+
type: "string",
|
|
81707
|
+
description: "The version: its canvas run id (r_\u2026) Left out, the version the creative shows now (its last render).",
|
|
81708
|
+
required: false
|
|
81709
|
+
},
|
|
81605
81710
|
option: {
|
|
81606
81711
|
type: "string",
|
|
81607
81712
|
description: 'One option of a version that made several: its label ("ugc"), its number ("2") or its slot. Left out, the whole version.',
|
|
@@ -81655,7 +81760,9 @@ var feedbackRecordCommand = defineCommand156({
|
|
|
81655
81760
|
}
|
|
81656
81761
|
const parsed = creativesFeedbackRecordRequestSchema.safeParse({
|
|
81657
81762
|
slug: args8.slug,
|
|
81658
|
-
runId: args8.run
|
|
81763
|
+
runId: await versionOf(String(args8.slug), args8.run).then(
|
|
81764
|
+
(run3) => run3 ?? fail5("VALIDATION_ERROR", "--run: this creative has no rendered version here; name one (r_\u2026).")
|
|
81765
|
+
),
|
|
81659
81766
|
...typeof args8.option === "string" && args8.option.trim() ? { option: args8.option.trim() } : {},
|
|
81660
81767
|
verdict: args8.verdict,
|
|
81661
81768
|
...reasons ? { reasons } : {},
|
|
@@ -81730,7 +81837,7 @@ var feedbackCommand = defineCommand157({
|
|
|
81730
81837
|
// src/commands/creatives/learn.ts
|
|
81731
81838
|
import { readFileSync as readFileSync18 } from "fs";
|
|
81732
81839
|
import { readFile as readFile37, writeFile as writeFile23 } from "fs/promises";
|
|
81733
|
-
import
|
|
81840
|
+
import path46 from "path";
|
|
81734
81841
|
import { defineCommand as defineCommand158 } from "citty";
|
|
81735
81842
|
|
|
81736
81843
|
// src/commands/creatives/learn-model.ts
|
|
@@ -81952,14 +82059,14 @@ function learnEnvelope(learnings, written, unreadable = []) {
|
|
|
81952
82059
|
}
|
|
81953
82060
|
async function writeBack(root, learnings) {
|
|
81954
82061
|
for (const learning of learnings) {
|
|
81955
|
-
const file =
|
|
82062
|
+
const file = path46.join(root, IDEAS_DIR, `${learning.idea}.md`);
|
|
81956
82063
|
const raw = await readFile37(file, "utf8");
|
|
81957
82064
|
await writeFile23(file, setDefinitionFields(raw, { status: learning.to, result: learning.result }), "utf8");
|
|
81958
82065
|
}
|
|
81959
82066
|
}
|
|
81960
82067
|
function readDefinition2(root, slug) {
|
|
81961
82068
|
try {
|
|
81962
|
-
return readFileSync18(
|
|
82069
|
+
return readFileSync18(path46.join(root, "src", "creatives", slug, "_definition.md"), "utf8");
|
|
81963
82070
|
} catch {
|
|
81964
82071
|
return null;
|
|
81965
82072
|
}
|
|
@@ -81999,7 +82106,7 @@ var learnCommand = defineCommand158({
|
|
|
81999
82106
|
import { execFile as execFile3 } from "child_process";
|
|
82000
82107
|
import { mkdtemp as mkdtemp2, readFile as readFile38, rm as rm7, stat as stat7, writeFile as writeFile24 } from "fs/promises";
|
|
82001
82108
|
import { tmpdir as tmpdir3 } from "os";
|
|
82002
|
-
import
|
|
82109
|
+
import path47 from "path";
|
|
82003
82110
|
import { promisify as promisify3 } from "util";
|
|
82004
82111
|
import { defineCommand as defineCommand159 } from "citty";
|
|
82005
82112
|
var run2 = promisify3(execFile3);
|
|
@@ -82222,7 +82329,7 @@ async function scaffoldIdea(root, idea, args8, slug, temperature) {
|
|
|
82222
82329
|
],
|
|
82223
82330
|
signal
|
|
82224
82331
|
);
|
|
82225
|
-
const dir =
|
|
82332
|
+
const dir = path47.join(root, "src", "creatives", slug);
|
|
82226
82333
|
const fresh = !await stat7(dir).catch(() => null);
|
|
82227
82334
|
const reference = args8.reference ? { adId: args8.reference, platform: asPlatform(args8.platform), why: "chosen by hand", tried: 0 } : args8.fromIdea ? { code: "FROM_IDEA", message: "Asked to start from the idea." } : await pickReference(
|
|
82228
82335
|
root,
|
|
@@ -82242,8 +82349,8 @@ async function scaffoldIdea(root, idea, args8, slug, temperature) {
|
|
|
82242
82349
|
return { scaffold, reference };
|
|
82243
82350
|
}
|
|
82244
82351
|
async function scaffoldFromIdea(idea, slug, viewerFlags) {
|
|
82245
|
-
const dir = await mkdtemp2(
|
|
82246
|
-
const specPath =
|
|
82352
|
+
const dir = await mkdtemp2(path47.join(tmpdir3(), "idea-spec-"));
|
|
82353
|
+
const specPath = path47.join(dir, "prompt.json");
|
|
82247
82354
|
await writeFile24(specPath, JSON.stringify(ideaSpec(idea, idea.who.replace(/[-_]/g, " ")), null, 2), "utf8");
|
|
82248
82355
|
try {
|
|
82249
82356
|
return await baker([
|
|
@@ -82262,18 +82369,18 @@ async function scaffoldFromIdea(idea, slug, viewerFlags) {
|
|
|
82262
82369
|
}
|
|
82263
82370
|
}
|
|
82264
82371
|
async function recordIdea(root, slug, idea, evidence) {
|
|
82265
|
-
const dir =
|
|
82266
|
-
const definitionPath =
|
|
82372
|
+
const dir = path47.join(root, "src", "creatives", slug);
|
|
82373
|
+
const definitionPath = path47.join(dir, "_definition.md");
|
|
82267
82374
|
const definition = await readFile38(definitionPath, "utf8").catch(() => null);
|
|
82268
82375
|
if (definition !== null) {
|
|
82269
82376
|
await writeFile24(definitionPath, setDefinitionFields(definition, { ...definitionFieldsOf(idea, evidence) }), "utf8");
|
|
82270
82377
|
}
|
|
82271
|
-
const promptPath =
|
|
82378
|
+
const promptPath = path47.join(dir, "prompt.json");
|
|
82272
82379
|
const prompt = isVideoIdea(idea) ? null : await readFile38(promptPath, "utf8").catch(() => null);
|
|
82273
82380
|
if (prompt !== null) await writeFile24(promptPath, setSpecMessage(prompt, idea.message), "utf8").catch(() => void 0);
|
|
82274
82381
|
const unsourcedCopy = prompt === null ? [] : await draftedClaims(root, prompt);
|
|
82275
82382
|
if (idea.status === "idea") {
|
|
82276
|
-
const ideaPath =
|
|
82383
|
+
const ideaPath = path47.join(root, IDEAS_DIR, `${idea.id}.md`);
|
|
82277
82384
|
await writeFile24(ideaPath, setDefinitionFields(await readFile38(ideaPath, "utf8"), { status: "built" }), "utf8");
|
|
82278
82385
|
}
|
|
82279
82386
|
await baker(["canvas", "sync-definition", dir]);
|
|
@@ -82350,7 +82457,7 @@ var makeCommand = defineCommand159({
|
|
|
82350
82457
|
const opts = makeArgsOf(args8);
|
|
82351
82458
|
const { idea, check } = await loadIdea(root, String(args8.idea));
|
|
82352
82459
|
const slug = opts.slug ?? idea.id;
|
|
82353
|
-
const written = await readFile38(
|
|
82460
|
+
const written = await readFile38(path47.join(root, "src", "creatives", slug, "prompt.json"), "utf8").then(
|
|
82354
82461
|
(text3) => {
|
|
82355
82462
|
try {
|
|
82356
82463
|
return JSON.parse(text3);
|
|
@@ -82374,7 +82481,7 @@ var makeCommand = defineCommand159({
|
|
|
82374
82481
|
reference,
|
|
82375
82482
|
...fromIdea ? { fromIdea } : {},
|
|
82376
82483
|
viewer: opts.adset ? { adset: opts.adset } : { temperature },
|
|
82377
|
-
canvasPath:
|
|
82484
|
+
canvasPath: path47.relative(root, String(scaffold.canvas_path ?? path47.join(dir, `${slug}.canvas.json`))),
|
|
82378
82485
|
scaffoldHints: Array.isArray(scaffold.hints) ? scaffold.hints : [],
|
|
82379
82486
|
unsourcedCopy
|
|
82380
82487
|
})
|
|
@@ -82830,11 +82937,15 @@ var publishCommand = defineCommand160({
|
|
|
82830
82937
|
// src/commands/creatives/select.ts
|
|
82831
82938
|
import { defineCommand as defineCommand161 } from "citty";
|
|
82832
82939
|
var DESCRIPTION12 = `Choose the version of a creative to keep, and optionally which of its options, only when the user says to keep this version in this chat. The creative shows that version as the chosen one, and the choice counts as the user's approval. A version you render after it replaces it when the chat is published (the user saw that one last). It does not save the image to their library (that is baker creatives publish) and puts nothing into an ad.
|
|
82833
|
-
Start here: baker creatives select --slug spring-offer
|
|
82940
|
+
Start here: baker creatives select --slug spring-offer
|
|
82834
82941
|
Only some options of a version that made several: --options "ugc,2" (labels or numbers). Naming options again replaces the earlier pick.`;
|
|
82835
82942
|
var ARGS14 = {
|
|
82836
82943
|
slug: { type: "string", description: "The creative: its folder name under src/creatives/.", required: true },
|
|
82837
|
-
run: {
|
|
82944
|
+
run: {
|
|
82945
|
+
type: "string",
|
|
82946
|
+
description: "The version to keep: its canvas run id (r_\u2026) Left out, the version the creative shows now (its last render).",
|
|
82947
|
+
required: false
|
|
82948
|
+
},
|
|
82838
82949
|
options: {
|
|
82839
82950
|
type: "string",
|
|
82840
82951
|
description: 'Keep only these options of the version, comma-separated: labels ("ugc"), numbers ("2") or slots. Left out, the whole version.',
|
|
@@ -82853,7 +82964,9 @@ var selectCommand = defineCommand161({
|
|
|
82853
82964
|
const options = typeof args8.options === "string" ? args8.options.split(",").map((option) => option.trim()).filter((option) => option.length > 0) : [];
|
|
82854
82965
|
const parsed = creativesSelectRequestSchema.safeParse({
|
|
82855
82966
|
slug: args8.slug,
|
|
82856
|
-
runId: args8.run
|
|
82967
|
+
runId: await versionOf(String(args8.slug), args8.run).then(
|
|
82968
|
+
(run3) => run3 ?? fail7("VALIDATION_ERROR", "--run: this creative has no rendered version here; name one (r_\u2026).")
|
|
82969
|
+
),
|
|
82857
82970
|
...options.length > 0 ? { options } : {}
|
|
82858
82971
|
});
|
|
82859
82972
|
if (!parsed.success) {
|
|
@@ -84122,11 +84235,11 @@ import { defineCommand as defineCommand164 } from "citty";
|
|
|
84122
84235
|
|
|
84123
84236
|
// src/commands/experiment/composition.ts
|
|
84124
84237
|
import { readdir as readdir19, readFile as readFile42 } from "fs/promises";
|
|
84125
|
-
import
|
|
84238
|
+
import path49 from "path";
|
|
84126
84239
|
|
|
84127
84240
|
// src/commands/landing/import-graph.ts
|
|
84128
84241
|
import { readdir as readdir18, readFile as readFile41, stat as stat8 } from "fs/promises";
|
|
84129
|
-
import
|
|
84242
|
+
import path48 from "path";
|
|
84130
84243
|
var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
|
|
84131
84244
|
var RESOLVE_CANDIDATES = [
|
|
84132
84245
|
"",
|
|
@@ -84159,7 +84272,7 @@ async function walkFiles(dir) {
|
|
|
84159
84272
|
}
|
|
84160
84273
|
const out = [];
|
|
84161
84274
|
for (const entry of entries) {
|
|
84162
|
-
const full =
|
|
84275
|
+
const full = path48.join(dir, entry.name);
|
|
84163
84276
|
if (entry.isDirectory()) {
|
|
84164
84277
|
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
84165
84278
|
out.push(...await walkFiles(full));
|
|
@@ -84173,8 +84286,8 @@ async function resolveSpecifier(specifier, fromFile, root) {
|
|
|
84173
84286
|
const bare = specifier.split("?")[0] ?? "";
|
|
84174
84287
|
if (bare.includes("*")) return null;
|
|
84175
84288
|
let base;
|
|
84176
|
-
if (bare.startsWith("/")) base =
|
|
84177
|
-
else if (bare.startsWith(".")) base =
|
|
84289
|
+
if (bare.startsWith("/")) base = path48.join(root, bare.slice(1));
|
|
84290
|
+
else if (bare.startsWith(".")) base = path48.resolve(path48.dirname(fromFile), bare);
|
|
84178
84291
|
else return null;
|
|
84179
84292
|
for (const suffix of RESOLVE_CANDIDATES) {
|
|
84180
84293
|
const candidate = base + suffix;
|
|
@@ -84196,7 +84309,7 @@ async function importedFiles(text3, file, root) {
|
|
|
84196
84309
|
}
|
|
84197
84310
|
async function landingGraphFiles(root, slug) {
|
|
84198
84311
|
const seen = /* @__PURE__ */ new Set();
|
|
84199
|
-
const queue = await walkFiles(
|
|
84312
|
+
const queue = await walkFiles(path48.join(root, "src/pages", slug));
|
|
84200
84313
|
while (queue.length > 0) {
|
|
84201
84314
|
const file = queue.pop();
|
|
84202
84315
|
if (file === void 0 || seen.has(file)) continue;
|
|
@@ -84211,7 +84324,7 @@ async function landingGraphFiles(root, slug) {
|
|
|
84211
84324
|
if (!seen.has(target2)) queue.push(target2);
|
|
84212
84325
|
}
|
|
84213
84326
|
}
|
|
84214
|
-
return new Set([...seen].map((abs) =>
|
|
84327
|
+
return new Set([...seen].map((abs) => path48.relative(root, abs).split(path48.sep).join("/")));
|
|
84215
84328
|
}
|
|
84216
84329
|
|
|
84217
84330
|
// src/commands/experiment/composition.ts
|
|
@@ -84256,7 +84369,7 @@ function formsOnlyIn(these, those) {
|
|
|
84256
84369
|
}
|
|
84257
84370
|
async function knownFlows(root) {
|
|
84258
84371
|
try {
|
|
84259
|
-
const entries = await readdir19(
|
|
84372
|
+
const entries = await readdir19(path49.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
|
|
84260
84373
|
return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
|
|
84261
84374
|
} catch {
|
|
84262
84375
|
return /* @__PURE__ */ new Set();
|
|
@@ -84267,7 +84380,7 @@ async function readForms(root, slug) {
|
|
|
84267
84380
|
const [files, flows] = await Promise.all([landingGraphFiles(root, slug), knownFlows(root)]);
|
|
84268
84381
|
if (flows.size === 0) return [];
|
|
84269
84382
|
const texts = await Promise.all(
|
|
84270
|
-
[...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile42(
|
|
84383
|
+
[...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile42(path49.join(root, file), "utf8"))
|
|
84271
84384
|
);
|
|
84272
84385
|
return formsReferenced(texts, flows);
|
|
84273
84386
|
} catch {
|
|
@@ -84278,7 +84391,7 @@ async function readForms(root, slug) {
|
|
|
84278
84391
|
// src/commands/experiment/fold.ts
|
|
84279
84392
|
import { statSync } from "fs";
|
|
84280
84393
|
import { cp as cp3, mkdir as mkdir15, readdir as readdir20, readFile as readFile43, rm as rm8, stat as stat9, writeFile as writeFile25 } from "fs/promises";
|
|
84281
|
-
import
|
|
84394
|
+
import path51 from "path";
|
|
84282
84395
|
|
|
84283
84396
|
// ../api/src/experiments/variants.ts
|
|
84284
84397
|
var VARIANT_SEPARATOR = "--";
|
|
@@ -84303,21 +84416,21 @@ function nextVariantNumber(page, existingSlugs, archived) {
|
|
|
84303
84416
|
}
|
|
84304
84417
|
|
|
84305
84418
|
// src/commands/landing/repoint.ts
|
|
84306
|
-
import
|
|
84419
|
+
import path50 from "path";
|
|
84307
84420
|
var QUOTED_RELATIVE = /(['"])(\.\.?\/[^'"]*)\1/g;
|
|
84308
84421
|
function isInside3(abs, dir) {
|
|
84309
|
-
return abs === dir || abs.startsWith(dir +
|
|
84422
|
+
return abs === dir || abs.startsWith(dir + path50.sep);
|
|
84310
84423
|
}
|
|
84311
84424
|
function toSpecifier(from, to) {
|
|
84312
|
-
const rel =
|
|
84425
|
+
const rel = path50.relative(from, to).split(path50.sep).join("/");
|
|
84313
84426
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
84314
84427
|
}
|
|
84315
84428
|
function repointSpecifier(spec, opts) {
|
|
84316
84429
|
if (!spec.startsWith(".")) return spec;
|
|
84317
|
-
const abs =
|
|
84430
|
+
const abs = path50.resolve(opts.fromDir, spec);
|
|
84318
84431
|
if (opts.forkedTargets?.has(abs)) {
|
|
84319
|
-
const withinControl =
|
|
84320
|
-
return toSpecifier(opts.toDir,
|
|
84432
|
+
const withinControl = path50.relative(opts.controlDir, abs);
|
|
84433
|
+
return toSpecifier(opts.toDir, path50.resolve(opts.variantDir, withinControl));
|
|
84321
84434
|
}
|
|
84322
84435
|
if (!isInside3(abs, opts.controlDir)) return spec;
|
|
84323
84436
|
return toSpecifier(opts.toDir, abs);
|
|
@@ -84329,9 +84442,9 @@ function repointFile(text3, opts) {
|
|
|
84329
84442
|
}
|
|
84330
84443
|
function repointMoved(text3, opts) {
|
|
84331
84444
|
return text3.replace(QUOTED_RELATIVE, (_match, quote, spec) => {
|
|
84332
|
-
const abs =
|
|
84333
|
-
const within =
|
|
84334
|
-
const target2 = within.startsWith("..") ||
|
|
84445
|
+
const abs = path50.resolve(opts.fromDir, spec);
|
|
84446
|
+
const within = path50.relative(opts.movedFrom, abs);
|
|
84447
|
+
const target2 = within.startsWith("..") || path50.isAbsolute(within) ? abs : path50.resolve(opts.movedTo, within);
|
|
84335
84448
|
return `${quote}${toSpecifier(opts.toDir, target2)}${quote}`;
|
|
84336
84449
|
});
|
|
84337
84450
|
}
|
|
@@ -84340,7 +84453,7 @@ function repointMoved(text3, opts) {
|
|
|
84340
84453
|
var ARCHIVE_ROOT = "src/_variants";
|
|
84341
84454
|
var QUOTED_RELATIVE2 = /(['"])(\.\.?\/[^'"]*)\1/g;
|
|
84342
84455
|
function posix2(p) {
|
|
84343
|
-
return p.split(
|
|
84456
|
+
return p.split(path51.sep).join("/");
|
|
84344
84457
|
}
|
|
84345
84458
|
async function isDir(p) {
|
|
84346
84459
|
try {
|
|
@@ -84359,39 +84472,39 @@ async function filesUnder(dir, prefix = "") {
|
|
|
84359
84472
|
const out = [];
|
|
84360
84473
|
for (const entry of entries) {
|
|
84361
84474
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
84362
|
-
if (entry.isDirectory()) out.push(...await filesUnder(
|
|
84475
|
+
if (entry.isDirectory()) out.push(...await filesUnder(path51.join(dir, entry.name), rel));
|
|
84363
84476
|
else out.push(rel);
|
|
84364
84477
|
}
|
|
84365
84478
|
return out.sort();
|
|
84366
84479
|
}
|
|
84367
84480
|
var TEXT_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte|md|json|css)$/;
|
|
84368
84481
|
function archiveRelPath(abs, base) {
|
|
84369
|
-
if (!abs.startsWith(base +
|
|
84370
|
-
return posix2(
|
|
84482
|
+
if (!abs.startsWith(base + path51.sep)) return null;
|
|
84483
|
+
return posix2(path51.relative(base, abs));
|
|
84371
84484
|
}
|
|
84372
84485
|
async function archiveArm(opts) {
|
|
84373
84486
|
const { root, armDir, pageDir, archiveDir, armSlug } = opts;
|
|
84374
84487
|
const targets = await archiveContents({ root, armDir, pageDir, armSlug });
|
|
84375
|
-
const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs,
|
|
84488
|
+
const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path51.join(archiveDir, rel)]));
|
|
84376
84489
|
const written = [];
|
|
84377
84490
|
for (const [rel, abs] of [...targets].sort()) {
|
|
84378
|
-
const dest =
|
|
84379
|
-
await mkdir15(
|
|
84491
|
+
const dest = path51.join(archiveDir, rel);
|
|
84492
|
+
await mkdir15(path51.dirname(dest), { recursive: true });
|
|
84380
84493
|
if (!TEXT_EXT.test(rel)) {
|
|
84381
84494
|
await cp3(abs, dest);
|
|
84382
84495
|
} else {
|
|
84383
84496
|
const text3 = await readFile43(abs, "utf8");
|
|
84384
84497
|
await writeFile25(dest, repointIntoArchive(text3, abs, dest, archivedBySource), "utf8");
|
|
84385
84498
|
}
|
|
84386
|
-
written.push(posix2(
|
|
84499
|
+
written.push(posix2(path51.relative(root, dest)));
|
|
84387
84500
|
}
|
|
84388
84501
|
return written;
|
|
84389
84502
|
}
|
|
84390
84503
|
async function archiveContents(opts) {
|
|
84391
84504
|
const { root, armDir, pageDir, armSlug } = opts;
|
|
84392
84505
|
const graph = await landingGraphFiles(root, armSlug);
|
|
84393
|
-
const reachable = new Set([...graph].map((rel) =>
|
|
84394
|
-
for (const rel of await filesUnder(armDir)) reachable.add(
|
|
84506
|
+
const reachable = new Set([...graph].map((rel) => path51.resolve(root, rel)));
|
|
84507
|
+
for (const rel of await filesUnder(armDir)) reachable.add(path51.join(armDir, rel));
|
|
84395
84508
|
const sorted = [...reachable].sort();
|
|
84396
84509
|
const targets = /* @__PURE__ */ new Map();
|
|
84397
84510
|
for (const base of [pageDir, armDir]) {
|
|
@@ -84404,14 +84517,14 @@ async function archiveContents(opts) {
|
|
|
84404
84517
|
return targets;
|
|
84405
84518
|
}
|
|
84406
84519
|
function repointIntoArchive(text3, sourceAbs, destAbs, archivedBySource) {
|
|
84407
|
-
const fromDir =
|
|
84408
|
-
const toDir =
|
|
84520
|
+
const fromDir = path51.dirname(sourceAbs);
|
|
84521
|
+
const toDir = path51.dirname(destAbs);
|
|
84409
84522
|
return text3.replace(QUOTED_RELATIVE2, (match, quote, spec, offset) => {
|
|
84410
84523
|
const [specPath, suffix] = splitSuffix(spec);
|
|
84411
|
-
const target2 =
|
|
84524
|
+
const target2 = path51.resolve(fromDir, specPath);
|
|
84412
84525
|
const resolved = resolveInArchive(target2, archivedBySource) ?? resolveOnDisk(target2, isImportPosition(text3, offset));
|
|
84413
84526
|
if (resolved === null) return match;
|
|
84414
|
-
const rel = posix2(
|
|
84527
|
+
const rel = posix2(path51.relative(toDir, resolved));
|
|
84415
84528
|
return `${quote}${rel.startsWith(".") ? rel : `./${rel}`}${suffix}${quote}`;
|
|
84416
84529
|
});
|
|
84417
84530
|
}
|
|
@@ -84445,9 +84558,9 @@ async function promoteVariantFiles(opts) {
|
|
|
84445
84558
|
const written = [];
|
|
84446
84559
|
for (const rel of await filesUnder(variantDir)) {
|
|
84447
84560
|
if (rel === "_definition.md") continue;
|
|
84448
|
-
const from =
|
|
84449
|
-
const to =
|
|
84450
|
-
await mkdir15(
|
|
84561
|
+
const from = path51.join(variantDir, rel);
|
|
84562
|
+
const to = path51.join(pageDir, rel);
|
|
84563
|
+
await mkdir15(path51.dirname(to), { recursive: true });
|
|
84451
84564
|
if (!TEXT_EXT.test(rel)) {
|
|
84452
84565
|
await cp3(from, to);
|
|
84453
84566
|
} else {
|
|
@@ -84455,15 +84568,15 @@ async function promoteVariantFiles(opts) {
|
|
|
84455
84568
|
await writeFile25(
|
|
84456
84569
|
to,
|
|
84457
84570
|
repointMoved(text3, {
|
|
84458
|
-
fromDir:
|
|
84459
|
-
toDir:
|
|
84571
|
+
fromDir: path51.dirname(from),
|
|
84572
|
+
toDir: path51.dirname(to),
|
|
84460
84573
|
movedFrom: variantDir,
|
|
84461
84574
|
movedTo: pageDir
|
|
84462
84575
|
}),
|
|
84463
84576
|
"utf8"
|
|
84464
84577
|
);
|
|
84465
84578
|
}
|
|
84466
|
-
written.push(posix2(
|
|
84579
|
+
written.push(posix2(path51.relative(root, to)));
|
|
84467
84580
|
}
|
|
84468
84581
|
return written;
|
|
84469
84582
|
}
|
|
@@ -84487,8 +84600,8 @@ function archiveRecord(target2, variantNumber) {
|
|
|
84487
84600
|
`;
|
|
84488
84601
|
}
|
|
84489
84602
|
async function foldExperiment(root, target2) {
|
|
84490
|
-
const pageDir =
|
|
84491
|
-
const variantDir =
|
|
84603
|
+
const pageDir = path51.resolve(root, "src/pages", target2.landingSlug);
|
|
84604
|
+
const variantDir = path51.resolve(root, "src/pages", target2.variantSlug);
|
|
84492
84605
|
const variantNumber = variantNumberOf(target2.variantSlug);
|
|
84493
84606
|
if (variantNumber === null) {
|
|
84494
84607
|
return {
|
|
@@ -84502,7 +84615,7 @@ async function foldExperiment(root, target2) {
|
|
|
84502
84615
|
return { error: `src/pages/${target2.variantSlug}/ is already gone \u2014 this test looks folded in already` };
|
|
84503
84616
|
}
|
|
84504
84617
|
const archiveKey = target2.landingInternalId ?? target2.landingSlug;
|
|
84505
|
-
const archiveDir =
|
|
84618
|
+
const archiveDir = path51.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
|
|
84506
84619
|
await rm8(archiveDir, { recursive: true, force: true });
|
|
84507
84620
|
await mkdir15(archiveDir, { recursive: true });
|
|
84508
84621
|
const written = await archiveArm({
|
|
@@ -84512,8 +84625,8 @@ async function foldExperiment(root, target2) {
|
|
|
84512
84625
|
archiveDir,
|
|
84513
84626
|
armSlug: target2.survivor === "variant" ? target2.landingSlug : target2.variantSlug
|
|
84514
84627
|
});
|
|
84515
|
-
await writeFile25(
|
|
84516
|
-
written.push(posix2(
|
|
84628
|
+
await writeFile25(path51.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
|
|
84629
|
+
written.push(posix2(path51.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
|
|
84517
84630
|
if (target2.survivor === "variant") {
|
|
84518
84631
|
written.push(...await promoteVariantFiles({ root, pageDir, variantDir }));
|
|
84519
84632
|
}
|
|
@@ -84521,7 +84634,7 @@ async function foldExperiment(root, target2) {
|
|
|
84521
84634
|
return {
|
|
84522
84635
|
experimentId: target2.experimentId,
|
|
84523
84636
|
page: target2.landingSlug,
|
|
84524
|
-
archivedTo: posix2(
|
|
84637
|
+
archivedTo: posix2(path51.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
|
|
84525
84638
|
written,
|
|
84526
84639
|
removed: [`src/pages/${target2.variantSlug}`]
|
|
84527
84640
|
};
|
|
@@ -85294,10 +85407,10 @@ function parseEvidence(raw, rawArgs) {
|
|
|
85294
85407
|
|
|
85295
85408
|
// src/commands/experiment/identity.ts
|
|
85296
85409
|
import { readFile as readFile44 } from "fs/promises";
|
|
85297
|
-
import
|
|
85410
|
+
import path52 from "path";
|
|
85298
85411
|
async function readPageInternalId(root, slug) {
|
|
85299
85412
|
try {
|
|
85300
|
-
const text3 = await readFile44(
|
|
85413
|
+
const text3 = await readFile44(path52.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
|
|
85301
85414
|
return /^internalId:\s*"?([^"\s]+)"?\s*$/m.exec(text3)?.[1];
|
|
85302
85415
|
} catch {
|
|
85303
85416
|
return void 0;
|
|
@@ -85306,7 +85419,7 @@ async function readPageInternalId(root, slug) {
|
|
|
85306
85419
|
|
|
85307
85420
|
// src/commands/experiment/measurement.ts
|
|
85308
85421
|
import { readFile as readFile45 } from "fs/promises";
|
|
85309
|
-
import
|
|
85422
|
+
import path53 from "path";
|
|
85310
85423
|
function eventDeclarationsIn(source) {
|
|
85311
85424
|
const found = [];
|
|
85312
85425
|
const pattern = /\b(data-baker-(?:view|event))\s*=\s*["']([^"']+)["']/g;
|
|
@@ -85366,7 +85479,7 @@ function sectionsOf(files, slug) {
|
|
|
85366
85479
|
return files.filter((file) => file.startsWith(prefix) && !file.slice(prefix.length).startsWith("index."));
|
|
85367
85480
|
}
|
|
85368
85481
|
async function declarationsOf(root, files) {
|
|
85369
|
-
const sources = await Promise.all(files.map((file) => readFile45(
|
|
85482
|
+
const sources = await Promise.all(files.map((file) => readFile45(path53.join(root, file), "utf8").catch(() => "")));
|
|
85370
85483
|
return sources.flatMap(eventDeclarationsIn);
|
|
85371
85484
|
}
|
|
85372
85485
|
|
|
@@ -86788,10 +86901,10 @@ function parseValueExpression(raw) {
|
|
|
86788
86901
|
return parts.map(parsePart);
|
|
86789
86902
|
}
|
|
86790
86903
|
function trackingFieldIds() {
|
|
86791
|
-
const
|
|
86792
|
-
if (!existsSync9(
|
|
86904
|
+
const path69 = join4(flowsDir(), "..", "tracking.ts");
|
|
86905
|
+
if (!existsSync9(path69)) return null;
|
|
86793
86906
|
try {
|
|
86794
|
-
const source = readFileSync19(
|
|
86907
|
+
const source = readFileSync19(path69, "utf-8");
|
|
86795
86908
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
86796
86909
|
if (!block2) return null;
|
|
86797
86910
|
const ids2 = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -87373,13 +87486,13 @@ function specsFromFile(parsed) {
|
|
|
87373
87486
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
87374
87487
|
});
|
|
87375
87488
|
}
|
|
87376
|
-
function readSpecFile(
|
|
87489
|
+
function readSpecFile(path69) {
|
|
87377
87490
|
let raw;
|
|
87378
87491
|
try {
|
|
87379
|
-
raw =
|
|
87492
|
+
raw = path69 === "-" ? readFileSync20(0, "utf-8") : readFileSync20(path69, "utf-8");
|
|
87380
87493
|
} catch (error) {
|
|
87381
87494
|
refuse3(
|
|
87382
|
-
`Could not read ${
|
|
87495
|
+
`Could not read ${path69 === "-" ? "the mapping from stdin" : `"${path69}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
87383
87496
|
);
|
|
87384
87497
|
}
|
|
87385
87498
|
let parsed;
|
|
@@ -87387,7 +87500,7 @@ function readSpecFile(path68) {
|
|
|
87387
87500
|
parsed = JSON.parse(raw);
|
|
87388
87501
|
} catch (error) {
|
|
87389
87502
|
refuse3(
|
|
87390
|
-
`${
|
|
87503
|
+
`${path69 === "-" ? "stdin" : `"${path69}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
87391
87504
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
87392
87505
|
);
|
|
87393
87506
|
}
|
|
@@ -87686,21 +87799,21 @@ var ARRAY_FIELDS = [
|
|
|
87686
87799
|
"tagIds"
|
|
87687
87800
|
];
|
|
87688
87801
|
var ARRAY_OWNERS = ["", "body"];
|
|
87689
|
-
function dropUnsetOptionals(sideEffect,
|
|
87802
|
+
function dropUnsetOptionals(sideEffect, path69) {
|
|
87690
87803
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
87691
87804
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
87692
87805
|
delete sideEffect[key];
|
|
87693
|
-
return [{ path:
|
|
87806
|
+
return [{ path: path69, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
87694
87807
|
});
|
|
87695
87808
|
}
|
|
87696
|
-
function fillNulledArrays(target2, prefix,
|
|
87809
|
+
function fillNulledArrays(target2, prefix, path69) {
|
|
87697
87810
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
87698
87811
|
if (!(key in target2) || target2[key] !== null) return [];
|
|
87699
87812
|
target2[key] = [];
|
|
87700
|
-
return [{ path:
|
|
87813
|
+
return [{ path: path69, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
87701
87814
|
});
|
|
87702
87815
|
}
|
|
87703
|
-
function tidyEmailRecipients(sideEffect,
|
|
87816
|
+
function tidyEmailRecipients(sideEffect, path69) {
|
|
87704
87817
|
if (sideEffect.type !== "email") return [];
|
|
87705
87818
|
const config = sideEffect.encryptedConfig;
|
|
87706
87819
|
if (!config || typeof config !== "object" || Array.isArray(config)) return [];
|
|
@@ -87711,7 +87824,7 @@ function tidyEmailRecipients(sideEffect, path68) {
|
|
|
87711
87824
|
const tidied = to.join(", ");
|
|
87712
87825
|
if (tidied === raw) return [];
|
|
87713
87826
|
config.email = tidied;
|
|
87714
|
-
return [{ path:
|
|
87827
|
+
return [{ path: path69, change: "tidied the recipient list's spacing and separators" }];
|
|
87715
87828
|
}
|
|
87716
87829
|
function sideEffectsOf(node) {
|
|
87717
87830
|
if (!Array.isArray(node.sideEffects)) return [];
|
|
@@ -87720,13 +87833,13 @@ function sideEffectsOf(node) {
|
|
|
87720
87833
|
);
|
|
87721
87834
|
}
|
|
87722
87835
|
function normalizeSideEffect(sideEffect, where) {
|
|
87723
|
-
const
|
|
87836
|
+
const path69 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
87724
87837
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
87725
87838
|
const target2 = owner ? sideEffect[owner] : sideEffect;
|
|
87726
87839
|
if (!target2 || typeof target2 !== "object") return [];
|
|
87727
|
-
return fillNulledArrays(target2, owner ? `${owner}.` : "",
|
|
87840
|
+
return fillNulledArrays(target2, owner ? `${owner}.` : "", path69);
|
|
87728
87841
|
});
|
|
87729
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
87842
|
+
return [...dropUnsetOptionals(sideEffect, path69), ...arrays, ...tidyEmailRecipients(sideEffect, path69)];
|
|
87730
87843
|
}
|
|
87731
87844
|
function normalizeFlowTree(tree) {
|
|
87732
87845
|
const changes = [];
|
|
@@ -89232,10 +89345,10 @@ async function stageOps(ops) {
|
|
|
89232
89345
|
handleError5(err);
|
|
89233
89346
|
}
|
|
89234
89347
|
}
|
|
89235
|
-
async function draftAction2(
|
|
89348
|
+
async function draftAction2(path69, body, chat) {
|
|
89236
89349
|
const chatId = resolveChatId(chat);
|
|
89237
89350
|
try {
|
|
89238
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
89351
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path69, { chatId, ...body }));
|
|
89239
89352
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
89240
89353
|
return data;
|
|
89241
89354
|
} catch (err) {
|
|
@@ -91781,9 +91894,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
91781
91894
|
}
|
|
91782
91895
|
return readFile46(pathOrUrl);
|
|
91783
91896
|
}
|
|
91784
|
-
async function isDirectory(
|
|
91897
|
+
async function isDirectory(path69) {
|
|
91785
91898
|
try {
|
|
91786
|
-
const s = await stat10(
|
|
91899
|
+
const s = await stat10(path69);
|
|
91787
91900
|
return s.isDirectory();
|
|
91788
91901
|
} catch {
|
|
91789
91902
|
return false;
|
|
@@ -92211,13 +92324,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
92211
92324
|
}
|
|
92212
92325
|
function disambiguate(paths) {
|
|
92213
92326
|
const taken = /* @__PURE__ */ new Set();
|
|
92214
|
-
return paths.map((
|
|
92215
|
-
if (!taken.has(
|
|
92216
|
-
taken.add(
|
|
92217
|
-
return
|
|
92327
|
+
return paths.map((path69) => {
|
|
92328
|
+
if (!taken.has(path69)) {
|
|
92329
|
+
taken.add(path69);
|
|
92330
|
+
return path69;
|
|
92218
92331
|
}
|
|
92219
|
-
const ext = extname4(
|
|
92220
|
-
const stem =
|
|
92332
|
+
const ext = extname4(path69);
|
|
92333
|
+
const stem = path69.slice(0, path69.length - ext.length);
|
|
92221
92334
|
let n = 2;
|
|
92222
92335
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
92223
92336
|
const unique2 = `${stem}-${n}${ext}`;
|
|
@@ -92343,10 +92456,10 @@ async function runDownloads(plan) {
|
|
|
92343
92456
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
92344
92457
|
const downloaded = [];
|
|
92345
92458
|
for (const [index, item] of fetched.entries()) {
|
|
92346
|
-
const
|
|
92459
|
+
const path69 = paths[index] ?? item.path;
|
|
92347
92460
|
try {
|
|
92348
|
-
await atomicWrite(
|
|
92349
|
-
downloaded.push({ input: item.input, output:
|
|
92461
|
+
await atomicWrite(path69, item.buffer);
|
|
92462
|
+
downloaded.push({ input: item.input, output: path69, bytes: item.buffer.length, contentType: item.contentType });
|
|
92350
92463
|
} catch (err) {
|
|
92351
92464
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
92352
92465
|
}
|
|
@@ -95242,7 +95355,7 @@ import { defineCommand as defineCommand226 } from "citty";
|
|
|
95242
95355
|
|
|
95243
95356
|
// src/commands/landing/critique.ts
|
|
95244
95357
|
import { readdir as readdir22, readFile as readFile48, stat as stat12 } from "fs/promises";
|
|
95245
|
-
import
|
|
95358
|
+
import path56 from "path";
|
|
95246
95359
|
import { defineCommand as defineCommand213 } from "citty";
|
|
95247
95360
|
|
|
95248
95361
|
// src/engine/landing/lib/constants.ts
|
|
@@ -96434,13 +96547,13 @@ function describeCounts(findings) {
|
|
|
96434
96547
|
|
|
96435
96548
|
// src/commands/landing/snapshot.ts
|
|
96436
96549
|
import { mkdir as mkdir16, rename as rename3, writeFile as writeFile27 } from "fs/promises";
|
|
96437
|
-
import
|
|
96550
|
+
import path54 from "path";
|
|
96438
96551
|
var CRITIC_VERSION = "4";
|
|
96439
96552
|
function critiqueCacheDir(projectRoot) {
|
|
96440
|
-
return
|
|
96553
|
+
return path54.join(projectRoot, ".cache", "landing-critique");
|
|
96441
96554
|
}
|
|
96442
96555
|
function snapshotPath(projectRoot, slug) {
|
|
96443
|
-
return
|
|
96556
|
+
return path54.join(critiqueCacheDir(projectRoot), `${slug}.json`);
|
|
96444
96557
|
}
|
|
96445
96558
|
async function writeCritiqueSnapshot(projectRoot, snapshot) {
|
|
96446
96559
|
await mkdir16(critiqueCacheDir(projectRoot), { recursive: true });
|
|
@@ -96453,7 +96566,7 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
|
|
|
96453
96566
|
|
|
96454
96567
|
// src/commands/landing/source-version.ts
|
|
96455
96568
|
import { readdir as readdir21, readFile as readFile47, stat as stat11 } from "fs/promises";
|
|
96456
|
-
import
|
|
96569
|
+
import path55 from "path";
|
|
96457
96570
|
var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
|
|
96458
96571
|
async function landingSourceRelPaths(root, slug) {
|
|
96459
96572
|
const files = await landingGraphFiles(root, slug);
|
|
@@ -96462,7 +96575,7 @@ async function landingSourceRelPaths(root, slug) {
|
|
|
96462
96575
|
async function readLandingSources(root, slug) {
|
|
96463
96576
|
const rel = await landingSourceRelPaths(root, slug);
|
|
96464
96577
|
const out = [];
|
|
96465
|
-
for (const r of rel) out.push({ path: r, text: await readFile47(
|
|
96578
|
+
for (const r of rel) out.push({ path: r, text: await readFile47(path55.join(root, r), "utf8") });
|
|
96466
96579
|
return out;
|
|
96467
96580
|
}
|
|
96468
96581
|
async function computeLandingSourceSha(root, slug) {
|
|
@@ -96471,7 +96584,7 @@ async function computeLandingSourceSha(root, slug) {
|
|
|
96471
96584
|
for (const r of rel) {
|
|
96472
96585
|
let bytes;
|
|
96473
96586
|
try {
|
|
96474
|
-
bytes = await readFile47(
|
|
96587
|
+
bytes = await readFile47(path55.join(root, r));
|
|
96475
96588
|
} catch {
|
|
96476
96589
|
bytes = Buffer.alloc(0);
|
|
96477
96590
|
}
|
|
@@ -96481,16 +96594,16 @@ async function computeLandingSourceSha(root, slug) {
|
|
|
96481
96594
|
}
|
|
96482
96595
|
async function computeLegacyLandingSourceSha(landingDir) {
|
|
96483
96596
|
const rel = [];
|
|
96484
|
-
if (await isFile2(
|
|
96485
|
-
for (const abs of await walkAstro(
|
|
96486
|
-
rel.push(
|
|
96597
|
+
if (await isFile2(path55.join(landingDir, "index.astro"))) rel.push("index.astro");
|
|
96598
|
+
for (const abs of await walkAstro(path55.join(landingDir, "_components"))) {
|
|
96599
|
+
rel.push(path55.relative(landingDir, abs).split(path55.sep).join("/"));
|
|
96487
96600
|
}
|
|
96488
96601
|
rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
96489
96602
|
const parts = [];
|
|
96490
96603
|
for (const r of rel) {
|
|
96491
96604
|
let bytes;
|
|
96492
96605
|
try {
|
|
96493
|
-
bytes = await readFile47(
|
|
96606
|
+
bytes = await readFile47(path55.join(landingDir, r));
|
|
96494
96607
|
} catch {
|
|
96495
96608
|
bytes = Buffer.alloc(0);
|
|
96496
96609
|
}
|
|
@@ -96514,7 +96627,7 @@ async function walkAstro(dir) {
|
|
|
96514
96627
|
}
|
|
96515
96628
|
const out = [];
|
|
96516
96629
|
for (const entry of entries) {
|
|
96517
|
-
const abs =
|
|
96630
|
+
const abs = path55.join(dir, entry.name);
|
|
96518
96631
|
if (entry.isDirectory()) out.push(...await walkAstro(abs));
|
|
96519
96632
|
else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
|
|
96520
96633
|
}
|
|
@@ -96575,7 +96688,7 @@ var critiqueCommand2 = defineCommand213({
|
|
|
96575
96688
|
{ availableSlugs: await listLandingSlugs(projectRoot) }
|
|
96576
96689
|
);
|
|
96577
96690
|
}
|
|
96578
|
-
if (!await isDir2(
|
|
96691
|
+
if (!await isDir2(path56.resolve(projectRoot, "src", "pages", slug))) {
|
|
96579
96692
|
fail10("NOT_FOUND", `No landing at src/pages/${slug}/`, {
|
|
96580
96693
|
availableSlugs: await listLandingSlugs(projectRoot)
|
|
96581
96694
|
});
|
|
@@ -96618,7 +96731,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
|
|
|
96618
96731
|
const [sources, compositionSha, sourceSha] = await Promise.all([
|
|
96619
96732
|
readLandingSources(projectRoot, slug),
|
|
96620
96733
|
computeLandingSourceSha(projectRoot, slug),
|
|
96621
|
-
computeLegacyLandingSourceSha(
|
|
96734
|
+
computeLegacyLandingSourceSha(path56.resolve(projectRoot, "src", "pages", slug))
|
|
96622
96735
|
]);
|
|
96623
96736
|
const report = critiqueLanding({ slug, sources, brand, competitors });
|
|
96624
96737
|
let snapshotFailed = false;
|
|
@@ -96638,7 +96751,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
|
|
|
96638
96751
|
return { slug, report, snapshotFailed };
|
|
96639
96752
|
}
|
|
96640
96753
|
async function readCompetitorNames(projectRoot) {
|
|
96641
|
-
const dir =
|
|
96754
|
+
const dir = path56.join(projectRoot, "src", "content", "competitors");
|
|
96642
96755
|
let entries;
|
|
96643
96756
|
try {
|
|
96644
96757
|
entries = (await readdir22(dir)).filter((f) => f.endsWith(".md"));
|
|
@@ -96647,9 +96760,9 @@ async function readCompetitorNames(projectRoot) {
|
|
|
96647
96760
|
}
|
|
96648
96761
|
const names = [];
|
|
96649
96762
|
for (const entry of entries) {
|
|
96650
|
-
names.push(
|
|
96763
|
+
names.push(path56.basename(entry, ".md").replace(/[-_]+/g, " "));
|
|
96651
96764
|
try {
|
|
96652
|
-
const head = (await readFile48(
|
|
96765
|
+
const head = (await readFile48(path56.join(dir, entry), "utf8")).slice(0, 2e3);
|
|
96653
96766
|
const titled = /^\s*(?:title|name)\s*:\s*["']?([^"'\n]+)["']?\s*$/im.exec(head);
|
|
96654
96767
|
if (titled?.[1]) names.push(titled[1].trim());
|
|
96655
96768
|
} catch {
|
|
@@ -96659,7 +96772,7 @@ async function readCompetitorNames(projectRoot) {
|
|
|
96659
96772
|
}
|
|
96660
96773
|
async function listLandingSlugs(projectRoot) {
|
|
96661
96774
|
try {
|
|
96662
|
-
const entries = await readdir22(
|
|
96775
|
+
const entries = await readdir22(path56.join(projectRoot, "src", "pages"), { withFileTypes: true });
|
|
96663
96776
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
96664
96777
|
} catch {
|
|
96665
96778
|
return [];
|
|
@@ -96783,7 +96896,7 @@ function exportStatusHints(view) {
|
|
|
96783
96896
|
}
|
|
96784
96897
|
return ["Still being prepared. Carry on with other work and check again in a minute \u2014 never sleep-loop on it."];
|
|
96785
96898
|
}
|
|
96786
|
-
function parseProfileFlag(raw, readFile52 = (
|
|
96899
|
+
function parseProfileFlag(raw, readFile52 = (path69) => readFileSync25(path69, "utf8")) {
|
|
96787
96900
|
let parsed;
|
|
96788
96901
|
try {
|
|
96789
96902
|
parsed = JSON.parse(raw.startsWith("@") ? readFile52(raw.slice(1)) : raw);
|
|
@@ -96958,7 +97071,7 @@ var addCommand = defineCommand215({
|
|
|
96958
97071
|
|
|
96959
97072
|
// src/commands/landing/inspiration/code.ts
|
|
96960
97073
|
import { mkdir as mkdir17, writeFile as writeFile28 } from "fs/promises";
|
|
96961
|
-
import
|
|
97074
|
+
import path57 from "path";
|
|
96962
97075
|
import { defineCommand as defineCommand216 } from "citty";
|
|
96963
97076
|
registerSchema({
|
|
96964
97077
|
command: "landing.inspiration.code",
|
|
@@ -96981,9 +97094,9 @@ var codeCommand = defineCommand216({
|
|
|
96981
97094
|
try {
|
|
96982
97095
|
const id = args8.id;
|
|
96983
97096
|
const data = await apiGet("/api/landing-inspiration/section-code", { id });
|
|
96984
|
-
const dir =
|
|
97097
|
+
const dir = path57.join(process.cwd(), ".baker", "inspiration", id);
|
|
96985
97098
|
await mkdir17(dir, { recursive: true });
|
|
96986
|
-
const file =
|
|
97099
|
+
const file = path57.join(dir, "section.html");
|
|
96987
97100
|
await writeFile28(file, data.html);
|
|
96988
97101
|
const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
96989
97102
|
const fidelity = fidelityHint(data.fidelity);
|
|
@@ -96993,7 +97106,7 @@ var codeCommand = defineCommand216({
|
|
|
96993
97106
|
ok: true,
|
|
96994
97107
|
data: {
|
|
96995
97108
|
id,
|
|
96996
|
-
file:
|
|
97109
|
+
file: path57.relative(process.cwd(), file),
|
|
96997
97110
|
bytes: data.html.length,
|
|
96998
97111
|
fidelity: data.fidelity,
|
|
96999
97112
|
reproduction_notes: data.reproductionNotes,
|
|
@@ -97453,7 +97566,7 @@ function classifyCaptureFailure(error) {
|
|
|
97453
97566
|
|
|
97454
97567
|
// src/engine/landing-library/run.ts
|
|
97455
97568
|
import { mkdir as mkdir18, writeFile as writeFile30 } from "fs/promises";
|
|
97456
|
-
import
|
|
97569
|
+
import path59 from "path";
|
|
97457
97570
|
|
|
97458
97571
|
// ../proxy/src/preflight.ts
|
|
97459
97572
|
import http from "http";
|
|
@@ -98871,9 +98984,9 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
|
|
|
98871
98984
|
|
|
98872
98985
|
// src/engine/landing-library/report.ts
|
|
98873
98986
|
import { writeFile as writeFile29 } from "fs/promises";
|
|
98874
|
-
import
|
|
98987
|
+
import path58 from "path";
|
|
98875
98988
|
async function writeCaptureReport(manifest, outDir) {
|
|
98876
|
-
const file =
|
|
98989
|
+
const file = path58.join(outDir, "report.html");
|
|
98877
98990
|
await writeFile29(file, renderReport(manifest));
|
|
98878
98991
|
return file;
|
|
98879
98992
|
}
|
|
@@ -99017,32 +99130,32 @@ async function reproducePage(args8) {
|
|
|
99017
99130
|
const { browser, page, outDir, pageUrl, livePageShot } = args8;
|
|
99018
99131
|
const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
|
|
99019
99132
|
if (!built) return { bundle: null, fidelity: null };
|
|
99020
|
-
await writeFile30(
|
|
99133
|
+
await writeFile30(path59.join(outDir, "page.html"), built.html);
|
|
99021
99134
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
|
|
99022
99135
|
wholePage: true,
|
|
99023
99136
|
timeoutMs: 6e4
|
|
99024
99137
|
});
|
|
99025
99138
|
if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
|
|
99026
|
-
await writeFile30(
|
|
99139
|
+
await writeFile30(path59.join(outDir, "page-rendered.png"), rendered);
|
|
99027
99140
|
const { score, note } = await scoreFidelity(livePageShot, rendered);
|
|
99028
99141
|
return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
|
|
99029
99142
|
}
|
|
99030
99143
|
async function captureOneSection(args8) {
|
|
99031
99144
|
const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args8;
|
|
99032
|
-
const dir =
|
|
99145
|
+
const dir = path59.join(sectionsDir, String(candidate.index).padStart(2, "0"));
|
|
99033
99146
|
await mkdir18(dir, { recursive: true });
|
|
99034
99147
|
const desktop = await captureSection(page, candidate);
|
|
99035
|
-
if (desktop) await writeFile30(
|
|
99148
|
+
if (desktop) await writeFile30(path59.join(dir, "desktop.png"), desktop);
|
|
99036
99149
|
const visualHash = desktop ? await perceptualHash(desktop) : null;
|
|
99037
99150
|
const motion = await collectMotion(page, candidate.selector);
|
|
99038
99151
|
const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
|
|
99039
99152
|
let fidelity = null;
|
|
99040
99153
|
let fidelityNote;
|
|
99041
99154
|
if (built) {
|
|
99042
|
-
await writeFile30(
|
|
99155
|
+
await writeFile30(path59.join(dir, "section.html"), built.html);
|
|
99043
99156
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
|
|
99044
99157
|
if (rendered && desktop) {
|
|
99045
|
-
await writeFile30(
|
|
99158
|
+
await writeFile30(path59.join(dir, "section-rendered.png"), rendered);
|
|
99046
99159
|
const result = await scoreFidelity(desktop, rendered);
|
|
99047
99160
|
fidelity = result.score;
|
|
99048
99161
|
fidelityNote = result.note;
|
|
@@ -99050,9 +99163,9 @@ async function captureOneSection(args8) {
|
|
|
99050
99163
|
}
|
|
99051
99164
|
return {
|
|
99052
99165
|
...candidate,
|
|
99053
|
-
desktopShot: desktop ?
|
|
99166
|
+
desktopShot: desktop ? path59.relative(outDir, path59.join(dir, "desktop.png")) : null,
|
|
99054
99167
|
mobileShot: null,
|
|
99055
|
-
bundle: built ?
|
|
99168
|
+
bundle: built ? path59.relative(outDir, path59.join(dir, "section.html")) : null,
|
|
99056
99169
|
fidelity,
|
|
99057
99170
|
...fidelityNote ? { fidelityNote } : {},
|
|
99058
99171
|
...built ? { cssStats: built.stats } : {},
|
|
@@ -99071,9 +99184,9 @@ async function captureMobileShots(args8) {
|
|
|
99071
99184
|
for (const section2 of sections) {
|
|
99072
99185
|
const shot = await captureSectionOnMobile(mobile.page, section2);
|
|
99073
99186
|
if (!shot) continue;
|
|
99074
|
-
const file =
|
|
99187
|
+
const file = path59.join(sectionsDir, String(section2.index).padStart(2, "0"), "mobile.png");
|
|
99075
99188
|
await writeFile30(file, shot);
|
|
99076
|
-
section2.mobileShot =
|
|
99189
|
+
section2.mobileShot = path59.relative(outDir, file);
|
|
99077
99190
|
}
|
|
99078
99191
|
} finally {
|
|
99079
99192
|
await mobile.context.close();
|
|
@@ -99088,10 +99201,10 @@ async function captureMotionTakes(args8) {
|
|
|
99088
99201
|
const filmOne = async (section2) => {
|
|
99089
99202
|
const take = await captureMotionTake(browser, pageUrl, section2.selector).catch(() => null);
|
|
99090
99203
|
if (!take) return;
|
|
99091
|
-
const dir =
|
|
99092
|
-
const file =
|
|
99204
|
+
const dir = path59.join(sectionsDir, String(section2.index).padStart(2, "0"));
|
|
99205
|
+
const file = path59.join(dir, "motion-filmstrip.png");
|
|
99093
99206
|
await writeFile30(file, take.filmstrip);
|
|
99094
|
-
section2.motionFilmstrip =
|
|
99207
|
+
section2.motionFilmstrip = path59.relative(outDir, file);
|
|
99095
99208
|
log(` [${section2.index}] ${section2.motion.summary}`);
|
|
99096
99209
|
};
|
|
99097
99210
|
const queue = [...moving];
|
|
@@ -99148,7 +99261,7 @@ async function captureAlternateViews(args8) {
|
|
|
99148
99261
|
async function reproduceWholePage(args8) {
|
|
99149
99262
|
const { browser, page, outDir, pageUrl, withCode, log } = args8;
|
|
99150
99263
|
const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
|
|
99151
|
-
if (fullPage) await writeFile30(
|
|
99264
|
+
if (fullPage) await writeFile30(path59.join(outDir, "full-page.png"), fullPage);
|
|
99152
99265
|
if (!withCode) return { bundle: null, fidelity: null };
|
|
99153
99266
|
const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
|
|
99154
99267
|
log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
|
|
@@ -99219,7 +99332,7 @@ async function openViaLadder(args8) {
|
|
|
99219
99332
|
async function scrapeLanding(options) {
|
|
99220
99333
|
const timeoutMs = options.timeoutMs ?? 45e3;
|
|
99221
99334
|
const log = options.onProgress ?? (() => void 0);
|
|
99222
|
-
const sectionsDir =
|
|
99335
|
+
const sectionsDir = path59.join(options.outDir, "sections");
|
|
99223
99336
|
const nonPublic = refuseNonPublicUrl(options.url);
|
|
99224
99337
|
if (nonPublic) {
|
|
99225
99338
|
throw new BlockedPageError({
|
|
@@ -99281,7 +99394,7 @@ async function scrapeLanding(options) {
|
|
|
99281
99394
|
security: prepared.security,
|
|
99282
99395
|
captureTier: tier
|
|
99283
99396
|
};
|
|
99284
|
-
await writeFile30(
|
|
99397
|
+
await writeFile30(path59.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
99285
99398
|
`);
|
|
99286
99399
|
if (options.report !== false) {
|
|
99287
99400
|
const reportPath = await writeCaptureReport(manifest, options.outDir);
|
|
@@ -99296,28 +99409,28 @@ async function scrapeLanding(options) {
|
|
|
99296
99409
|
|
|
99297
99410
|
// src/commands/landing/inspiration/captureOut.ts
|
|
99298
99411
|
import { existsSync as existsSync12 } from "fs";
|
|
99299
|
-
import
|
|
99412
|
+
import path60 from "path";
|
|
99300
99413
|
var SCRATCH_DIR = ".baker";
|
|
99301
99414
|
function isWithin(parent, target2) {
|
|
99302
|
-
const relative =
|
|
99303
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
99415
|
+
const relative = path60.relative(parent, target2);
|
|
99416
|
+
return relative === "" || !relative.startsWith("..") && !path60.isAbsolute(relative);
|
|
99304
99417
|
}
|
|
99305
99418
|
function findRepoRoot(from) {
|
|
99306
|
-
let dir =
|
|
99419
|
+
let dir = path60.resolve(from);
|
|
99307
99420
|
for (; ; ) {
|
|
99308
|
-
if (existsSync12(
|
|
99309
|
-
const parent =
|
|
99421
|
+
if (existsSync12(path60.join(dir, ".git"))) return dir;
|
|
99422
|
+
const parent = path60.dirname(dir);
|
|
99310
99423
|
if (parent === dir) return null;
|
|
99311
99424
|
dir = parent;
|
|
99312
99425
|
}
|
|
99313
99426
|
}
|
|
99314
99427
|
function checkCaptureOut(out, options) {
|
|
99315
99428
|
const { cwd, repoRoot } = options;
|
|
99316
|
-
const resolved =
|
|
99429
|
+
const resolved = path60.resolve(cwd, out);
|
|
99317
99430
|
if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
|
|
99318
|
-
const scratch =
|
|
99431
|
+
const scratch = path60.join(repoRoot, SCRATCH_DIR);
|
|
99319
99432
|
if (isWithin(scratch, resolved)) return { ok: true };
|
|
99320
|
-
const suggestion =
|
|
99433
|
+
const suggestion = path60.posix.join(SCRATCH_DIR, "teardowns", path60.basename(resolved) || "capture");
|
|
99321
99434
|
return {
|
|
99322
99435
|
ok: false,
|
|
99323
99436
|
error: {
|
|
@@ -99491,12 +99604,12 @@ var scrapeCommand = defineCommand220({
|
|
|
99491
99604
|
});
|
|
99492
99605
|
|
|
99493
99606
|
// src/commands/landing/inspiration/search.ts
|
|
99494
|
-
import
|
|
99607
|
+
import path62 from "path";
|
|
99495
99608
|
import { defineCommand as defineCommand221 } from "citty";
|
|
99496
99609
|
|
|
99497
99610
|
// src/commands/landing/inspiration/shot.ts
|
|
99498
99611
|
import { mkdir as mkdir19, writeFile as writeFile31 } from "fs/promises";
|
|
99499
|
-
import
|
|
99612
|
+
import path61 from "path";
|
|
99500
99613
|
import sharp9 from "sharp";
|
|
99501
99614
|
var READABLE_SHOT = {
|
|
99502
99615
|
maxWidth: 1440,
|
|
@@ -99522,9 +99635,9 @@ async function downloadReadableShot(url, file) {
|
|
|
99522
99635
|
const response = await fetch(url);
|
|
99523
99636
|
if (!response.ok) return null;
|
|
99524
99637
|
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
99525
|
-
await mkdir19(
|
|
99638
|
+
await mkdir19(path61.dirname(file), { recursive: true });
|
|
99526
99639
|
await writeFile31(file, shot);
|
|
99527
|
-
return
|
|
99640
|
+
return path61.relative(process.cwd(), file);
|
|
99528
99641
|
} catch {
|
|
99529
99642
|
return null;
|
|
99530
99643
|
}
|
|
@@ -99616,13 +99729,13 @@ function buildSearchBody2(args8) {
|
|
|
99616
99729
|
return body;
|
|
99617
99730
|
}
|
|
99618
99731
|
async function downloadShots(results) {
|
|
99619
|
-
const dir =
|
|
99732
|
+
const dir = path62.join(process.cwd(), ".baker", "inspiration");
|
|
99620
99733
|
const saved = /* @__PURE__ */ new Map();
|
|
99621
99734
|
await Promise.all(
|
|
99622
99735
|
results.map(async (result) => {
|
|
99623
99736
|
const file = await downloadReadableShot(
|
|
99624
99737
|
result.desktopShotUrl,
|
|
99625
|
-
|
|
99738
|
+
path62.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
99626
99739
|
);
|
|
99627
99740
|
if (file) saved.set(result.id, file);
|
|
99628
99741
|
})
|
|
@@ -99850,7 +99963,7 @@ var sequencesCommand = defineCommand222({
|
|
|
99850
99963
|
});
|
|
99851
99964
|
|
|
99852
99965
|
// src/commands/landing/inspiration/view.ts
|
|
99853
|
-
import
|
|
99966
|
+
import path63 from "path";
|
|
99854
99967
|
import { defineCommand as defineCommand223 } from "citty";
|
|
99855
99968
|
registerSchema({
|
|
99856
99969
|
command: "landing.inspiration.view",
|
|
@@ -99883,12 +99996,12 @@ var viewCommand2 = defineCommand223({
|
|
|
99883
99996
|
const id = args8.id;
|
|
99884
99997
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
99885
99998
|
const section2 = data.section;
|
|
99886
|
-
const dir =
|
|
99999
|
+
const dir = path63.join(process.cwd(), ".baker", "inspiration", id);
|
|
99887
100000
|
const ext = READABLE_SHOT.extension;
|
|
99888
100001
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
99889
|
-
downloadReadableShot(section2.desktopShotUrl,
|
|
99890
|
-
downloadReadableShot(section2.mobileShotUrl,
|
|
99891
|
-
downloadReadableShot(section2.motionFilmstripUrl,
|
|
100002
|
+
downloadReadableShot(section2.desktopShotUrl, path63.join(dir, `desktop.${ext}`)),
|
|
100003
|
+
downloadReadableShot(section2.mobileShotUrl, path63.join(dir, `mobile.${ext}`)),
|
|
100004
|
+
downloadReadableShot(section2.motionFilmstripUrl, path63.join(dir, `motion-filmstrip.${ext}`))
|
|
99892
100005
|
]);
|
|
99893
100006
|
const full = args8.full;
|
|
99894
100007
|
const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -99997,7 +100110,7 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
|
|
|
99997
100110
|
// src/commands/landing/variant.ts
|
|
99998
100111
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
99999
100112
|
import { mkdir as mkdir20, readdir as readdir23, readFile as readFile49, stat as stat13, writeFile as writeFile32 } from "fs/promises";
|
|
100000
|
-
import
|
|
100113
|
+
import path64 from "path";
|
|
100001
100114
|
import { defineCommand as defineCommand225 } from "citty";
|
|
100002
100115
|
registerSchema({
|
|
100003
100116
|
command: "landing.variant",
|
|
@@ -100033,7 +100146,7 @@ async function readInternalId(definitionPath) {
|
|
|
100033
100146
|
async function archivedVariantNumbers(root, internalId) {
|
|
100034
100147
|
if (!internalId) return [];
|
|
100035
100148
|
try {
|
|
100036
|
-
const entries = await readdir23(
|
|
100149
|
+
const entries = await readdir23(path64.resolve(root, "src/_variants", internalId), { withFileTypes: true });
|
|
100037
100150
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
|
|
100038
100151
|
} catch {
|
|
100039
100152
|
return [];
|
|
@@ -100063,7 +100176,7 @@ async function exists2(p) {
|
|
|
100063
100176
|
}
|
|
100064
100177
|
async function listLandingSlugs2(root) {
|
|
100065
100178
|
try {
|
|
100066
|
-
const entries = await readdir23(
|
|
100179
|
+
const entries = await readdir23(path64.resolve(root, "src", "pages"), { withFileTypes: true });
|
|
100067
100180
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
100068
100181
|
} catch {
|
|
100069
100182
|
return [];
|
|
@@ -100079,7 +100192,7 @@ async function listComponents(componentsDir, prefix = "") {
|
|
|
100079
100192
|
const out = [];
|
|
100080
100193
|
for (const entry of entries) {
|
|
100081
100194
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
100082
|
-
if (entry.isDirectory()) out.push(...await listComponents(
|
|
100195
|
+
if (entry.isDirectory()) out.push(...await listComponents(path64.join(componentsDir, entry.name), rel));
|
|
100083
100196
|
else if (entry.name.endsWith(".astro")) out.push(rel);
|
|
100084
100197
|
}
|
|
100085
100198
|
return out.sort();
|
|
@@ -100146,16 +100259,16 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
100146
100259
|
`"${controlSlug}" is already a variant of "${variantOfSlug(controlSlug)}". Make the next variant of the page itself: \`baker landing variant ${variantOfSlug(controlSlug)}\`.`
|
|
100147
100260
|
);
|
|
100148
100261
|
}
|
|
100149
|
-
const controlDir =
|
|
100262
|
+
const controlDir = path64.resolve(projectRoot, "src", "pages", controlSlug);
|
|
100150
100263
|
if (!await isDir3(controlDir)) {
|
|
100151
100264
|
fail11("NOT_FOUND", `No page at src/pages/${controlSlug}/`, {
|
|
100152
100265
|
availableSlugs: await listLandingSlugs2(projectRoot)
|
|
100153
100266
|
});
|
|
100154
100267
|
}
|
|
100155
|
-
if (!await exists2(
|
|
100268
|
+
if (!await exists2(path64.join(controlDir, "index.astro"))) {
|
|
100156
100269
|
fail11("NOT_FOUND", `src/pages/${controlSlug}/index.astro is missing, so there is no page to make a variant of.`);
|
|
100157
100270
|
}
|
|
100158
|
-
const internalId = await readInternalId(
|
|
100271
|
+
const internalId = await readInternalId(path64.join(controlDir, "_definition.md"));
|
|
100159
100272
|
const variantSlugValue = variantSlug(
|
|
100160
100273
|
controlSlug,
|
|
100161
100274
|
nextVariantNumber(
|
|
@@ -100164,8 +100277,8 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
100164
100277
|
await archivedVariantNumbers(projectRoot, internalId)
|
|
100165
100278
|
)
|
|
100166
100279
|
);
|
|
100167
|
-
const variantDir =
|
|
100168
|
-
const available = await listComponents(
|
|
100280
|
+
const variantDir = path64.resolve(projectRoot, "src", "pages", variantSlugValue);
|
|
100281
|
+
const available = await listComponents(path64.join(controlDir, "_components"));
|
|
100169
100282
|
const forks = [];
|
|
100170
100283
|
for (const name of parseForks(opts.fork, opts.rawArgs)) {
|
|
100171
100284
|
const resolved = resolveForkName(name, available);
|
|
@@ -100181,26 +100294,26 @@ async function resolveTargets(projectRoot, opts) {
|
|
|
100181
100294
|
}
|
|
100182
100295
|
async function writeVariant(opts) {
|
|
100183
100296
|
const { controlDir, variantDir, controlSlug, variantSlug: variantSlug2, forks } = opts;
|
|
100184
|
-
const forkedTargets = new Set(forks.map((f) =>
|
|
100297
|
+
const forkedTargets = new Set(forks.map((f) => path64.join(controlDir, "_components", f)));
|
|
100185
100298
|
const written = [];
|
|
100186
|
-
const indexText = await readFile49(
|
|
100299
|
+
const indexText = await readFile49(path64.join(controlDir, "index.astro"), "utf8");
|
|
100187
100300
|
await mkdir20(variantDir, { recursive: true });
|
|
100188
100301
|
await writeFile32(
|
|
100189
|
-
|
|
100302
|
+
path64.join(variantDir, "index.astro"),
|
|
100190
100303
|
repointFile(indexText, { fromDir: controlDir, toDir: variantDir, controlDir, variantDir, forkedTargets }),
|
|
100191
100304
|
"utf8"
|
|
100192
100305
|
);
|
|
100193
100306
|
written.push(`src/pages/${variantSlug2}/index.astro`);
|
|
100194
100307
|
for (const fork of forks) {
|
|
100195
|
-
const fromFile =
|
|
100196
|
-
const toFile =
|
|
100308
|
+
const fromFile = path64.join(controlDir, "_components", fork);
|
|
100309
|
+
const toFile = path64.join(variantDir, "_components", fork);
|
|
100197
100310
|
const text3 = await readFile49(fromFile, "utf8");
|
|
100198
|
-
await mkdir20(
|
|
100311
|
+
await mkdir20(path64.dirname(toFile), { recursive: true });
|
|
100199
100312
|
await writeFile32(
|
|
100200
100313
|
toFile,
|
|
100201
100314
|
repointFile(text3, {
|
|
100202
|
-
fromDir:
|
|
100203
|
-
toDir:
|
|
100315
|
+
fromDir: path64.dirname(fromFile),
|
|
100316
|
+
toDir: path64.dirname(toFile),
|
|
100204
100317
|
controlDir,
|
|
100205
100318
|
variantDir,
|
|
100206
100319
|
forkedTargets
|
|
@@ -100209,7 +100322,7 @@ async function writeVariant(opts) {
|
|
|
100209
100322
|
);
|
|
100210
100323
|
written.push(`src/pages/${variantSlug2}/_components/${fork}`);
|
|
100211
100324
|
}
|
|
100212
|
-
const controlDefinitionPath =
|
|
100325
|
+
const controlDefinitionPath = path64.join(controlDir, "_definition.md");
|
|
100213
100326
|
if (await exists2(controlDefinitionPath)) {
|
|
100214
100327
|
const definition = buildVariantDefinition(await readFile49(controlDefinitionPath, "utf8"), {
|
|
100215
100328
|
internalId: randomUUID4().replace(/-/g, "").slice(0, 8),
|
|
@@ -100219,11 +100332,11 @@ async function writeVariant(opts) {
|
|
|
100219
100332
|
...opts.because ? { because: opts.because } : {},
|
|
100220
100333
|
...opts.change ? { change: opts.change } : {}
|
|
100221
100334
|
});
|
|
100222
|
-
await writeFile32(
|
|
100335
|
+
await writeFile32(path64.join(variantDir, "_definition.md"), definition, "utf8");
|
|
100223
100336
|
written.push(`src/pages/${variantSlug2}/_definition.md`);
|
|
100224
100337
|
}
|
|
100225
|
-
await mkdir20(
|
|
100226
|
-
await writeFile32(
|
|
100338
|
+
await mkdir20(path64.join(variantDir, "_images"), { recursive: true });
|
|
100339
|
+
await writeFile32(path64.join(variantDir, "_images", ".gitkeep"), "", "utf8");
|
|
100227
100340
|
return written;
|
|
100228
100341
|
}
|
|
100229
100342
|
var variantCommand = defineCommand225({
|
|
@@ -101571,7 +101684,7 @@ var countriesCommand = defineCommand237({
|
|
|
101571
101684
|
|
|
101572
101685
|
// src/commands/research/customers.ts
|
|
101573
101686
|
import { mkdir as mkdir21, readdir as readdir24, readFile as readFile50, writeFile as writeFile33 } from "fs/promises";
|
|
101574
|
-
import
|
|
101687
|
+
import path65 from "path";
|
|
101575
101688
|
import { defineCommand as defineCommand239 } from "citty";
|
|
101576
101689
|
import { parse as parseYaml5 } from "yaml";
|
|
101577
101690
|
import { z as z77 } from "zod";
|
|
@@ -102123,7 +102236,7 @@ function customersHints(input) {
|
|
|
102123
102236
|
const cite = `Cite these by id in an idea's \`evidence\` (src/creatives/_ideas/<idea>.md); write the ad from the quote as said.`;
|
|
102124
102237
|
return written < FEW_OBSERVED ? [`Only ${written} observed. ${widen}`, cite] : [cite];
|
|
102125
102238
|
}
|
|
102126
|
-
var INSIGHTS_DIR2 =
|
|
102239
|
+
var INSIGHTS_DIR2 = path65.join("src", "content", "insights");
|
|
102127
102240
|
var BATCH_CHARS = 24e3;
|
|
102128
102241
|
var MAX_BATCHES = 5;
|
|
102129
102242
|
var WEB_PAGES = 3;
|
|
@@ -102188,12 +102301,12 @@ async function readExistingInsights(dir) {
|
|
|
102188
102301
|
return await Promise.all(
|
|
102189
102302
|
files.map(async (file) => ({
|
|
102190
102303
|
id: file.slice(0, -3),
|
|
102191
|
-
quote: quoteOf(await readFile50(
|
|
102304
|
+
quote: quoteOf(await readFile50(path65.join(dir, file), "utf8").catch(() => ""))
|
|
102192
102305
|
}))
|
|
102193
102306
|
);
|
|
102194
102307
|
}
|
|
102195
102308
|
async function productSlugs(root) {
|
|
102196
|
-
const files = await readdir24(
|
|
102309
|
+
const files = await readdir24(path65.join(root, "src", "content", "products")).catch(() => []);
|
|
102197
102310
|
return files.filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3));
|
|
102198
102311
|
}
|
|
102199
102312
|
async function gatherTestimonials(focus) {
|
|
@@ -102293,7 +102406,7 @@ async function classifyAll(sources, focus, root) {
|
|
|
102293
102406
|
const batches = batchSources(sources, BATCH_CHARS).slice(0, MAX_BATCHES);
|
|
102294
102407
|
const spent = [];
|
|
102295
102408
|
const answers = await Promise.all(batches.map((batch) => classifyBatch(batch, focus, (u) => spent.push(u))));
|
|
102296
|
-
await holdUnbilledSpend(
|
|
102409
|
+
await holdUnbilledSpend(path65.join(root, "canvas", ".cache"), spent);
|
|
102297
102410
|
if (batches.length > 0 && answers.every((a) => a === null)) return null;
|
|
102298
102411
|
const result = { kept: [], dropped: 0, tooLong: 0 };
|
|
102299
102412
|
batches.forEach((batch, i) => {
|
|
@@ -102310,7 +102423,7 @@ async function writeInsights(dir, writes, opts) {
|
|
|
102310
102423
|
const written = [];
|
|
102311
102424
|
for (const entry of writes) {
|
|
102312
102425
|
const file = renderInsightFile(entry.insight, opts);
|
|
102313
|
-
const ok = await writeFile33(
|
|
102426
|
+
const ok = await writeFile33(path65.join(dir, `${entry.id}.md`), file, { encoding: "utf8", flag: "wx" }).then(
|
|
102314
102427
|
() => true,
|
|
102315
102428
|
() => false
|
|
102316
102429
|
);
|
|
@@ -102361,7 +102474,7 @@ var customersCommand = defineCommand239({
|
|
|
102361
102474
|
"Run it again. Do not write insights by hand: an insight is only a quote this command found in its source."
|
|
102362
102475
|
);
|
|
102363
102476
|
}
|
|
102364
|
-
const dir =
|
|
102477
|
+
const dir = path65.join(root, INSIGHTS_DIR2);
|
|
102365
102478
|
const plan = planInsightWrites(gated.kept, await readExistingInsights(dir), limit);
|
|
102366
102479
|
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
102367
102480
|
const shown = dryRun ? plan.writes : await writeInsights(dir, plan.writes, { today: today2, ...product ? { product } : {} });
|
|
@@ -103964,7 +104077,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
103964
104077
|
|
|
103965
104078
|
// src/commands/scheduled-agents/templates.ts
|
|
103966
104079
|
import { readFile as readFile51 } from "fs/promises";
|
|
103967
|
-
import
|
|
104080
|
+
import path66 from "path";
|
|
103968
104081
|
import { defineCommand as defineCommand256 } from "citty";
|
|
103969
104082
|
registerSchema({
|
|
103970
104083
|
command: "scheduled-agents.templates",
|
|
@@ -104071,7 +104184,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
|
|
|
104071
104184
|
}
|
|
104072
104185
|
if (save.length > 0) {
|
|
104073
104186
|
const briefFile = flag2("brief-file");
|
|
104074
|
-
const brief2 = briefFile.length > 0 ? await readFile51(
|
|
104187
|
+
const brief2 = briefFile.length > 0 ? await readFile51(path66.resolve(briefFile), "utf8") : flag2("brief");
|
|
104075
104188
|
if (brief2.trim().length === 0) {
|
|
104076
104189
|
failValidation6("--brief-file (preferred) or --brief is required: the brief is the recipe.");
|
|
104077
104190
|
}
|
|
@@ -104853,7 +104966,7 @@ var setCommand = defineCommand264({
|
|
|
104853
104966
|
timezone: args8.timezone,
|
|
104854
104967
|
"export-profile": args8["export-profile"]
|
|
104855
104968
|
},
|
|
104856
|
-
(
|
|
104969
|
+
(path69) => readFileSync26(path69, "utf8")
|
|
104857
104970
|
);
|
|
104858
104971
|
const body = { chatId: requireChatId(), inputs };
|
|
104859
104972
|
writeJson(await apiPost("/api/site/stage", body));
|
|
@@ -105135,7 +105248,7 @@ function parseImageRefs(spec) {
|
|
|
105135
105248
|
}
|
|
105136
105249
|
var defaultDeps = {
|
|
105137
105250
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
105138
|
-
upload: (
|
|
105251
|
+
upload: (path69) => uploadLocalImage({ file: path69, contentType: detectImageContentType(path69), source: "uploaded" })
|
|
105139
105252
|
};
|
|
105140
105253
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
105141
105254
|
const refs = parseImageRefs(spec);
|
|
@@ -105155,10 +105268,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
105155
105268
|
}
|
|
105156
105269
|
return { imageIds, added };
|
|
105157
105270
|
}
|
|
105158
|
-
function uploadFailure(
|
|
105271
|
+
function uploadFailure(path69) {
|
|
105159
105272
|
return (error) => {
|
|
105160
105273
|
if (error instanceof ApiError) throw error;
|
|
105161
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
105274
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path69}" as an image.`);
|
|
105162
105275
|
};
|
|
105163
105276
|
}
|
|
105164
105277
|
|
|
@@ -106258,10 +106371,10 @@ async function stageOp4(op) {
|
|
|
106258
106371
|
handleError8(err);
|
|
106259
106372
|
}
|
|
106260
106373
|
}
|
|
106261
|
-
async function draftAction3(
|
|
106374
|
+
async function draftAction3(path69, body, chat) {
|
|
106262
106375
|
const chatId = resolveChatId(chat);
|
|
106263
106376
|
try {
|
|
106264
|
-
const { data, hints: hints2 } = splitHints(await apiPost(
|
|
106377
|
+
const { data, hints: hints2 } = splitHints(await apiPost(path69, { chatId, ...body }));
|
|
106265
106378
|
writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
|
|
106266
106379
|
return data;
|
|
106267
106380
|
} catch (err) {
|
|
@@ -107825,7 +107938,7 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
|
|
|
107825
107938
|
import { constants } from "fs";
|
|
107826
107939
|
import { copyFile as copyFile2, mkdir as mkdir22, mkdtemp as mkdtemp3, rm as rm9 } from "fs/promises";
|
|
107827
107940
|
import { tmpdir as tmpdir4 } from "os";
|
|
107828
|
-
import
|
|
107941
|
+
import path67 from "path";
|
|
107829
107942
|
import { defineCommand as defineCommand293 } from "citty";
|
|
107830
107943
|
|
|
107831
107944
|
// src/commands/videos/videoPlatforms.ts
|
|
@@ -107993,8 +108106,8 @@ var fetchCommand2 = defineCommand293({
|
|
|
107993
108106
|
}
|
|
107994
108107
|
});
|
|
107995
108108
|
async function fetchVideo(args8) {
|
|
107996
|
-
const outDir =
|
|
107997
|
-
const workDir = await mkdtemp3(
|
|
108109
|
+
const outDir = path67.resolve(args8.out);
|
|
108110
|
+
const workDir = await mkdtemp3(path67.join(tmpdir4(), "videos-fetch-"));
|
|
107998
108111
|
try {
|
|
107999
108112
|
await mkdir22(outDir, { recursive: true });
|
|
108000
108113
|
const vimeoCookie = captureVimeoCookie();
|
|
@@ -108039,7 +108152,7 @@ function fileStem(info) {
|
|
|
108039
108152
|
}
|
|
108040
108153
|
async function placeInto(outDir, source, stem) {
|
|
108041
108154
|
for (let n = 1; ; n++) {
|
|
108042
|
-
const target2 =
|
|
108155
|
+
const target2 = path67.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path67.extname(source)}`);
|
|
108043
108156
|
try {
|
|
108044
108157
|
await copyFile2(source, target2, constants.COPYFILE_EXCL);
|
|
108045
108158
|
return target2;
|
|
@@ -108126,7 +108239,7 @@ var groupCommand2 = defineCommand295({
|
|
|
108126
108239
|
// src/commands/videos/ingest.ts
|
|
108127
108240
|
import { mkdtemp as mkdtemp4, rm as rm10, stat as stat14 } from "fs/promises";
|
|
108128
108241
|
import { tmpdir as tmpdir5 } from "os";
|
|
108129
|
-
import
|
|
108242
|
+
import path68 from "path";
|
|
108130
108243
|
import { defineCommand as defineCommand296 } from "citty";
|
|
108131
108244
|
|
|
108132
108245
|
// src/lib/streamUpload.ts
|
|
@@ -108366,7 +108479,7 @@ function ingestUrl(args8) {
|
|
|
108366
108479
|
}
|
|
108367
108480
|
async function downloadThenIngest(args8, country) {
|
|
108368
108481
|
const vimeoCookie = captureVimeoCookie();
|
|
108369
|
-
const workDir = await mkdtemp4(
|
|
108482
|
+
const workDir = await mkdtemp4(path68.join(tmpdir5(), "videos-ingest-"));
|
|
108370
108483
|
try {
|
|
108371
108484
|
const probe = await probeYtDlp({ url: args8.url, country, vimeoCookie, cookieDir: workDir });
|
|
108372
108485
|
if (isAudioOnly(probe.info)) {
|