@koda-sl/baker-cli 0.347.0 → 0.348.0-dev.78a35388f
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 +21 -11
- package/dist/{chunk-YBD3W4M7.js → chunk-4QG7SF4U.js} +83 -10
- package/dist/chunk-4QG7SF4U.js.map +1 -0
- package/dist/cli.js +204 -31
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-YBD3W4M7.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
YtDlpError,
|
|
24
24
|
bestSupportedQuality,
|
|
25
25
|
canonicalUrl,
|
|
26
|
+
catalogView,
|
|
26
27
|
clipAudioMode,
|
|
27
28
|
clipDurationsFor,
|
|
28
29
|
clipParamRecipe,
|
|
@@ -67,7 +68,7 @@ import {
|
|
|
67
68
|
validateCanvasDeep,
|
|
68
69
|
withoutCastName,
|
|
69
70
|
ytDlpBlockSignal
|
|
70
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-4QG7SF4U.js";
|
|
71
72
|
import {
|
|
72
73
|
csvOrJson,
|
|
73
74
|
daysAgoIso,
|
|
@@ -1957,6 +1958,7 @@ var GOOGLE_ADS_LIMITS = {
|
|
|
1957
1958
|
businessNameMax: 25
|
|
1958
1959
|
}
|
|
1959
1960
|
};
|
|
1961
|
+
var GOOGLE_ADS_QUERY_MAX_PAGE_SIZE = 8192;
|
|
1960
1962
|
var KEYWORD_MATCH_TYPES = ["EXACT", "PHRASE", "BROAD"];
|
|
1961
1963
|
var ADVERTISING_CHANNEL_TYPES = [
|
|
1962
1964
|
"SEARCH",
|
|
@@ -9674,7 +9676,76 @@ function urlOptionsHints(report) {
|
|
|
9674
9676
|
return hints2;
|
|
9675
9677
|
}
|
|
9676
9678
|
|
|
9679
|
+
// src/commands/ads/google/during-literals.ts
|
|
9680
|
+
var GAQL_DURING_LITERALS = [
|
|
9681
|
+
"TODAY",
|
|
9682
|
+
"YESTERDAY",
|
|
9683
|
+
"LAST_7_DAYS",
|
|
9684
|
+
"LAST_14_DAYS",
|
|
9685
|
+
"LAST_30_DAYS",
|
|
9686
|
+
"LAST_BUSINESS_WEEK",
|
|
9687
|
+
"THIS_MONTH",
|
|
9688
|
+
"LAST_MONTH",
|
|
9689
|
+
"THIS_WEEK_SUN_TODAY",
|
|
9690
|
+
"THIS_WEEK_MON_TODAY",
|
|
9691
|
+
"LAST_WEEK_SUN_SAT",
|
|
9692
|
+
"LAST_WEEK_MON_SUN"
|
|
9693
|
+
];
|
|
9694
|
+
function isDuringLiteral(value) {
|
|
9695
|
+
return GAQL_DURING_LITERALS.includes(value.toUpperCase());
|
|
9696
|
+
}
|
|
9697
|
+
function isoDay(date) {
|
|
9698
|
+
return date.toISOString().slice(0, 10);
|
|
9699
|
+
}
|
|
9700
|
+
function utcDate(year, month, day) {
|
|
9701
|
+
return new Date(Date.UTC(year, month, day));
|
|
9702
|
+
}
|
|
9703
|
+
function monthsBefore(date, months) {
|
|
9704
|
+
const lastDayOfTarget = utcDate(date.getUTCFullYear(), date.getUTCMonth() - months + 1, 0).getUTCDate();
|
|
9705
|
+
return utcDate(date.getUTCFullYear(), date.getUTCMonth() - months, Math.min(date.getUTCDate(), lastDayOfTarget));
|
|
9706
|
+
}
|
|
9707
|
+
function equivalentBetween(literal, now) {
|
|
9708
|
+
const upper2 = literal.toUpperCase();
|
|
9709
|
+
const today = utcDate(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
|
|
9710
|
+
const yesterday = utcDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate() - 1);
|
|
9711
|
+
const range = (from, to) => `BETWEEN '${isoDay(from)}' AND '${isoDay(to)}'`;
|
|
9712
|
+
const year = today.getUTCFullYear();
|
|
9713
|
+
const quarterStart = Math.floor(today.getUTCMonth() / 3) * 3;
|
|
9714
|
+
const rolling = upper2.match(/^LAST_(\d+)_(DAYS|WEEKS|MONTHS|YEARS)$/);
|
|
9715
|
+
if (rolling) {
|
|
9716
|
+
const n = Number(rolling[1]);
|
|
9717
|
+
const unit = rolling[2];
|
|
9718
|
+
if (n < 1) return null;
|
|
9719
|
+
if (unit === "DAYS" || unit === "WEEKS") {
|
|
9720
|
+
const days = unit === "DAYS" ? n : n * 7;
|
|
9721
|
+
return range(utcDate(year, today.getUTCMonth(), today.getUTCDate() - days), yesterday);
|
|
9722
|
+
}
|
|
9723
|
+
const months = unit === "MONTHS" ? n : n * 12;
|
|
9724
|
+
return range(monthsBefore(today, months), yesterday);
|
|
9725
|
+
}
|
|
9726
|
+
switch (upper2) {
|
|
9727
|
+
case "THIS_YEAR":
|
|
9728
|
+
return range(utcDate(year, 0, 1), today);
|
|
9729
|
+
case "LAST_YEAR":
|
|
9730
|
+
return range(utcDate(year - 1, 0, 1), utcDate(year - 1, 11, 31));
|
|
9731
|
+
case "THIS_QUARTER":
|
|
9732
|
+
return range(utcDate(year, quarterStart, 1), today);
|
|
9733
|
+
case "LAST_QUARTER":
|
|
9734
|
+
return range(utcDate(year, quarterStart - 3, 1), utcDate(year, quarterStart, 0));
|
|
9735
|
+
default:
|
|
9736
|
+
return null;
|
|
9737
|
+
}
|
|
9738
|
+
}
|
|
9739
|
+
function duringLiteralExplanation(literal, between) {
|
|
9740
|
+
const accepted = GAQL_DURING_LITERALS.join(", ");
|
|
9741
|
+
const lead = between ? `Google does not accept ${literal} after DURING. The same window as explicit dates is ${between}.` : `Google does not accept ${literal} after DURING, and it names no fixed window \u2014 use BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD', or drop the date filter.`;
|
|
9742
|
+
return `${lead} DURING accepts only: ${accepted}. Any other window needs BETWEEN.`;
|
|
9743
|
+
}
|
|
9744
|
+
|
|
9677
9745
|
// src/commands/ads/google/changes-window.ts
|
|
9746
|
+
function monthlySpendTrendQuery(now = /* @__PURE__ */ new Date()) {
|
|
9747
|
+
return `SELECT campaign.name, segments.month, metrics.cost_micros, metrics.conversions FROM campaign WHERE segments.date ${equivalentBetween("LAST_12_MONTHS", now)}`;
|
|
9748
|
+
}
|
|
9678
9749
|
function isChangeScope(value) {
|
|
9679
9750
|
return CHANGE_SCOPES.includes(value);
|
|
9680
9751
|
}
|
|
@@ -9728,7 +9799,7 @@ function lookbackTooLong(scope, days, max) {
|
|
|
9728
9799
|
message: `Google's account history API reaches back ${CHANGE_SCOPE_MAX_DAYS.summary} days at most; ${days} days is outside that window.`,
|
|
9729
9800
|
fix: {
|
|
9730
9801
|
action: "use_different_resource",
|
|
9731
|
-
explanation:
|
|
9802
|
+
explanation: `Do not abort \u2014 infer the change from performance instead. Query monthly metrics per campaign (${monthlySpendTrendQuery()}) to see which campaigns stopped or started spending. That shows what changed and when, though not who changed it. Older history exists only in the Google Ads web UI, which has no API \u2014 ask the user to check it if the 'who' matters.`
|
|
9732
9803
|
}
|
|
9733
9804
|
};
|
|
9734
9805
|
}
|
|
@@ -10087,7 +10158,7 @@ var CORRECTION_RULES = [
|
|
|
10087
10158
|
matchApiError: /changeStatusError\W{0,4}START_DATE_TOO_OLD/i,
|
|
10088
10159
|
fix: () => ({
|
|
10089
10160
|
action: "use_different_resource",
|
|
10090
|
-
explanation:
|
|
10161
|
+
explanation: `Google's account history reaches back 90 days at most, and this query asks for more. Do not abort \u2014 infer the change from performance: ${monthlySpendTrendQuery()} shows which campaigns started or stopped spending and when, though not who changed them. Anything older with attribution exists only in the Google Ads web UI, which has no API.`
|
|
10091
10162
|
})
|
|
10092
10163
|
},
|
|
10093
10164
|
// 18c. change_status rejects a date range it cannot bound. Google raises this both for
|
|
@@ -11914,9 +11985,16 @@ import { resolve } from "path";
|
|
|
11914
11985
|
import { defineCommand as defineCommand28 } from "citty";
|
|
11915
11986
|
|
|
11916
11987
|
// src/commands/ads/google/presets.ts
|
|
11917
|
-
var
|
|
11988
|
+
var BETWEEN_RE = /^BETWEEN\s+'[0-9]{4}-[0-9]{2}-[0-9]{2}'\s+AND\s+'[0-9]{4}-[0-9]{2}-[0-9]{2}'$/i;
|
|
11918
11989
|
function isValidDateRange(value) {
|
|
11919
|
-
|
|
11990
|
+
const trimmed = value.trim();
|
|
11991
|
+
return isDuringLiteral(trimmed) || BETWEEN_RE.test(trimmed);
|
|
11992
|
+
}
|
|
11993
|
+
function dateRangeError(dateRange, now) {
|
|
11994
|
+
if (/^[A-Za-z0-9_]+$/.test(dateRange.trim())) {
|
|
11995
|
+
return `Invalid date range: "${dateRange}". ${duringLiteralExplanation(dateRange, equivalentBetween(dateRange, now))} Pass it as --date-range "BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'".`;
|
|
11996
|
+
}
|
|
11997
|
+
return `Invalid date range: "${dateRange}". Use a GAQL date literal (e.g. LAST_30_DAYS, TODAY) or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'.`;
|
|
11920
11998
|
}
|
|
11921
11999
|
var SERVING_CHAINS = {
|
|
11922
12000
|
keyword_view: ["campaign.status", "ad_group.status", "ad_group_criterion.status"],
|
|
@@ -12052,17 +12130,15 @@ function buildStatusScope(statusFields, includePaused) {
|
|
|
12052
12130
|
const predicate = includePaused ? "!= 'REMOVED'" : "= 'ENABLED'";
|
|
12053
12131
|
return statusFields.map((field) => ` AND ${field} ${predicate}`).join("");
|
|
12054
12132
|
}
|
|
12055
|
-
function expandPreset(preset, params) {
|
|
12133
|
+
function expandPreset(preset, params, now = /* @__PURE__ */ new Date()) {
|
|
12056
12134
|
const dateRange = params.dateRange ?? preset.defaultDateRange;
|
|
12057
12135
|
const limit = params.limit ?? preset.defaultLimit;
|
|
12058
|
-
if (!isValidDateRange(dateRange)) {
|
|
12059
|
-
return {
|
|
12060
|
-
query: "",
|
|
12061
|
-
dateRangeError: `Invalid date range: "${dateRange}". Use a GAQL date literal (e.g. LAST_30_DAYS, TODAY) or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'.`
|
|
12062
|
-
};
|
|
12136
|
+
if (preset.gaqlTemplate.includes("{dateRange}") && !isValidDateRange(dateRange)) {
|
|
12137
|
+
return { query: "", dateRangeError: dateRangeError(dateRange, now) };
|
|
12063
12138
|
}
|
|
12064
12139
|
const statusScope = buildStatusScope(preset.statusFields, params.includePaused ?? false);
|
|
12065
|
-
const
|
|
12140
|
+
const range = dateRange.trim();
|
|
12141
|
+
const query = preset.gaqlTemplate.replace(/DURING\s+\{dateRange\}/g, BETWEEN_RE.test(range) ? range : `DURING ${range}`).replace(/\{dateRange\}/g, range).replace(/\{limit\}/g, String(limit)).replace(/\{statusScope\}/g, statusScope);
|
|
12066
12142
|
return { query };
|
|
12067
12143
|
}
|
|
12068
12144
|
|
|
@@ -12221,6 +12297,49 @@ function applyAutoFixes(query, limit) {
|
|
|
12221
12297
|
}
|
|
12222
12298
|
return { query: corrected, warnings };
|
|
12223
12299
|
}
|
|
12300
|
+
var DURING_CLAUSE = /(?<=[a-z_]\.[a-z_.]+\s+)DURING\s+([A-Za-z0-9_]+)/gi;
|
|
12301
|
+
function rejectUnsupportedDuring(query, customerId) {
|
|
12302
|
+
const unsupported = [...query.matchAll(DURING_CLAUSE)].map((match) => match[1] ?? "").filter((literal2) => !isDuringLiteral(literal2));
|
|
12303
|
+
const literal = unsupported[0];
|
|
12304
|
+
if (literal === void 0) return null;
|
|
12305
|
+
const now = /* @__PURE__ */ new Date();
|
|
12306
|
+
const between = equivalentBetween(literal, now);
|
|
12307
|
+
const fixed = unsupported.every((l) => equivalentBetween(l, now) !== null) ? query.replace(
|
|
12308
|
+
DURING_CLAUSE,
|
|
12309
|
+
(clause, l) => isDuringLiteral(l) ? clause : equivalentBetween(l, now) ?? clause
|
|
12310
|
+
) : void 0;
|
|
12311
|
+
return {
|
|
12312
|
+
ok: false,
|
|
12313
|
+
error: {
|
|
12314
|
+
code: "INVALID_DATE_RANGE",
|
|
12315
|
+
message: `DURING ${literal} is not a Google Ads date range, so Google would refuse this query.`,
|
|
12316
|
+
fix: {
|
|
12317
|
+
action: "narrow_date_range",
|
|
12318
|
+
...fixed ? { correctedCommand: buildCommand2(fixed, customerId) } : {},
|
|
12319
|
+
explanation: duringLiteralExplanation(literal, between)
|
|
12320
|
+
},
|
|
12321
|
+
retryable: false
|
|
12322
|
+
}
|
|
12323
|
+
};
|
|
12324
|
+
}
|
|
12325
|
+
function rejectOversizedLimit(query, customerId) {
|
|
12326
|
+
const match = query.match(/\bLIMIT\s+(\d+)\s*$/i);
|
|
12327
|
+
if (!match || Number(match[1]) <= GOOGLE_ADS_QUERY_MAX_PAGE_SIZE) return null;
|
|
12328
|
+
const fixed = query.replace(/\bLIMIT\s+\d+\s*$/i, `LIMIT ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE}`);
|
|
12329
|
+
return {
|
|
12330
|
+
ok: false,
|
|
12331
|
+
error: {
|
|
12332
|
+
code: "VALIDATION_ERROR",
|
|
12333
|
+
message: `LIMIT ${match[1]} is more rows than one read can return (${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE}).`,
|
|
12334
|
+
fix: {
|
|
12335
|
+
action: "retry_with_flag",
|
|
12336
|
+
correctedCommand: buildCommand2(fixed, customerId),
|
|
12337
|
+
explanation: `One query returns at most ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE} rows. For more, split the read into narrower queries \u2014 a shorter BETWEEN range each, or one campaign each \u2014 write each with --out, and combine the files.`
|
|
12338
|
+
},
|
|
12339
|
+
retryable: false
|
|
12340
|
+
}
|
|
12341
|
+
};
|
|
12342
|
+
}
|
|
12224
12343
|
function validatePreflight(query, customerId, limit) {
|
|
12225
12344
|
const warnings = [];
|
|
12226
12345
|
const corrected = query;
|
|
@@ -12292,6 +12411,10 @@ function validatePreflight(query, customerId, limit) {
|
|
|
12292
12411
|
}
|
|
12293
12412
|
};
|
|
12294
12413
|
}
|
|
12414
|
+
const duringRejection = rejectUnsupportedDuring(corrected, customerId);
|
|
12415
|
+
if (duringRejection) return { valid: false, warnings: [], error: duringRejection };
|
|
12416
|
+
const limitRejection = rejectOversizedLimit(corrected, customerId);
|
|
12417
|
+
if (limitRejection) return { valid: false, warnings: [], error: limitRejection };
|
|
12295
12418
|
if (/\bsegments\.conversion_action_name\b/i.test(corrected) && /\bmetrics\.cost_micros\b/i.test(corrected)) {
|
|
12296
12419
|
return {
|
|
12297
12420
|
valid: false,
|
|
@@ -12500,7 +12623,7 @@ registerSchema({
|
|
|
12500
12623
|
},
|
|
12501
12624
|
"date-range": {
|
|
12502
12625
|
type: "string",
|
|
12503
|
-
description: "Date range for presets (LAST_7_DAYS, LAST_30_DAYS,
|
|
12626
|
+
description: "Date range for presets: a Google date literal (TODAY, YESTERDAY, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, THIS_MONTH, LAST_MONTH \u2026) or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'. Google has no LAST_90_DAYS \u2014 use BETWEEN for any other window.",
|
|
12504
12627
|
required: false
|
|
12505
12628
|
},
|
|
12506
12629
|
"include-paused": {
|
|
@@ -12510,7 +12633,7 @@ registerSchema({
|
|
|
12510
12633
|
},
|
|
12511
12634
|
limit: {
|
|
12512
12635
|
type: "number",
|
|
12513
|
-
description: "Max rows in ONE page (default 200), AND the LIMIT added to a query that has none \u2014 so it caps the whole read with --all too. Values up to
|
|
12636
|
+
description: "Max rows in ONE page (default 200), AND the LIMIT added to a query that has none \u2014 so it caps the whole read with --all too. Values up to 8192 are accepted \u2014 the most one read can return. Any read that fills this cap comes back flagged TRUNCATED_RESULTS \u2014 never count or total from one.",
|
|
12514
12637
|
required: false,
|
|
12515
12638
|
default: 200
|
|
12516
12639
|
},
|
|
@@ -12518,7 +12641,7 @@ registerSchema({
|
|
|
12518
12641
|
cursor: { type: "string", description: "Pagination cursor from previous response", required: false },
|
|
12519
12642
|
all: {
|
|
12520
12643
|
type: "boolean",
|
|
12521
|
-
description: "Follow every page until the data set is exhausted (use with --out for large datasets). Needed for a read you may count or total, but not sufficient: it exhausts the pages, not the statement's LIMIT, so pair it with a
|
|
12644
|
+
description: "Follow every page until the data set is exhausted (use with --out for large datasets). Needed for a read you may count or total, but not sufficient: it exhausts the pages, not the statement's LIMIT, so pair it with a LIMIT in the statement above the row count you expect (at most 8192 \u2014 split bigger reads into narrower queries) and check the read came back without TRUNCATED_RESULTS.",
|
|
12522
12645
|
required: false
|
|
12523
12646
|
},
|
|
12524
12647
|
out: {
|
|
@@ -12605,7 +12728,8 @@ function completenessWarnings(read) {
|
|
|
12605
12728
|
const filledTheCap = cap3 !== void 0 && cap3 > 0 && read.rowCount >= cap3;
|
|
12606
12729
|
if (!read.hasMore && !filledTheCap) return [];
|
|
12607
12730
|
const cause = read.hasMore ? `More rows are waiting: the account returned a next-page cursor this run did not follow.` : `The ${read.rowCount} rows returned exactly fill the row cap in force (${cap3}).`;
|
|
12608
|
-
const
|
|
12731
|
+
const atPageCap = cap3 !== void 0 && cap3 >= GOOGLE_ADS_QUERY_MAX_PAGE_SIZE;
|
|
12732
|
+
const fix = atPageCap ? `${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE} rows is the most one read can return \u2014 split it into narrower queries (a shorter BETWEEN range each, or one campaign each), write each with --out, and combine the files.` : read.all ? `Every page was followed, so the cap is the LIMIT in the statement itself \u2014 raise it above ${cap3}, or drop it and pass a larger --limit (up to ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE}), then re-run.` : `Re-run with --all --out <file> to page through everything, or raise --limit above ${cap3} (up to ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE}).`;
|
|
12609
12733
|
return [
|
|
12610
12734
|
{
|
|
12611
12735
|
code: "TRUNCATED_RESULTS",
|
|
@@ -12939,9 +13063,35 @@ async function executeQuery(finalQuery, args5, customerId, limit, warnings, useC
|
|
|
12939
13063
|
function shouldReadCache(args5) {
|
|
12940
13064
|
return !args5["no-cache"] && !args5.out;
|
|
12941
13065
|
}
|
|
13066
|
+
var DEFAULT_QUERY_LIMIT = 200;
|
|
13067
|
+
function parseQueryLimit(raw) {
|
|
13068
|
+
if (raw === void 0 || raw === null || raw === "") return { ok: true, limit: DEFAULT_QUERY_LIMIT };
|
|
13069
|
+
const limit = Number(raw);
|
|
13070
|
+
if (Number.isInteger(limit) && limit >= 1 && limit <= GOOGLE_ADS_QUERY_MAX_PAGE_SIZE) return { ok: true, limit };
|
|
13071
|
+
return {
|
|
13072
|
+
ok: false,
|
|
13073
|
+
error: {
|
|
13074
|
+
ok: false,
|
|
13075
|
+
error: {
|
|
13076
|
+
code: "VALIDATION_ERROR",
|
|
13077
|
+
message: `--limit must be a whole number from 1 to ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE}, got '${String(raw)}'.`,
|
|
13078
|
+
fix: {
|
|
13079
|
+
action: "retry_with_flag",
|
|
13080
|
+
explanation: `One read returns at most ${GOOGLE_ADS_QUERY_MAX_PAGE_SIZE} rows. For more, split the read into narrower queries (a shorter BETWEEN range each, or one campaign each), write each with --out, and combine the files.`
|
|
13081
|
+
},
|
|
13082
|
+
retryable: false
|
|
13083
|
+
}
|
|
13084
|
+
}
|
|
13085
|
+
};
|
|
13086
|
+
}
|
|
12942
13087
|
async function validateArgs(args5) {
|
|
13088
|
+
const parsedLimit = parseQueryLimit(args5.limit);
|
|
13089
|
+
if (!parsedLimit.ok) {
|
|
13090
|
+
writeAdsJson(parsedLimit.error);
|
|
13091
|
+
process.exit(1);
|
|
13092
|
+
}
|
|
13093
|
+
const { limit } = parsedLimit;
|
|
12943
13094
|
const customerId = await resolveCustomerId(args5);
|
|
12944
|
-
const limit = args5.limit ? Number(args5.limit) : 200;
|
|
12945
13095
|
const gaql = resolveGaql(args5, limit);
|
|
12946
13096
|
if (!gaql) {
|
|
12947
13097
|
process.exit(1);
|
|
@@ -35368,15 +35518,38 @@ import { defineCommand as defineCommand119 } from "citty";
|
|
|
35368
35518
|
|
|
35369
35519
|
// src/commands/canvas/catalog.ts
|
|
35370
35520
|
import { defineCommand as defineCommand108 } from "citty";
|
|
35371
|
-
var
|
|
35372
|
-
|
|
35373
|
-
|
|
35374
|
-
|
|
35521
|
+
var DESCRIPTION = "The canvas node catalog. Start here: `baker canvas catalog` lists every node by category with one line each (a few KB). Then `--node video_generate` prints that node's full JSON Schema \u2014 params, inputs, outputs, models, when to use it. `--category image` narrows the list; add `--full` for that category's schemas. `--full` alone prints every schema (~160 KB) \u2014 prefer `--node`.";
|
|
35522
|
+
var ARGS = {
|
|
35523
|
+
node: {
|
|
35524
|
+
type: "string",
|
|
35525
|
+
required: false,
|
|
35526
|
+
description: "Node id(s) whose full schema to print, comma-separated. Example: --node video_generate,tts"
|
|
35375
35527
|
},
|
|
35376
|
-
|
|
35377
|
-
|
|
35378
|
-
|
|
35528
|
+
category: {
|
|
35529
|
+
type: "string",
|
|
35530
|
+
required: false,
|
|
35531
|
+
description: "Only this category (audio, video, image, \u2026). Listed with one line per node unless --full."
|
|
35532
|
+
},
|
|
35533
|
+
full: {
|
|
35534
|
+
type: "boolean",
|
|
35535
|
+
required: false,
|
|
35536
|
+
default: false,
|
|
35537
|
+
description: "Print full JSON Schemas instead of the one-line index (every node, or the --category)."
|
|
35538
|
+
}
|
|
35539
|
+
};
|
|
35540
|
+
registerSchema({ command: "canvas.catalog", description: DESCRIPTION, args: ARGS });
|
|
35541
|
+
var catalogCommand = defineCommand108({
|
|
35542
|
+
meta: { name: "catalog", description: DESCRIPTION },
|
|
35543
|
+
args: ARGS,
|
|
35544
|
+
async run({ args: args5 }) {
|
|
35545
|
+
const view = catalogView(generateCatalog(defaultRegistry()), {
|
|
35546
|
+
node: typeof args5.node === "string" ? args5.node : void 0,
|
|
35547
|
+
category: typeof args5.category === "string" ? args5.category : void 0,
|
|
35548
|
+
full: args5.full === true
|
|
35549
|
+
});
|
|
35550
|
+
process.stdout.write(`${JSON.stringify(view, null, 2)}
|
|
35379
35551
|
`);
|
|
35552
|
+
if (!view.ok) process.exit(1);
|
|
35380
35553
|
}
|
|
35381
35554
|
});
|
|
35382
35555
|
|
|
@@ -44344,7 +44517,7 @@ Subcommands:
|
|
|
44344
44517
|
baker canvas run <file.json> \u2014 execute the canvas, write outputs to ./canvas/<run_id>/
|
|
44345
44518
|
baker canvas rerun <slug> \u2014 restore a creative's latest recorded canvas from run history and run it (works in a fresh workspace)
|
|
44346
44519
|
baker canvas sync-definition <path> \u2014 push a creative's current node-graph + input thumbnails to the dashboard without rendering (runs automatically on canvas/prompt edits)
|
|
44347
|
-
baker canvas catalog \u2014
|
|
44520
|
+
baker canvas catalog \u2014 one line per node; --node <id> for its full schema
|
|
44348
44521
|
baker canvas inspect <run_id> \u2014 one-page summary of a completed run
|
|
44349
44522
|
baker canvas scaffold-ad --spec <spec.json> \u2014 DEFAULT for a new ad: write beats (one spoken line + one shot each), get the whole runnable canvas
|
|
44350
44523
|
baker canvas scaffold-video <video> \u2014 reproduce a video the USER gave you (an ad you found is inspiration, not a copy target)
|
|
@@ -63680,10 +63853,10 @@ var getCommand5 = defineCommand208({
|
|
|
63680
63853
|
|
|
63681
63854
|
// src/commands/studio/improve.ts
|
|
63682
63855
|
import { defineCommand as defineCommand209 } from "citty";
|
|
63683
|
-
var
|
|
63856
|
+
var DESCRIPTION2 = "Sharpen a rough brief into directed art direction \u2014 the same rewrite the client gets from the wand in the Studio prompt bar. Reach for it when you are relaying the CLIENT's own words and want them shaped without substituting your voice; when you are writing the art direction yourself, just write it, because you will do a better job than this does.";
|
|
63684
63857
|
registerSchema({
|
|
63685
63858
|
command: "studio.improve",
|
|
63686
|
-
description:
|
|
63859
|
+
description: DESCRIPTION2,
|
|
63687
63860
|
args: {
|
|
63688
63861
|
prompt: { type: "string", description: "The rough brief to sharpen", required: true },
|
|
63689
63862
|
kind: {
|
|
@@ -63707,7 +63880,7 @@ registerSchema({
|
|
|
63707
63880
|
var improveCommand = defineCommand209({
|
|
63708
63881
|
meta: {
|
|
63709
63882
|
name: "improve",
|
|
63710
|
-
description: `${
|
|
63883
|
+
description: `${DESCRIPTION2}
|
|
63711
63884
|
|
|
63712
63885
|
Both the rewrite and the original come back, so you can show the client what changed rather than silently replacing their words. Nothing is generated \u2014 feed the result to \`baker studio generate\` yourself.
|
|
63713
63886
|
|
|
@@ -63855,10 +64028,10 @@ var listCommand18 = defineCommand211({
|
|
|
63855
64028
|
|
|
63856
64029
|
// src/commands/studio/models.ts
|
|
63857
64030
|
import { defineCommand as defineCommand212 } from "citty";
|
|
63858
|
-
var
|
|
64031
|
+
var DESCRIPTION3 = "What each Studio model actually accepts: its shapes, resolutions, clip lengths, prompt character cap, how many reference images it takes, and which knobs it has. Read this before a batch you care about \u2014 the models disagree far more than they look like they do, and a setting the chosen model does not have is REFUSED, not ignored.";
|
|
63859
64032
|
registerSchema({
|
|
63860
64033
|
command: "studio.models",
|
|
63861
|
-
description:
|
|
64034
|
+
description: DESCRIPTION3,
|
|
63862
64035
|
args: {
|
|
63863
64036
|
kind: {
|
|
63864
64037
|
type: "string",
|
|
@@ -63944,7 +64117,7 @@ function buildModelCards(kind, model) {
|
|
|
63944
64117
|
var modelsCommand = defineCommand212({
|
|
63945
64118
|
meta: {
|
|
63946
64119
|
name: "models",
|
|
63947
|
-
description: `${
|
|
64120
|
+
description: `${DESCRIPTION3}
|
|
63948
64121
|
|
|
63949
64122
|
Everything here is read from the same table the backend validates against, so it cannot drift from what a request will actually be allowed to do.
|
|
63950
64123
|
|