@koda-sl/baker-cli 0.122.0 → 0.122.1-dev.57a9836c5
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 +39 -25
- package/dist/{chunk-IWPAXJC3.js → chunk-T6HBTZOO.js} +339 -76
- package/dist/chunk-T6HBTZOO.js.map +1 -0
- package/dist/cli.js +1391 -1141
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +58 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-IWPAXJC3.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
BackendClient,
|
|
3
4
|
ELEVENLABS_MAX_MUSIC_LENGTH_MS,
|
|
4
5
|
IMAGE_GENERATE_MODELS,
|
|
5
6
|
LayerExecutionError,
|
|
6
7
|
MODEL_REGISTRY,
|
|
7
8
|
SEEDANCE_DURATIONS,
|
|
8
9
|
ValidationError,
|
|
10
|
+
collectAssetRefLikes,
|
|
9
11
|
createEngineFromEnv,
|
|
10
12
|
defaultRegistry,
|
|
11
13
|
describeFailureReason,
|
|
12
14
|
elementMentionKeywords,
|
|
13
15
|
generateCatalog,
|
|
16
|
+
isPersistedAssetRef,
|
|
17
|
+
requireCredentialsFromEnv,
|
|
14
18
|
resolveConcurrency,
|
|
19
|
+
sha256Hex,
|
|
20
|
+
toModelSafeImage,
|
|
21
|
+
ulid,
|
|
15
22
|
validateCanvasDeep
|
|
16
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-T6HBTZOO.js";
|
|
17
24
|
import {
|
|
18
25
|
csvOrJson,
|
|
19
26
|
daysAgoIso,
|
|
@@ -49,7 +56,7 @@ import {
|
|
|
49
56
|
import "./chunk-5WRI5ZAA.js";
|
|
50
57
|
|
|
51
58
|
// src/cli.ts
|
|
52
|
-
import { defineCommand as
|
|
59
|
+
import { defineCommand as defineCommand160, runMain } from "citty";
|
|
53
60
|
|
|
54
61
|
// src/commands/actions/index.ts
|
|
55
62
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -848,6 +855,7 @@ var LINKEDIN_LIMITS = {
|
|
|
848
855
|
choiceOptionsMax: 30,
|
|
849
856
|
choiceOptionTextMax: 100,
|
|
850
857
|
thankYouMessageMax: 300,
|
|
858
|
+
privacyPolicyTextMax: 2e3,
|
|
851
859
|
legalDisclaimerMax: 2e3,
|
|
852
860
|
consentsMax: 5,
|
|
853
861
|
// Campaign Manager caps disclosure checkboxes at 5
|
|
@@ -1442,6 +1450,7 @@ var leadFormFields = {
|
|
|
1442
1450
|
/** Form language, e.g. { country: "US", language: "en" }. Defaults to the account locale on LinkedIn. */
|
|
1443
1451
|
locale: z2.object({ country: z2.string().length(2), language: z2.string().length(2) }).optional(),
|
|
1444
1452
|
privacyPolicyUrl: httpsUrlSchema,
|
|
1453
|
+
privacyPolicyText: z2.string().max(LEAD.privacyPolicyTextMax).optional(),
|
|
1445
1454
|
questions: z2.array(leadFormQuestionSchema).min(1).max(LEAD.questionsMax),
|
|
1446
1455
|
consents: z2.array(leadFormConsentSchema).max(LEAD.consentsMax).optional(),
|
|
1447
1456
|
hiddenFields: z2.array(leadFormHiddenFieldSchema).max(LEAD.hiddenFieldsMax).optional(),
|
|
@@ -1916,261 +1925,142 @@ var imagesIngestResponseSchema = z4.object({
|
|
|
1916
1925
|
contentHash: z4.string()
|
|
1917
1926
|
});
|
|
1918
1927
|
|
|
1919
|
-
// ../api/src/tags.ts
|
|
1920
|
-
import { z as z5 } from "zod";
|
|
1921
|
-
var TAG_TYPES = [
|
|
1922
|
-
"meta",
|
|
1923
|
-
"amplitude",
|
|
1924
|
-
"googleAds",
|
|
1925
|
-
"tiktok",
|
|
1926
|
-
"vwo",
|
|
1927
|
-
"hotjar",
|
|
1928
|
-
"clarity",
|
|
1929
|
-
"pinterest",
|
|
1930
|
-
"code",
|
|
1931
|
-
"googleAnalytics",
|
|
1932
|
-
"googleTagManager",
|
|
1933
|
-
"hubspot",
|
|
1934
|
-
"linkedinInsightTag",
|
|
1935
|
-
"onetrust",
|
|
1936
|
-
"posthog",
|
|
1937
|
-
"datafast",
|
|
1938
|
-
"recaptcha",
|
|
1939
|
-
"twitterAds"
|
|
1940
|
-
];
|
|
1941
|
-
var tagTypeSchema = z5.enum(TAG_TYPES);
|
|
1942
|
-
var TAG_IDENTIFYING_FIELD = {
|
|
1943
|
-
meta: "pixelId",
|
|
1944
|
-
googleAds: "conversionID",
|
|
1945
|
-
tiktok: "pixelCode",
|
|
1946
|
-
pinterest: "tagId",
|
|
1947
|
-
linkedinInsightTag: "partnerId",
|
|
1948
|
-
googleAnalytics: "measurementId",
|
|
1949
|
-
googleTagManager: "containerID",
|
|
1950
|
-
amplitude: "apiKey",
|
|
1951
|
-
hotjar: "siteID",
|
|
1952
|
-
clarity: "projectId",
|
|
1953
|
-
hubspot: "hubID",
|
|
1954
|
-
vwo: "accountId",
|
|
1955
|
-
code: null,
|
|
1956
|
-
onetrust: "domainId",
|
|
1957
|
-
posthog: "projectToken",
|
|
1958
|
-
datafast: "websiteId",
|
|
1959
|
-
recaptcha: "siteKey",
|
|
1960
|
-
twitterAds: "pixelId"
|
|
1961
|
-
};
|
|
1962
|
-
var tagDraftOpKindSchema = z5.enum(["create", "update", "delete"]);
|
|
1963
|
-
var tagDraftOpViewSchema = z5.object({
|
|
1964
|
-
/** `tag_temp_*` for staged creates; the real tag id for update/delete ops. */
|
|
1965
|
-
ref: z5.string(),
|
|
1966
|
-
kind: tagDraftOpKindSchema,
|
|
1967
|
-
type: tagTypeSchema,
|
|
1968
|
-
/** Present on update/delete ops — the real tag this op targets. */
|
|
1969
|
-
tagId: z5.string().optional(),
|
|
1970
|
-
/** Non-secret config (create: full; update: the staged patch). Secrets are structurally absent. */
|
|
1971
|
-
config: z5.record(z5.string(), z5.string()),
|
|
1972
|
-
/** Update only — fields the op explicitly clears. */
|
|
1973
|
-
clearFields: z5.array(z5.string()).optional(),
|
|
1974
|
-
/** Names of secret fields already provided via the dashboard secure form. Never values. */
|
|
1975
|
-
secretsSet: z5.array(z5.string()),
|
|
1976
|
-
/** Names of secret fields still awaiting user input. */
|
|
1977
|
-
secretsPending: z5.array(z5.string()),
|
|
1978
|
-
summary: z5.string(),
|
|
1979
|
-
stagedAt: z5.number()
|
|
1980
|
-
});
|
|
1981
|
-
var tagsEffectiveEntrySchema = z5.object({
|
|
1982
|
-
/** Real tag id, or `tag_temp_*` for staged creates. Use as flow side-effect `tagIds` value. */
|
|
1983
|
-
ref: z5.string(),
|
|
1984
|
-
tagId: z5.string().optional(),
|
|
1985
|
-
type: tagTypeSchema,
|
|
1986
|
-
/** Value of the type's identifying field, when set. */
|
|
1987
|
-
identifier: z5.string().optional(),
|
|
1988
|
-
/** Redacted config; for staged updates, production config with the patch merged. */
|
|
1989
|
-
config: z5.record(z5.string(), z5.string()),
|
|
1990
|
-
/** Absent = live production tag with no staged changes in this chat. */
|
|
1991
|
-
staged: tagDraftOpKindSchema.optional(),
|
|
1992
|
-
secretsSet: z5.array(z5.string()),
|
|
1993
|
-
secretsPending: z5.array(z5.string())
|
|
1994
|
-
});
|
|
1995
|
-
var tagsListRequestSchema = z5.object({ chatId: z5.string() });
|
|
1996
|
-
var tagsListResponseSchema = z5.object({ tags: z5.array(tagsEffectiveEntrySchema) });
|
|
1997
|
-
var tagsDraftListRequestSchema = z5.object({ chatId: z5.string() });
|
|
1998
|
-
var tagsDraftListResponseSchema = z5.object({
|
|
1999
|
-
status: z5.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
2000
|
-
ops: z5.array(tagDraftOpViewSchema)
|
|
2001
|
-
});
|
|
2002
|
-
var tagInputRequestSchema = z5.object({
|
|
2003
|
-
// Every tag change is a tab in the approval form: create/edit show the full
|
|
2004
|
-
// body; delete shows a confirm. No tag change bypasses this approval.
|
|
2005
|
-
mode: z5.enum(["create", "edit", "delete"]),
|
|
2006
|
-
tagType: tagTypeSchema,
|
|
2007
|
-
/** Edit/delete mode — the real tag id or `tag_temp_*` ref being changed. */
|
|
2008
|
-
ref: z5.string().optional(),
|
|
2009
|
-
/** Non-secret values the agent proposes to prefill. Secret keys are stripped at every boundary. */
|
|
2010
|
-
prefilledConfig: z5.record(z5.string(), z5.string()).optional(),
|
|
2011
|
-
/** Secret field names the agent asks the user to provide. */
|
|
2012
|
-
requestedSecretFields: z5.array(z5.string()).optional(),
|
|
2013
|
-
/** Short message shown above the form explaining why the input is needed. */
|
|
2014
|
-
message: z5.string().optional()
|
|
2015
|
-
});
|
|
2016
|
-
var tagChangeToolInputSchema = z5.object({
|
|
2017
|
-
changes: z5.array(tagInputRequestSchema).min(1).max(8)
|
|
2018
|
-
});
|
|
2019
|
-
var tagInputResultSchema = z5.discriminatedUnion("status", [
|
|
2020
|
-
z5.object({
|
|
2021
|
-
status: z5.literal("submitted"),
|
|
2022
|
-
ref: z5.string(),
|
|
2023
|
-
type: tagTypeSchema,
|
|
2024
|
-
/** Identifying field name → value (non-secret), when the type has one. */
|
|
2025
|
-
identifier: z5.record(z5.string(), z5.string()).optional(),
|
|
2026
|
-
secretFieldsSet: z5.array(z5.string()),
|
|
2027
|
-
note: z5.string().optional()
|
|
2028
|
-
}),
|
|
2029
|
-
z5.object({
|
|
2030
|
-
status: z5.literal("declined"),
|
|
2031
|
-
reason: z5.string().optional()
|
|
2032
|
-
})
|
|
2033
|
-
]);
|
|
2034
|
-
var tagChangeToolResultSchema = z5.object({
|
|
2035
|
-
results: z5.array(tagInputResultSchema)
|
|
2036
|
-
});
|
|
2037
|
-
|
|
2038
1928
|
// ../api/src/testimonials.ts
|
|
2039
|
-
import { z as
|
|
2040
|
-
var testimonialSourceTypeSchema =
|
|
2041
|
-
var testimonialStatusSchema =
|
|
2042
|
-
var testimonialSentimentSchema =
|
|
2043
|
-
var testimonialDocSchema =
|
|
2044
|
-
_id:
|
|
2045
|
-
_creationTime:
|
|
2046
|
-
companyId:
|
|
2047
|
-
sourceId:
|
|
1929
|
+
import { z as z5 } from "zod";
|
|
1930
|
+
var testimonialSourceTypeSchema = z5.enum(["google", "trustpilot"]);
|
|
1931
|
+
var testimonialStatusSchema = z5.enum(["pending", "processing", "ready", "error"]);
|
|
1932
|
+
var testimonialSentimentSchema = z5.enum(["positive", "neutral", "negative"]);
|
|
1933
|
+
var testimonialDocSchema = z5.object({
|
|
1934
|
+
_id: z5.string(),
|
|
1935
|
+
_creationTime: z5.number(),
|
|
1936
|
+
companyId: z5.string(),
|
|
1937
|
+
sourceId: z5.string(),
|
|
2048
1938
|
sourceType: testimonialSourceTypeSchema,
|
|
2049
|
-
reviewText:
|
|
2050
|
-
reviewTitle:
|
|
2051
|
-
searchText:
|
|
2052
|
-
reviewerName:
|
|
2053
|
-
reviewerImageUrl:
|
|
2054
|
-
reviewerImageId:
|
|
2055
|
-
reviewerLocation:
|
|
2056
|
-
rating:
|
|
2057
|
-
reviewDate:
|
|
2058
|
-
ownerAnswer:
|
|
2059
|
-
mediaUrls:
|
|
2060
|
-
imageIds:
|
|
2061
|
-
videoIds:
|
|
2062
|
-
sourceUrl:
|
|
2063
|
-
rawData:
|
|
2064
|
-
tags:
|
|
2065
|
-
highlight:
|
|
2066
|
-
language:
|
|
2067
|
-
summary:
|
|
1939
|
+
reviewText: z5.string(),
|
|
1940
|
+
reviewTitle: z5.string().optional(),
|
|
1941
|
+
searchText: z5.string().optional(),
|
|
1942
|
+
reviewerName: z5.string().optional(),
|
|
1943
|
+
reviewerImageUrl: z5.string().optional(),
|
|
1944
|
+
reviewerImageId: z5.string().optional(),
|
|
1945
|
+
reviewerLocation: z5.string().optional(),
|
|
1946
|
+
rating: z5.number().optional(),
|
|
1947
|
+
reviewDate: z5.number().optional(),
|
|
1948
|
+
ownerAnswer: z5.string().optional(),
|
|
1949
|
+
mediaUrls: z5.array(z5.string()).optional(),
|
|
1950
|
+
imageIds: z5.array(z5.string()).optional(),
|
|
1951
|
+
videoIds: z5.array(z5.string()).optional(),
|
|
1952
|
+
sourceUrl: z5.string().optional(),
|
|
1953
|
+
rawData: z5.unknown().optional(),
|
|
1954
|
+
tags: z5.array(z5.string()),
|
|
1955
|
+
highlight: z5.string().optional(),
|
|
1956
|
+
language: z5.string().optional(),
|
|
1957
|
+
summary: z5.string().optional(),
|
|
2068
1958
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2069
|
-
textEmbedding:
|
|
2070
|
-
externalId:
|
|
2071
|
-
contentHash:
|
|
1959
|
+
textEmbedding: z5.array(z5.number()).optional(),
|
|
1960
|
+
externalId: z5.string().optional(),
|
|
1961
|
+
contentHash: z5.string().optional(),
|
|
2072
1962
|
status: testimonialStatusSchema,
|
|
2073
|
-
errorMessage:
|
|
2074
|
-
createdAt:
|
|
2075
|
-
updatedAt:
|
|
1963
|
+
errorMessage: z5.string().optional(),
|
|
1964
|
+
createdAt: z5.number(),
|
|
1965
|
+
updatedAt: z5.number()
|
|
2076
1966
|
});
|
|
2077
|
-
var testimonialsListRequestSchema =
|
|
1967
|
+
var testimonialsListRequestSchema = z5.object({
|
|
2078
1968
|
source: testimonialSourceTypeSchema.optional(),
|
|
2079
|
-
rating_min:
|
|
2080
|
-
rating_max:
|
|
2081
|
-
tags:
|
|
1969
|
+
rating_min: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1970
|
+
rating_max: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1971
|
+
tags: z5.string().transform((s) => s.split(",").filter(Boolean)).optional(),
|
|
2082
1972
|
status: testimonialStatusSchema.optional(),
|
|
2083
1973
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2084
|
-
language:
|
|
2085
|
-
limit:
|
|
2086
|
-
});
|
|
2087
|
-
var testimonialsListResponseSchema =
|
|
2088
|
-
var testimonialsGetRequestSchema =
|
|
2089
|
-
var testimonialsSearchRequestSchema =
|
|
2090
|
-
query:
|
|
2091
|
-
limit:
|
|
1974
|
+
language: z5.string().min(2).max(5).optional(),
|
|
1975
|
+
limit: z5.coerce.number().int().positive().max(200).optional()
|
|
1976
|
+
});
|
|
1977
|
+
var testimonialsListResponseSchema = z5.array(testimonialDocSchema);
|
|
1978
|
+
var testimonialsGetRequestSchema = z5.object({ id: z5.string().min(1, "Missing id parameter") });
|
|
1979
|
+
var testimonialsSearchRequestSchema = z5.object({
|
|
1980
|
+
query: z5.string().min(1),
|
|
1981
|
+
limit: z5.coerce.number().int().positive().max(100).optional(),
|
|
2092
1982
|
source: testimonialSourceTypeSchema.optional(),
|
|
2093
|
-
rating_min:
|
|
2094
|
-
rating_max:
|
|
2095
|
-
tags:
|
|
1983
|
+
rating_min: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1984
|
+
rating_max: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1985
|
+
tags: z5.array(z5.string()).optional(),
|
|
2096
1986
|
status: testimonialStatusSchema.optional(),
|
|
2097
1987
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2098
|
-
language:
|
|
1988
|
+
language: z5.string().min(2).max(5).optional()
|
|
2099
1989
|
}).refine(
|
|
2100
1990
|
(data) => data.rating_min === void 0 || data.rating_max === void 0 || data.rating_min <= data.rating_max,
|
|
2101
1991
|
{ message: "rating_min must be less than or equal to rating_max" }
|
|
2102
1992
|
);
|
|
2103
|
-
var testimonialsSearchResponseSchema =
|
|
2104
|
-
var testimonialsOutscraperWebhookResponseSchema =
|
|
2105
|
-
ok:
|
|
2106
|
-
note:
|
|
1993
|
+
var testimonialsSearchResponseSchema = z5.array(testimonialDocSchema);
|
|
1994
|
+
var testimonialsOutscraperWebhookResponseSchema = z5.object({
|
|
1995
|
+
ok: z5.literal(true),
|
|
1996
|
+
note: z5.string().optional()
|
|
2107
1997
|
});
|
|
2108
1998
|
|
|
2109
1999
|
// ../api/src/videos.ts
|
|
2110
|
-
import { z as
|
|
2111
|
-
var videoStatusSchema =
|
|
2112
|
-
var videoTranscriptSegmentSchema =
|
|
2113
|
-
text:
|
|
2114
|
-
startSecond:
|
|
2115
|
-
endSecond:
|
|
2116
|
-
});
|
|
2117
|
-
var videoSceneSchema =
|
|
2118
|
-
title:
|
|
2119
|
-
description:
|
|
2120
|
-
startSecond:
|
|
2121
|
-
endSecond:
|
|
2122
|
-
thumbnailTime:
|
|
2123
|
-
});
|
|
2124
|
-
var videoDocSchema =
|
|
2125
|
-
_id:
|
|
2126
|
-
_creationTime:
|
|
2127
|
-
companyId:
|
|
2128
|
-
muxAssetId:
|
|
2129
|
-
muxPlaybackId:
|
|
2130
|
-
muxUploadId:
|
|
2131
|
-
name:
|
|
2132
|
-
description:
|
|
2133
|
-
tags:
|
|
2134
|
-
source:
|
|
2135
|
-
externalId:
|
|
2136
|
-
sourceId:
|
|
2137
|
-
width:
|
|
2138
|
-
height:
|
|
2139
|
-
aspectRatio:
|
|
2140
|
-
duration:
|
|
2141
|
-
transcript:
|
|
2142
|
-
transcriptSegments:
|
|
2143
|
-
scenes:
|
|
2144
|
-
descriptionEmbedding:
|
|
2145
|
-
searchText:
|
|
2000
|
+
import { z as z6 } from "zod";
|
|
2001
|
+
var videoStatusSchema = z6.enum(["uploading", "uploaded", "processing", "ready", "error"]);
|
|
2002
|
+
var videoTranscriptSegmentSchema = z6.object({
|
|
2003
|
+
text: z6.string(),
|
|
2004
|
+
startSecond: z6.number(),
|
|
2005
|
+
endSecond: z6.number()
|
|
2006
|
+
});
|
|
2007
|
+
var videoSceneSchema = z6.object({
|
|
2008
|
+
title: z6.string(),
|
|
2009
|
+
description: z6.string(),
|
|
2010
|
+
startSecond: z6.number(),
|
|
2011
|
+
endSecond: z6.number(),
|
|
2012
|
+
thumbnailTime: z6.number()
|
|
2013
|
+
});
|
|
2014
|
+
var videoDocSchema = z6.object({
|
|
2015
|
+
_id: z6.string(),
|
|
2016
|
+
_creationTime: z6.number(),
|
|
2017
|
+
companyId: z6.string(),
|
|
2018
|
+
muxAssetId: z6.string(),
|
|
2019
|
+
muxPlaybackId: z6.string(),
|
|
2020
|
+
muxUploadId: z6.string(),
|
|
2021
|
+
name: z6.string(),
|
|
2022
|
+
description: z6.string(),
|
|
2023
|
+
tags: z6.array(z6.string()),
|
|
2024
|
+
source: z6.string(),
|
|
2025
|
+
externalId: z6.string().optional(),
|
|
2026
|
+
sourceId: z6.string().optional(),
|
|
2027
|
+
width: z6.number().optional(),
|
|
2028
|
+
height: z6.number().optional(),
|
|
2029
|
+
aspectRatio: z6.number().optional(),
|
|
2030
|
+
duration: z6.number().optional(),
|
|
2031
|
+
transcript: z6.string().optional(),
|
|
2032
|
+
transcriptSegments: z6.array(videoTranscriptSegmentSchema).optional(),
|
|
2033
|
+
scenes: z6.array(videoSceneSchema).optional(),
|
|
2034
|
+
descriptionEmbedding: z6.array(z6.number()).optional(),
|
|
2035
|
+
searchText: z6.string().optional(),
|
|
2146
2036
|
status: videoStatusSchema,
|
|
2147
|
-
errorMessage:
|
|
2148
|
-
createdAt:
|
|
2149
|
-
updatedAt:
|
|
2150
|
-
thumbnailUrl:
|
|
2151
|
-
});
|
|
2152
|
-
var videosWebhookResponseSchema =
|
|
2153
|
-
var videosGetRequestSchema =
|
|
2154
|
-
var videosSearchRequestSchema =
|
|
2155
|
-
query:
|
|
2156
|
-
limit:
|
|
2157
|
-
tags:
|
|
2158
|
-
});
|
|
2159
|
-
var videoSearchResultSchema =
|
|
2160
|
-
_id:
|
|
2161
|
-
thumbnailUrl:
|
|
2162
|
-
name:
|
|
2163
|
-
description:
|
|
2164
|
-
tags:
|
|
2165
|
-
status:
|
|
2166
|
-
duration:
|
|
2167
|
-
muxPlaybackId:
|
|
2168
|
-
createdAt:
|
|
2169
|
-
});
|
|
2170
|
-
var videosSearchResponseSchema =
|
|
2171
|
-
var videosUploadResponseSchema =
|
|
2172
|
-
var videosDeleteRequestSchema =
|
|
2173
|
-
var videosDeleteResponseSchema =
|
|
2037
|
+
errorMessage: z6.string().optional(),
|
|
2038
|
+
createdAt: z6.number(),
|
|
2039
|
+
updatedAt: z6.number(),
|
|
2040
|
+
thumbnailUrl: z6.string()
|
|
2041
|
+
});
|
|
2042
|
+
var videosWebhookResponseSchema = z6.object({ ok: z6.literal(true) });
|
|
2043
|
+
var videosGetRequestSchema = z6.object({ id: z6.string().min(1, "Missing id parameter") });
|
|
2044
|
+
var videosSearchRequestSchema = z6.object({
|
|
2045
|
+
query: z6.string().min(1),
|
|
2046
|
+
limit: z6.coerce.number().int().positive().max(100).optional(),
|
|
2047
|
+
tags: z6.array(z6.string()).optional()
|
|
2048
|
+
});
|
|
2049
|
+
var videoSearchResultSchema = z6.object({
|
|
2050
|
+
_id: z6.string(),
|
|
2051
|
+
thumbnailUrl: z6.string(),
|
|
2052
|
+
name: z6.string(),
|
|
2053
|
+
description: z6.string(),
|
|
2054
|
+
tags: z6.array(z6.string()),
|
|
2055
|
+
status: z6.string(),
|
|
2056
|
+
duration: z6.number().optional(),
|
|
2057
|
+
muxPlaybackId: z6.string(),
|
|
2058
|
+
createdAt: z6.number()
|
|
2059
|
+
});
|
|
2060
|
+
var videosSearchResponseSchema = z6.array(videoSearchResultSchema);
|
|
2061
|
+
var videosUploadResponseSchema = z6.object({ uploadUrl: z6.string(), videoId: z6.string() });
|
|
2062
|
+
var videosDeleteRequestSchema = z6.object({ id: z6.string().min(1, "Missing video ID") });
|
|
2063
|
+
var videosDeleteResponseSchema = z6.object({ ok: z6.literal(true) });
|
|
2174
2064
|
|
|
2175
2065
|
// src/commands/actions/complete.ts
|
|
2176
2066
|
import { defineCommand as defineCommand2 } from "citty";
|
|
@@ -3983,37 +3873,37 @@ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
|
|
|
3983
3873
|
var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
|
|
3984
3874
|
|
|
3985
3875
|
// ../api/src/ads-google/ops.ts
|
|
3986
|
-
import { z as
|
|
3987
|
-
var tempRefSchema2 =
|
|
3988
|
-
var refSchema =
|
|
3989
|
-
|
|
3990
|
-
|
|
3876
|
+
import { z as z7 } from "zod";
|
|
3877
|
+
var tempRefSchema2 = z7.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
|
|
3878
|
+
var refSchema = z7.union([
|
|
3879
|
+
z7.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
|
|
3880
|
+
z7.string().regex(NUMERIC_ID_REGEX2, "expected a numeric id"),
|
|
3991
3881
|
tempRefSchema2
|
|
3992
3882
|
]);
|
|
3993
3883
|
var targetRefSchema = refSchema;
|
|
3994
|
-
var microsSchema =
|
|
3995
|
-
var httpsUrlSchema2 =
|
|
3996
|
-
var customerIdSchema =
|
|
3997
|
-
var stageableStatusSchema2 =
|
|
3998
|
-
var matchTypeSchema =
|
|
3999
|
-
var keywordTextSchema =
|
|
4000
|
-
var budgetCreateSchema =
|
|
4001
|
-
name:
|
|
3884
|
+
var microsSchema = z7.number().int().positive("expected a positive micros amount");
|
|
3885
|
+
var httpsUrlSchema2 = z7.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
|
|
3886
|
+
var customerIdSchema = z7.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
|
|
3887
|
+
var stageableStatusSchema2 = z7.enum(STAGEABLE_CREATE_STATUSES2);
|
|
3888
|
+
var matchTypeSchema = z7.enum(KEYWORD_MATCH_TYPES);
|
|
3889
|
+
var keywordTextSchema = z7.string().min(1).max(GOOGLE_ADS_LIMITS.keyword.textMax).refine((t) => t.trim().split(/\s+/).length <= GOOGLE_ADS_LIMITS.keyword.wordsMax, "keyword exceeds 10 words");
|
|
3890
|
+
var budgetCreateSchema = z7.object({
|
|
3891
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax),
|
|
4002
3892
|
amountMicros: microsSchema,
|
|
4003
|
-
deliveryMethod:
|
|
4004
|
-
explicitlyShared:
|
|
3893
|
+
deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
|
|
3894
|
+
explicitlyShared: z7.boolean().default(false)
|
|
4005
3895
|
});
|
|
4006
|
-
var budgetUpdateSchema =
|
|
4007
|
-
name:
|
|
3896
|
+
var budgetUpdateSchema = z7.object({
|
|
3897
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
|
|
4008
3898
|
amountMicros: microsSchema.optional(),
|
|
4009
|
-
deliveryMethod:
|
|
3899
|
+
deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).optional()
|
|
4010
3900
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4011
|
-
var biddingConfigSchema =
|
|
4012
|
-
type:
|
|
3901
|
+
var biddingConfigSchema = z7.object({
|
|
3902
|
+
type: z7.enum(BIDDING_STRATEGY_TYPES),
|
|
4013
3903
|
targetCpaMicros: microsSchema.optional(),
|
|
4014
|
-
targetRoas:
|
|
3904
|
+
targetRoas: z7.number().positive().optional(),
|
|
4015
3905
|
cpcBidCeilingMicros: microsSchema.optional(),
|
|
4016
|
-
enhancedCpcEnabled:
|
|
3906
|
+
enhancedCpcEnabled: z7.boolean().optional()
|
|
4017
3907
|
}).superRefine((p, ctx) => {
|
|
4018
3908
|
if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
|
|
4019
3909
|
ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
|
|
@@ -4022,17 +3912,17 @@ var biddingConfigSchema = z8.object({
|
|
|
4022
3912
|
ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
|
|
4023
3913
|
}
|
|
4024
3914
|
});
|
|
4025
|
-
var networkSettingsSchema =
|
|
4026
|
-
targetGoogleSearch:
|
|
4027
|
-
targetSearchNetwork:
|
|
4028
|
-
targetContentNetwork:
|
|
4029
|
-
targetPartnerSearchNetwork:
|
|
3915
|
+
var networkSettingsSchema = z7.object({
|
|
3916
|
+
targetGoogleSearch: z7.boolean().optional(),
|
|
3917
|
+
targetSearchNetwork: z7.boolean().optional(),
|
|
3918
|
+
targetContentNetwork: z7.boolean().optional(),
|
|
3919
|
+
targetPartnerSearchNetwork: z7.boolean().optional()
|
|
4030
3920
|
});
|
|
4031
|
-
var dateSchema =
|
|
4032
|
-
var campaignCreateSchema2 =
|
|
4033
|
-
name:
|
|
4034
|
-
channelType:
|
|
4035
|
-
channelSubType:
|
|
3921
|
+
var dateSchema = z7.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
|
|
3922
|
+
var campaignCreateSchema2 = z7.object({
|
|
3923
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
|
|
3924
|
+
channelType: z7.enum(ADVERTISING_CHANNEL_TYPES),
|
|
3925
|
+
channelSubType: z7.enum(ADVERTISING_CHANNEL_SUB_TYPES).optional(),
|
|
4036
3926
|
budget: refSchema,
|
|
4037
3927
|
/** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
|
|
4038
3928
|
bidding: biddingConfigSchema.optional(),
|
|
@@ -4041,7 +3931,7 @@ var campaignCreateSchema2 = z8.object({
|
|
|
4041
3931
|
startDate: dateSchema.optional(),
|
|
4042
3932
|
endDate: dateSchema.optional(),
|
|
4043
3933
|
/** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
|
|
4044
|
-
objective:
|
|
3934
|
+
objective: z7.enum(CAMPAIGN_OBJECTIVES).optional(),
|
|
4045
3935
|
status: stageableStatusSchema2.default("PAUSED")
|
|
4046
3936
|
}).superRefine((p, ctx) => {
|
|
4047
3937
|
if (!p.bidding && !p.biddingStrategy) {
|
|
@@ -4065,129 +3955,129 @@ var campaignCreateSchema2 = z8.object({
|
|
|
4065
3955
|
ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
|
|
4066
3956
|
}
|
|
4067
3957
|
});
|
|
4068
|
-
var campaignUpdateSchema2 =
|
|
4069
|
-
name:
|
|
3958
|
+
var campaignUpdateSchema2 = z7.object({
|
|
3959
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
|
|
4070
3960
|
budget: refSchema.optional(),
|
|
4071
3961
|
bidding: biddingConfigSchema.optional(),
|
|
4072
3962
|
networkSettings: networkSettingsSchema.optional(),
|
|
4073
3963
|
startDate: dateSchema.optional(),
|
|
4074
3964
|
endDate: dateSchema.optional(),
|
|
4075
|
-
status:
|
|
3965
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4076
3966
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4077
|
-
var adGroupCreateSchema =
|
|
4078
|
-
name:
|
|
3967
|
+
var adGroupCreateSchema = z7.object({
|
|
3968
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
|
|
4079
3969
|
campaign: refSchema,
|
|
4080
|
-
type:
|
|
3970
|
+
type: z7.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
|
|
4081
3971
|
cpcBidMicros: microsSchema.optional(),
|
|
4082
3972
|
status: stageableStatusSchema2.default("PAUSED")
|
|
4083
3973
|
});
|
|
4084
|
-
var adGroupUpdateSchema =
|
|
4085
|
-
name:
|
|
3974
|
+
var adGroupUpdateSchema = z7.object({
|
|
3975
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
|
|
4086
3976
|
cpcBidMicros: microsSchema.optional(),
|
|
4087
|
-
status:
|
|
3977
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4088
3978
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4089
|
-
var keywordAddSchema =
|
|
3979
|
+
var keywordAddSchema = z7.object({
|
|
4090
3980
|
adGroup: refSchema,
|
|
4091
3981
|
text: keywordTextSchema,
|
|
4092
3982
|
matchType: matchTypeSchema,
|
|
4093
3983
|
cpcBidMicros: microsSchema.optional(),
|
|
4094
|
-
finalUrls:
|
|
3984
|
+
finalUrls: z7.array(httpsUrlSchema2).optional(),
|
|
4095
3985
|
status: stageableStatusSchema2.default("ENABLED")
|
|
4096
3986
|
});
|
|
4097
|
-
var keywordUpdateSchema =
|
|
3987
|
+
var keywordUpdateSchema = z7.object({
|
|
4098
3988
|
cpcBidMicros: microsSchema.optional(),
|
|
4099
|
-
finalUrls:
|
|
4100
|
-
status:
|
|
3989
|
+
finalUrls: z7.array(httpsUrlSchema2).optional(),
|
|
3990
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4101
3991
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4102
|
-
var negativeKeywordAddSchema =
|
|
4103
|
-
level:
|
|
3992
|
+
var negativeKeywordAddSchema = z7.object({
|
|
3993
|
+
level: z7.enum(["adGroup", "campaign"]),
|
|
4104
3994
|
parent: refSchema,
|
|
4105
3995
|
text: keywordTextSchema,
|
|
4106
3996
|
matchType: matchTypeSchema
|
|
4107
3997
|
});
|
|
4108
|
-
var sharedSetCreateSchema =
|
|
4109
|
-
name:
|
|
4110
|
-
type:
|
|
3998
|
+
var sharedSetCreateSchema = z7.object({
|
|
3999
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
|
|
4000
|
+
type: z7.enum(SHARED_SET_TYPES).default("NEGATIVE_KEYWORDS")
|
|
4111
4001
|
});
|
|
4112
|
-
var sharedSetMemberAddSchema =
|
|
4002
|
+
var sharedSetMemberAddSchema = z7.object({
|
|
4113
4003
|
sharedSet: refSchema,
|
|
4114
4004
|
text: keywordTextSchema,
|
|
4115
4005
|
matchType: matchTypeSchema
|
|
4116
4006
|
});
|
|
4117
|
-
var campaignSharedSetAttachSchema =
|
|
4007
|
+
var campaignSharedSetAttachSchema = z7.object({
|
|
4118
4008
|
campaign: refSchema,
|
|
4119
4009
|
sharedSet: refSchema
|
|
4120
4010
|
});
|
|
4121
|
-
var adTextAssetSchema =
|
|
4122
|
-
text:
|
|
4123
|
-
pinnedField:
|
|
4011
|
+
var adTextAssetSchema = z7.object({
|
|
4012
|
+
text: z7.string().min(1),
|
|
4013
|
+
pinnedField: z7.enum(PINNED_FIELDS).optional()
|
|
4124
4014
|
});
|
|
4125
|
-
var responsiveSearchAdSchema =
|
|
4126
|
-
format:
|
|
4127
|
-
headlines:
|
|
4015
|
+
var responsiveSearchAdSchema = z7.object({
|
|
4016
|
+
format: z7.literal("responsiveSearch"),
|
|
4017
|
+
headlines: z7.array(
|
|
4128
4018
|
adTextAssetSchema.refine(
|
|
4129
4019
|
(a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
|
|
4130
4020
|
"headline exceeds 30 chars"
|
|
4131
4021
|
)
|
|
4132
4022
|
).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
|
|
4133
|
-
descriptions:
|
|
4023
|
+
descriptions: z7.array(
|
|
4134
4024
|
adTextAssetSchema.refine(
|
|
4135
4025
|
(a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
|
|
4136
4026
|
"description exceeds 90 chars"
|
|
4137
4027
|
)
|
|
4138
4028
|
).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
|
|
4139
|
-
path1:
|
|
4140
|
-
path2:
|
|
4141
|
-
finalUrls:
|
|
4142
|
-
});
|
|
4143
|
-
var responsiveDisplayAdSchema =
|
|
4144
|
-
format:
|
|
4145
|
-
headlines:
|
|
4146
|
-
longHeadline:
|
|
4147
|
-
descriptions:
|
|
4148
|
-
businessName:
|
|
4029
|
+
path1: z7.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
|
|
4030
|
+
path2: z7.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
|
|
4031
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4032
|
+
});
|
|
4033
|
+
var responsiveDisplayAdSchema = z7.object({
|
|
4034
|
+
format: z7.literal("responsiveDisplay"),
|
|
4035
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
|
|
4036
|
+
longHeadline: z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
|
|
4037
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
|
|
4038
|
+
businessName: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.businessNameMax),
|
|
4149
4039
|
// A Responsive Display Ad's images are fields on the ad's own content (never campaign-level
|
|
4150
4040
|
// asset links). Google requires ≥1 landscape marketing image (1.91:1) AND ≥1 square marketing
|
|
4151
4041
|
// image (1:1) to serve; the logo images are optional.
|
|
4152
|
-
marketingImageAssets:
|
|
4153
|
-
squareMarketingImageAssets:
|
|
4154
|
-
logoImageAssets:
|
|
4155
|
-
finalUrls:
|
|
4156
|
-
});
|
|
4157
|
-
var callAdSchema =
|
|
4158
|
-
format:
|
|
4159
|
-
countryCode:
|
|
4160
|
-
phoneNumber:
|
|
4161
|
-
headline1:
|
|
4162
|
-
headline2:
|
|
4163
|
-
description1:
|
|
4164
|
-
description2:
|
|
4165
|
-
businessName:
|
|
4166
|
-
finalUrls:
|
|
4167
|
-
});
|
|
4168
|
-
var appAdSchema =
|
|
4169
|
-
format:
|
|
4170
|
-
headlines:
|
|
4171
|
-
descriptions:
|
|
4172
|
-
});
|
|
4173
|
-
var videoAdSchema =
|
|
4174
|
-
format:
|
|
4042
|
+
marketingImageAssets: z7.array(refSchema).optional(),
|
|
4043
|
+
squareMarketingImageAssets: z7.array(refSchema).optional(),
|
|
4044
|
+
logoImageAssets: z7.array(refSchema).optional(),
|
|
4045
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4046
|
+
});
|
|
4047
|
+
var callAdSchema = z7.object({
|
|
4048
|
+
format: z7.literal("call"),
|
|
4049
|
+
countryCode: z7.string().length(2),
|
|
4050
|
+
phoneNumber: z7.string().min(3),
|
|
4051
|
+
headline1: z7.string().min(1).max(30),
|
|
4052
|
+
headline2: z7.string().min(1).max(30),
|
|
4053
|
+
description1: z7.string().min(1).max(90),
|
|
4054
|
+
description2: z7.string().min(1).max(90),
|
|
4055
|
+
businessName: z7.string().min(1).max(25),
|
|
4056
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4057
|
+
});
|
|
4058
|
+
var appAdSchema = z7.object({
|
|
4059
|
+
format: z7.literal("app"),
|
|
4060
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(30) })).min(1),
|
|
4061
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(90) })).min(1)
|
|
4062
|
+
});
|
|
4063
|
+
var videoAdSchema = z7.object({
|
|
4064
|
+
format: z7.literal("video"),
|
|
4175
4065
|
// A raw YouTube id is not a publishable Google Ads reference — the video must be staged as
|
|
4176
4066
|
// its own `google.asset.create` (type: youtubeVideo) first, then referenced here by asset ref.
|
|
4177
|
-
videoAssets:
|
|
4178
|
-
finalUrls:
|
|
4179
|
-
});
|
|
4180
|
-
var demandGenAdSchema =
|
|
4181
|
-
format:
|
|
4182
|
-
headlines:
|
|
4183
|
-
descriptions:
|
|
4184
|
-
businessName:
|
|
4185
|
-
finalUrls:
|
|
4186
|
-
imageAssets:
|
|
4187
|
-
squareImageAssets:
|
|
4188
|
-
logoImageAssets:
|
|
4189
|
-
});
|
|
4190
|
-
var adContentSchema =
|
|
4067
|
+
videoAssets: z7.array(refSchema).min(1),
|
|
4068
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4069
|
+
});
|
|
4070
|
+
var demandGenAdSchema = z7.object({
|
|
4071
|
+
format: z7.literal("demandGen"),
|
|
4072
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(40) })).min(1).max(5),
|
|
4073
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(90) })).min(1).max(5),
|
|
4074
|
+
businessName: z7.string().min(1).max(25),
|
|
4075
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1),
|
|
4076
|
+
imageAssets: z7.array(refSchema).optional(),
|
|
4077
|
+
squareImageAssets: z7.array(refSchema).optional(),
|
|
4078
|
+
logoImageAssets: z7.array(refSchema).optional()
|
|
4079
|
+
});
|
|
4080
|
+
var adContentSchema = z7.discriminatedUnion("format", [
|
|
4191
4081
|
responsiveSearchAdSchema,
|
|
4192
4082
|
responsiveDisplayAdSchema,
|
|
4193
4083
|
callAdSchema,
|
|
@@ -4195,45 +4085,45 @@ var adContentSchema = z8.discriminatedUnion("format", [
|
|
|
4195
4085
|
videoAdSchema,
|
|
4196
4086
|
demandGenAdSchema
|
|
4197
4087
|
]);
|
|
4198
|
-
var adCreateSchema =
|
|
4088
|
+
var adCreateSchema = z7.object({
|
|
4199
4089
|
adGroup: refSchema,
|
|
4200
4090
|
status: stageableStatusSchema2.default("PAUSED"),
|
|
4201
4091
|
content: adContentSchema
|
|
4202
4092
|
});
|
|
4203
|
-
var adUpdateSchema =
|
|
4204
|
-
status:
|
|
4093
|
+
var adUpdateSchema = z7.object({
|
|
4094
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
|
|
4205
4095
|
/** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
|
|
4206
|
-
content:
|
|
4096
|
+
content: z7.record(z7.string(), z7.unknown()).optional()
|
|
4207
4097
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4208
|
-
var textAssetSchema =
|
|
4209
|
-
var imageAssetSchema =
|
|
4210
|
-
type:
|
|
4211
|
-
imageId:
|
|
4212
|
-
name:
|
|
4213
|
-
});
|
|
4214
|
-
var youtubeVideoAssetSchema =
|
|
4215
|
-
type:
|
|
4216
|
-
youtubeVideoId:
|
|
4217
|
-
name:
|
|
4218
|
-
});
|
|
4219
|
-
var sitelinkAssetSchema =
|
|
4220
|
-
type:
|
|
4221
|
-
linkText:
|
|
4222
|
-
description1:
|
|
4223
|
-
description2:
|
|
4224
|
-
finalUrls:
|
|
4225
|
-
});
|
|
4226
|
-
var calloutAssetSchema =
|
|
4227
|
-
type:
|
|
4228
|
-
calloutText:
|
|
4229
|
-
});
|
|
4230
|
-
var structuredSnippetAssetSchema =
|
|
4231
|
-
type:
|
|
4232
|
-
header:
|
|
4233
|
-
values:
|
|
4234
|
-
});
|
|
4235
|
-
var callToActionAssetSchema =
|
|
4236
|
-
var assetCreateSchema =
|
|
4098
|
+
var textAssetSchema = z7.object({ type: z7.literal("text"), text: z7.string().min(1) });
|
|
4099
|
+
var imageAssetSchema = z7.object({
|
|
4100
|
+
type: z7.literal("image"),
|
|
4101
|
+
imageId: z7.string().min(1),
|
|
4102
|
+
name: z7.string().optional()
|
|
4103
|
+
});
|
|
4104
|
+
var youtubeVideoAssetSchema = z7.object({
|
|
4105
|
+
type: z7.literal("youtubeVideo"),
|
|
4106
|
+
youtubeVideoId: z7.string().min(1),
|
|
4107
|
+
name: z7.string().optional()
|
|
4108
|
+
});
|
|
4109
|
+
var sitelinkAssetSchema = z7.object({
|
|
4110
|
+
type: z7.literal("sitelink"),
|
|
4111
|
+
linkText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
|
|
4112
|
+
description1: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4113
|
+
description2: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4114
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4115
|
+
});
|
|
4116
|
+
var calloutAssetSchema = z7.object({
|
|
4117
|
+
type: z7.literal("callout"),
|
|
4118
|
+
calloutText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
|
|
4119
|
+
});
|
|
4120
|
+
var structuredSnippetAssetSchema = z7.object({
|
|
4121
|
+
type: z7.literal("structuredSnippet"),
|
|
4122
|
+
header: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
|
|
4123
|
+
values: z7.array(z7.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
|
|
4124
|
+
});
|
|
4125
|
+
var callToActionAssetSchema = z7.object({ type: z7.literal("callToAction"), callToAction: z7.string().min(1) });
|
|
4126
|
+
var assetCreateSchema = z7.discriminatedUnion("type", [
|
|
4237
4127
|
textAssetSchema,
|
|
4238
4128
|
imageAssetSchema,
|
|
4239
4129
|
youtubeVideoAssetSchema,
|
|
@@ -4242,136 +4132,136 @@ var assetCreateSchema = z8.discriminatedUnion("type", [
|
|
|
4242
4132
|
structuredSnippetAssetSchema,
|
|
4243
4133
|
callToActionAssetSchema
|
|
4244
4134
|
]);
|
|
4245
|
-
var assetUpdateSchema =
|
|
4246
|
-
name:
|
|
4247
|
-
linkText:
|
|
4248
|
-
description1:
|
|
4249
|
-
description2:
|
|
4250
|
-
finalUrls:
|
|
4251
|
-
calloutText:
|
|
4252
|
-
header:
|
|
4253
|
-
values:
|
|
4254
|
-
callToAction:
|
|
4255
|
-
text:
|
|
4135
|
+
var assetUpdateSchema = z7.object({
|
|
4136
|
+
name: z7.string().min(1).optional(),
|
|
4137
|
+
linkText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax).optional(),
|
|
4138
|
+
description1: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4139
|
+
description2: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4140
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1).optional(),
|
|
4141
|
+
calloutText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax).optional(),
|
|
4142
|
+
header: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax).optional(),
|
|
4143
|
+
values: z7.array(z7.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
|
|
4144
|
+
callToAction: z7.string().min(1).optional(),
|
|
4145
|
+
text: z7.string().min(1).optional()
|
|
4256
4146
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4257
|
-
var assetLinkAttachSchema =
|
|
4258
|
-
level:
|
|
4147
|
+
var assetLinkAttachSchema = z7.object({
|
|
4148
|
+
level: z7.enum(["campaign", "adGroup", "customer"]),
|
|
4259
4149
|
parent: refSchema.optional(),
|
|
4260
4150
|
asset: refSchema,
|
|
4261
|
-
fieldType:
|
|
4151
|
+
fieldType: z7.enum(ASSET_FIELD_TYPES)
|
|
4262
4152
|
}).superRefine((value, ctx) => {
|
|
4263
4153
|
if (value.level !== "customer" && !value.parent) {
|
|
4264
4154
|
ctx.addIssue({
|
|
4265
|
-
code:
|
|
4155
|
+
code: z7.ZodIssueCode.custom,
|
|
4266
4156
|
path: ["parent"],
|
|
4267
4157
|
message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
|
|
4268
4158
|
});
|
|
4269
4159
|
}
|
|
4270
4160
|
});
|
|
4271
|
-
var assetGroupCreateSchema =
|
|
4161
|
+
var assetGroupCreateSchema = z7.object({
|
|
4272
4162
|
campaign: refSchema,
|
|
4273
|
-
name:
|
|
4274
|
-
finalUrls:
|
|
4275
|
-
headlines:
|
|
4276
|
-
longHeadlines:
|
|
4277
|
-
descriptions:
|
|
4278
|
-
businessName:
|
|
4279
|
-
imageAssets:
|
|
4280
|
-
squareImageAssets:
|
|
4281
|
-
logoAssets:
|
|
4282
|
-
status:
|
|
4283
|
-
});
|
|
4284
|
-
var assetGroupUpdateSchema =
|
|
4285
|
-
name:
|
|
4286
|
-
finalUrls:
|
|
4287
|
-
status:
|
|
4163
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax),
|
|
4164
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1),
|
|
4165
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.headlineTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.headlinesMin).max(GOOGLE_ADS_LIMITS.assetGroup.headlinesMax),
|
|
4166
|
+
longHeadlines: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.longHeadlineTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.longHeadlinesMin).max(GOOGLE_ADS_LIMITS.assetGroup.longHeadlinesMax),
|
|
4167
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.descriptionTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.descriptionsMin).max(GOOGLE_ADS_LIMITS.assetGroup.descriptionsMax),
|
|
4168
|
+
businessName: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.businessNameMax),
|
|
4169
|
+
imageAssets: z7.array(refSchema).optional(),
|
|
4170
|
+
squareImageAssets: z7.array(refSchema).optional(),
|
|
4171
|
+
logoAssets: z7.array(refSchema).optional(),
|
|
4172
|
+
status: z7.enum(["ENABLED", "PAUSED"]).default("PAUSED")
|
|
4173
|
+
});
|
|
4174
|
+
var assetGroupUpdateSchema = z7.object({
|
|
4175
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax).optional(),
|
|
4176
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1).optional(),
|
|
4177
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4288
4178
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4289
|
-
var audienceCreateSchema2 =
|
|
4290
|
-
name:
|
|
4291
|
-
type:
|
|
4292
|
-
description:
|
|
4179
|
+
var audienceCreateSchema2 = z7.object({
|
|
4180
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
|
|
4181
|
+
type: z7.enum(USER_LIST_TYPES).default("BASIC"),
|
|
4182
|
+
description: z7.string().optional(),
|
|
4293
4183
|
/** Customer-match members (crm-based) — file-first for large lists. */
|
|
4294
|
-
members:
|
|
4295
|
-
sourceFileRef:
|
|
4184
|
+
members: z7.array(z7.record(z7.string(), z7.string())).optional(),
|
|
4185
|
+
sourceFileRef: z7.string().optional()
|
|
4296
4186
|
});
|
|
4297
|
-
var audienceCriterionAttachSchema =
|
|
4298
|
-
level:
|
|
4187
|
+
var audienceCriterionAttachSchema = z7.object({
|
|
4188
|
+
level: z7.enum(["campaign", "adGroup"]),
|
|
4299
4189
|
parent: refSchema,
|
|
4300
4190
|
userList: refSchema,
|
|
4301
|
-
negative:
|
|
4191
|
+
negative: z7.boolean().default(false)
|
|
4302
4192
|
});
|
|
4303
|
-
var conversionActionCreateSchema =
|
|
4304
|
-
name:
|
|
4305
|
-
type:
|
|
4306
|
-
category:
|
|
4307
|
-
countingType:
|
|
4193
|
+
var conversionActionCreateSchema = z7.object({
|
|
4194
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
|
|
4195
|
+
type: z7.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
|
|
4196
|
+
category: z7.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
|
|
4197
|
+
countingType: z7.enum(CONVERSION_COUNTING_TYPES).default("ONE_PER_CLICK"),
|
|
4308
4198
|
defaultValueMicros: microsSchema.optional(),
|
|
4309
|
-
defaultCurrencyCode:
|
|
4310
|
-
clickThroughLookbackWindowDays:
|
|
4311
|
-
viewThroughLookbackWindowDays:
|
|
4312
|
-
status:
|
|
4313
|
-
});
|
|
4314
|
-
var conversionActionUpdateSchema =
|
|
4315
|
-
name:
|
|
4316
|
-
category:
|
|
4317
|
-
countingType:
|
|
4199
|
+
defaultCurrencyCode: z7.string().length(3).optional(),
|
|
4200
|
+
clickThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4201
|
+
viewThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4202
|
+
status: z7.enum(["ENABLED", "PAUSED"]).default("ENABLED")
|
|
4203
|
+
});
|
|
4204
|
+
var conversionActionUpdateSchema = z7.object({
|
|
4205
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
|
|
4206
|
+
category: z7.enum(CONVERSION_ACTION_CATEGORIES).optional(),
|
|
4207
|
+
countingType: z7.enum(CONVERSION_COUNTING_TYPES).optional(),
|
|
4318
4208
|
defaultValueMicros: microsSchema.optional(),
|
|
4319
|
-
defaultCurrencyCode:
|
|
4320
|
-
clickThroughLookbackWindowDays:
|
|
4321
|
-
viewThroughLookbackWindowDays:
|
|
4322
|
-
status:
|
|
4209
|
+
defaultCurrencyCode: z7.string().length(3).optional(),
|
|
4210
|
+
clickThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4211
|
+
viewThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4212
|
+
status: z7.enum(["ENABLED", "REMOVED", "HIDDEN"]).optional()
|
|
4323
4213
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4324
|
-
var biddingStrategyCreateSchema =
|
|
4325
|
-
name:
|
|
4214
|
+
var biddingStrategyCreateSchema = z7.object({
|
|
4215
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
|
|
4326
4216
|
config: biddingConfigSchema
|
|
4327
4217
|
}).superRefine((p, ctx) => {
|
|
4328
4218
|
if (p.config.type === "MANUAL_CPC") {
|
|
4329
4219
|
ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
|
|
4330
4220
|
}
|
|
4331
4221
|
});
|
|
4332
|
-
var biddingStrategyUpdateSchema =
|
|
4333
|
-
name:
|
|
4222
|
+
var biddingStrategyUpdateSchema = z7.object({
|
|
4223
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
|
|
4334
4224
|
config: biddingConfigSchema.optional()
|
|
4335
4225
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4336
|
-
var labelCreateSchema =
|
|
4337
|
-
name:
|
|
4338
|
-
backgroundColor:
|
|
4339
|
-
description:
|
|
4226
|
+
var labelCreateSchema = z7.object({
|
|
4227
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
|
|
4228
|
+
backgroundColor: z7.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
4229
|
+
description: z7.string().optional()
|
|
4340
4230
|
});
|
|
4341
|
-
var labelAttachSchema =
|
|
4342
|
-
level:
|
|
4231
|
+
var labelAttachSchema = z7.object({
|
|
4232
|
+
level: z7.enum(["campaign", "adGroup", "ad"]),
|
|
4343
4233
|
parent: refSchema,
|
|
4344
4234
|
label: refSchema
|
|
4345
4235
|
});
|
|
4346
|
-
var locationCriterionSchema =
|
|
4347
|
-
criterionType:
|
|
4348
|
-
geoTargetConstant:
|
|
4349
|
-
});
|
|
4350
|
-
var languageCriterionSchema =
|
|
4351
|
-
criterionType:
|
|
4352
|
-
languageConstant:
|
|
4353
|
-
});
|
|
4354
|
-
var adScheduleCriterionSchema =
|
|
4355
|
-
criterionType:
|
|
4356
|
-
dayOfWeek:
|
|
4357
|
-
startHour:
|
|
4358
|
-
startMinute:
|
|
4359
|
-
endHour:
|
|
4360
|
-
endMinute:
|
|
4361
|
-
});
|
|
4362
|
-
var deviceCriterionSchema =
|
|
4363
|
-
criterionType:
|
|
4364
|
-
device:
|
|
4236
|
+
var locationCriterionSchema = z7.object({
|
|
4237
|
+
criterionType: z7.literal("location"),
|
|
4238
|
+
geoTargetConstant: z7.union([z7.string().regex(GEO_TARGET_CONSTANT_REGEX), z7.string().regex(NUMERIC_ID_REGEX2)])
|
|
4239
|
+
});
|
|
4240
|
+
var languageCriterionSchema = z7.object({
|
|
4241
|
+
criterionType: z7.literal("language"),
|
|
4242
|
+
languageConstant: z7.union([z7.string().regex(LANGUAGE_CONSTANT_REGEX), z7.string().regex(NUMERIC_ID_REGEX2)])
|
|
4243
|
+
});
|
|
4244
|
+
var adScheduleCriterionSchema = z7.object({
|
|
4245
|
+
criterionType: z7.literal("adSchedule"),
|
|
4246
|
+
dayOfWeek: z7.enum(DAYS_OF_WEEK),
|
|
4247
|
+
startHour: z7.number().int().min(0).max(23),
|
|
4248
|
+
startMinute: z7.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
|
|
4249
|
+
endHour: z7.number().int().min(0).max(24),
|
|
4250
|
+
endMinute: z7.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
|
|
4251
|
+
});
|
|
4252
|
+
var deviceCriterionSchema = z7.object({
|
|
4253
|
+
criterionType: z7.literal("device"),
|
|
4254
|
+
device: z7.enum(DEVICE_TYPES),
|
|
4365
4255
|
// Google's `CampaignCriterion.bid_modifier`: "The modifier must be in the range 0.1 - 10.0. Use 0
|
|
4366
4256
|
// to opt out of a Device type." So 0 (exclude the device) and 0.1–10.0 are valid; the (0, 0.1) gap is not.
|
|
4367
|
-
bidModifier:
|
|
4257
|
+
bidModifier: z7.number().min(0).max(10).optional().refine((v) => v === void 0 || v === 0 || v >= 0.1, {
|
|
4368
4258
|
message: "bid modifier must be 0 (exclude the device) or between 0.1 and 10.0"
|
|
4369
4259
|
})
|
|
4370
4260
|
});
|
|
4371
|
-
var campaignCriterionAddSchema =
|
|
4261
|
+
var campaignCriterionAddSchema = z7.object({
|
|
4372
4262
|
campaign: refSchema,
|
|
4373
|
-
negative:
|
|
4374
|
-
criterion:
|
|
4263
|
+
negative: z7.boolean().default(false),
|
|
4264
|
+
criterion: z7.discriminatedUnion("criterionType", [
|
|
4375
4265
|
locationCriterionSchema,
|
|
4376
4266
|
languageCriterionSchema,
|
|
4377
4267
|
adScheduleCriterionSchema,
|
|
@@ -4381,7 +4271,7 @@ var campaignCriterionAddSchema = z8.object({
|
|
|
4381
4271
|
const c = val.criterion;
|
|
4382
4272
|
if (c.criterionType === "adSchedule" && c.endHour === 24 && c.endMinute !== "ZERO") {
|
|
4383
4273
|
ctx.addIssue({
|
|
4384
|
-
code:
|
|
4274
|
+
code: z7.ZodIssueCode.custom,
|
|
4385
4275
|
message: "endHour 24 (midnight) cannot have a non-zero endMinute",
|
|
4386
4276
|
path: ["criterion", "endMinute"]
|
|
4387
4277
|
});
|
|
@@ -4433,17 +4323,17 @@ var GOOGLE_DRAFT_OP_KINDS = [
|
|
|
4433
4323
|
"google.campaignCriterion.add",
|
|
4434
4324
|
"google.campaignCriterion.remove"
|
|
4435
4325
|
];
|
|
4436
|
-
var googleDraftOpKindSchema =
|
|
4326
|
+
var googleDraftOpKindSchema = z7.enum(GOOGLE_DRAFT_OP_KINDS);
|
|
4437
4327
|
function createOp2(kind, payload) {
|
|
4438
|
-
return
|
|
4328
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, payload });
|
|
4439
4329
|
}
|
|
4440
4330
|
function updateOp2(kind, payload) {
|
|
4441
|
-
return
|
|
4331
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
|
|
4442
4332
|
}
|
|
4443
4333
|
function targetOp(kind) {
|
|
4444
|
-
return
|
|
4334
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
|
|
4445
4335
|
}
|
|
4446
|
-
var googleDraftOpInputSchema =
|
|
4336
|
+
var googleDraftOpInputSchema = z7.discriminatedUnion("kind", [
|
|
4447
4337
|
createOp2("google.budget.create", budgetCreateSchema),
|
|
4448
4338
|
updateOp2("google.budget.update", budgetUpdateSchema),
|
|
4449
4339
|
createOp2("google.campaign.create", campaignCreateSchema2),
|
|
@@ -4491,132 +4381,132 @@ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
|
|
|
4491
4381
|
]);
|
|
4492
4382
|
|
|
4493
4383
|
// ../api/src/ads-google/wire.ts
|
|
4494
|
-
import { z as
|
|
4495
|
-
var googleWriteModeSchema =
|
|
4496
|
-
var googleDraftOpResultSchema =
|
|
4497
|
-
status:
|
|
4498
|
-
resourceName:
|
|
4499
|
-
error:
|
|
4500
|
-
skippedBecause:
|
|
4501
|
-
executedAt:
|
|
4502
|
-
});
|
|
4503
|
-
var googleDraftStageRequestSchema =
|
|
4504
|
-
chatId:
|
|
4384
|
+
import { z as z8 } from "zod";
|
|
4385
|
+
var googleWriteModeSchema = z8.enum(["live", "simulated"]);
|
|
4386
|
+
var googleDraftOpResultSchema = z8.object({
|
|
4387
|
+
status: z8.enum(["applied", "simulated", "failed", "skipped"]),
|
|
4388
|
+
resourceName: z8.string().optional(),
|
|
4389
|
+
error: z8.string().optional(),
|
|
4390
|
+
skippedBecause: z8.string().optional(),
|
|
4391
|
+
executedAt: z8.number().optional()
|
|
4392
|
+
});
|
|
4393
|
+
var googleDraftStageRequestSchema = z8.object({
|
|
4394
|
+
chatId: z8.string(),
|
|
4505
4395
|
op: googleDraftOpInputSchema
|
|
4506
4396
|
});
|
|
4507
|
-
var googleDraftStageResponseSchema =
|
|
4508
|
-
staged:
|
|
4509
|
-
ref:
|
|
4397
|
+
var googleDraftStageResponseSchema = z8.object({
|
|
4398
|
+
staged: z8.literal(true),
|
|
4399
|
+
ref: z8.string(),
|
|
4510
4400
|
kind: googleDraftOpKindSchema,
|
|
4511
4401
|
mode: googleWriteModeSchema,
|
|
4512
|
-
dependsOn:
|
|
4513
|
-
summary:
|
|
4514
|
-
warnings:
|
|
4402
|
+
dependsOn: z8.array(z8.string()),
|
|
4403
|
+
summary: z8.string(),
|
|
4404
|
+
warnings: z8.array(z8.string()),
|
|
4515
4405
|
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
4516
|
-
amended:
|
|
4406
|
+
amended: z8.boolean().optional()
|
|
4517
4407
|
});
|
|
4518
|
-
var googleDraftAmendRequestSchema =
|
|
4519
|
-
chatId:
|
|
4520
|
-
ref:
|
|
4521
|
-
patch:
|
|
4408
|
+
var googleDraftAmendRequestSchema = z8.object({
|
|
4409
|
+
chatId: z8.string(),
|
|
4410
|
+
ref: z8.string(),
|
|
4411
|
+
patch: z8.record(z8.string(), z8.unknown())
|
|
4522
4412
|
});
|
|
4523
|
-
var googleDraftShowRequestSchema =
|
|
4524
|
-
chatId:
|
|
4525
|
-
ref:
|
|
4413
|
+
var googleDraftShowRequestSchema = z8.object({
|
|
4414
|
+
chatId: z8.string(),
|
|
4415
|
+
ref: z8.string()
|
|
4526
4416
|
});
|
|
4527
4417
|
var GOOGLE_DRAFT_BATCH_MAX = 500;
|
|
4528
|
-
var googleDraftStageBatchRequestSchema =
|
|
4529
|
-
chatId:
|
|
4530
|
-
ops:
|
|
4418
|
+
var googleDraftStageBatchRequestSchema = z8.object({
|
|
4419
|
+
chatId: z8.string(),
|
|
4420
|
+
ops: z8.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
|
|
4531
4421
|
});
|
|
4532
|
-
var googleDraftStageBatchResponseSchema =
|
|
4533
|
-
staged:
|
|
4422
|
+
var googleDraftStageBatchResponseSchema = z8.object({
|
|
4423
|
+
staged: z8.literal(true),
|
|
4534
4424
|
mode: googleWriteModeSchema,
|
|
4535
|
-
count:
|
|
4536
|
-
ops:
|
|
4537
|
-
|
|
4538
|
-
ref:
|
|
4425
|
+
count: z8.number(),
|
|
4426
|
+
ops: z8.array(
|
|
4427
|
+
z8.object({
|
|
4428
|
+
ref: z8.string(),
|
|
4539
4429
|
kind: googleDraftOpKindSchema,
|
|
4540
|
-
dependsOn:
|
|
4541
|
-
summary:
|
|
4542
|
-
warnings:
|
|
4430
|
+
dependsOn: z8.array(z8.string()),
|
|
4431
|
+
summary: z8.string(),
|
|
4432
|
+
warnings: z8.array(z8.string())
|
|
4543
4433
|
})
|
|
4544
4434
|
)
|
|
4545
4435
|
});
|
|
4546
|
-
var googleDraftOpViewSchema =
|
|
4547
|
-
ref:
|
|
4436
|
+
var googleDraftOpViewSchema = z8.object({
|
|
4437
|
+
ref: z8.string(),
|
|
4548
4438
|
kind: googleDraftOpKindSchema,
|
|
4549
|
-
customerId:
|
|
4550
|
-
target:
|
|
4551
|
-
dependsOn:
|
|
4552
|
-
summary:
|
|
4553
|
-
stagedAt:
|
|
4439
|
+
customerId: z8.string(),
|
|
4440
|
+
target: z8.string().optional(),
|
|
4441
|
+
dependsOn: z8.array(z8.string()),
|
|
4442
|
+
summary: z8.string(),
|
|
4443
|
+
stagedAt: z8.number(),
|
|
4554
4444
|
result: googleDraftOpResultSchema.optional()
|
|
4555
4445
|
});
|
|
4556
|
-
var googleDraftShowResponseSchema =
|
|
4446
|
+
var googleDraftShowResponseSchema = z8.object({
|
|
4557
4447
|
op: googleDraftOpViewSchema.extend({
|
|
4558
|
-
payload:
|
|
4559
|
-
warnings:
|
|
4560
|
-
annotations:
|
|
4448
|
+
payload: z8.unknown().optional(),
|
|
4449
|
+
warnings: z8.array(z8.string()).optional(),
|
|
4450
|
+
annotations: z8.unknown().optional()
|
|
4561
4451
|
})
|
|
4562
4452
|
});
|
|
4563
|
-
var googleDraftListRequestSchema =
|
|
4564
|
-
chatId:
|
|
4453
|
+
var googleDraftListRequestSchema = z8.object({
|
|
4454
|
+
chatId: z8.string()
|
|
4565
4455
|
});
|
|
4566
|
-
var googleDraftAdvisorySchema =
|
|
4567
|
-
scope:
|
|
4568
|
-
message:
|
|
4456
|
+
var googleDraftAdvisorySchema = z8.object({
|
|
4457
|
+
scope: z8.enum(["campaign", "adGroup"]),
|
|
4458
|
+
message: z8.string()
|
|
4569
4459
|
});
|
|
4570
|
-
var googleDraftStatusCollectionSchema =
|
|
4571
|
-
label:
|
|
4572
|
-
added:
|
|
4573
|
-
removed:
|
|
4574
|
-
existing:
|
|
4460
|
+
var googleDraftStatusCollectionSchema = z8.object({
|
|
4461
|
+
label: z8.string(),
|
|
4462
|
+
added: z8.number(),
|
|
4463
|
+
removed: z8.number(),
|
|
4464
|
+
existing: z8.number()
|
|
4575
4465
|
});
|
|
4576
|
-
var googleDraftChangeOperationSchema =
|
|
4577
|
-
var googleDraftStatusNodeSchema =
|
|
4578
|
-
() =>
|
|
4579
|
-
entity:
|
|
4580
|
-
name:
|
|
4466
|
+
var googleDraftChangeOperationSchema = z8.enum(["create", "update", "pause", "resume", "remove"]);
|
|
4467
|
+
var googleDraftStatusNodeSchema = z8.lazy(
|
|
4468
|
+
() => z8.object({
|
|
4469
|
+
entity: z8.string(),
|
|
4470
|
+
name: z8.string(),
|
|
4581
4471
|
operation: googleDraftChangeOperationSchema.optional(),
|
|
4582
|
-
existing:
|
|
4583
|
-
collections:
|
|
4584
|
-
children:
|
|
4585
|
-
warnings:
|
|
4472
|
+
existing: z8.boolean(),
|
|
4473
|
+
collections: z8.array(googleDraftStatusCollectionSchema),
|
|
4474
|
+
children: z8.array(googleDraftStatusNodeSchema),
|
|
4475
|
+
warnings: z8.array(z8.string()).optional()
|
|
4586
4476
|
})
|
|
4587
4477
|
);
|
|
4588
|
-
var googleDraftListResponseSchema =
|
|
4589
|
-
status:
|
|
4478
|
+
var googleDraftListResponseSchema = z8.object({
|
|
4479
|
+
status: z8.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
4590
4480
|
mode: googleWriteModeSchema,
|
|
4591
|
-
count:
|
|
4592
|
-
ops:
|
|
4481
|
+
count: z8.number(),
|
|
4482
|
+
ops: z8.array(googleDraftOpViewSchema),
|
|
4593
4483
|
/** Grouped campaign ▸ ad group ▸ ad tree for the readable CLI status view. */
|
|
4594
|
-
tree:
|
|
4484
|
+
tree: z8.array(googleDraftStatusNodeSchema).optional(),
|
|
4595
4485
|
/** Non-blocking completeness advisories for the whole draft. */
|
|
4596
|
-
advisories:
|
|
4486
|
+
advisories: z8.array(googleDraftAdvisorySchema).optional()
|
|
4597
4487
|
});
|
|
4598
|
-
var googleDraftRemoveRequestSchema =
|
|
4599
|
-
chatId:
|
|
4600
|
-
ref:
|
|
4488
|
+
var googleDraftRemoveRequestSchema = z8.object({
|
|
4489
|
+
chatId: z8.string(),
|
|
4490
|
+
ref: z8.string()
|
|
4601
4491
|
});
|
|
4602
|
-
var googleDraftRemoveResponseSchema =
|
|
4492
|
+
var googleDraftRemoveResponseSchema = z8.object({
|
|
4603
4493
|
/** The requested ref plus any dependents removed by cascade. */
|
|
4604
|
-
removed:
|
|
4494
|
+
removed: z8.array(z8.string())
|
|
4605
4495
|
});
|
|
4606
|
-
var googleDraftClearRequestSchema =
|
|
4607
|
-
chatId:
|
|
4496
|
+
var googleDraftClearRequestSchema = z8.object({
|
|
4497
|
+
chatId: z8.string()
|
|
4608
4498
|
});
|
|
4609
|
-
var googleDraftClearResponseSchema =
|
|
4610
|
-
cleared:
|
|
4499
|
+
var googleDraftClearResponseSchema = z8.object({
|
|
4500
|
+
cleared: z8.number()
|
|
4611
4501
|
});
|
|
4612
|
-
var googleFieldErrorSchema =
|
|
4613
|
-
path:
|
|
4614
|
-
message:
|
|
4502
|
+
var googleFieldErrorSchema = z8.object({
|
|
4503
|
+
path: z8.string(),
|
|
4504
|
+
message: z8.string()
|
|
4615
4505
|
});
|
|
4616
|
-
var googleDraftErrorResponseSchema =
|
|
4617
|
-
code:
|
|
4618
|
-
error:
|
|
4619
|
-
fields:
|
|
4506
|
+
var googleDraftErrorResponseSchema = z8.object({
|
|
4507
|
+
code: z8.string(),
|
|
4508
|
+
error: z8.string(),
|
|
4509
|
+
fields: z8.array(googleFieldErrorSchema).optional()
|
|
4620
4510
|
});
|
|
4621
4511
|
|
|
4622
4512
|
// src/commands/ads/google/draft-status.ts
|
|
@@ -4781,11 +4671,11 @@ function rawTextEntries(value) {
|
|
|
4781
4671
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
4782
4672
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
4783
4673
|
}
|
|
4784
|
-
function rawFileEntries(
|
|
4785
|
-
if (typeof
|
|
4674
|
+
function rawFileEntries(path14) {
|
|
4675
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
4786
4676
|
return [];
|
|
4787
4677
|
}
|
|
4788
|
-
return readFileSync2(
|
|
4678
|
+
return readFileSync2(path14, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
4789
4679
|
}
|
|
4790
4680
|
function keywordEntries(args) {
|
|
4791
4681
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -4808,19 +4698,19 @@ function keywordEntries(args) {
|
|
|
4808
4698
|
}
|
|
4809
4699
|
return entries;
|
|
4810
4700
|
}
|
|
4811
|
-
function loadJsonFileArg(
|
|
4812
|
-
if (typeof
|
|
4701
|
+
function loadJsonFileArg(path14) {
|
|
4702
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
4813
4703
|
return {};
|
|
4814
4704
|
}
|
|
4815
4705
|
try {
|
|
4816
|
-
const parsed = JSON.parse(readFileSync2(
|
|
4706
|
+
const parsed = JSON.parse(readFileSync2(path14, "utf8"));
|
|
4817
4707
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4818
|
-
failWriteValidation(`${
|
|
4708
|
+
failWriteValidation(`${path14} must contain a JSON object`);
|
|
4819
4709
|
}
|
|
4820
4710
|
return parsed;
|
|
4821
4711
|
} catch (err) {
|
|
4822
4712
|
if (err instanceof SyntaxError) {
|
|
4823
|
-
failWriteValidation(`${
|
|
4713
|
+
failWriteValidation(`${path14} is not valid JSON: ${err.message}`);
|
|
4824
4714
|
}
|
|
4825
4715
|
throw err;
|
|
4826
4716
|
}
|
|
@@ -4931,10 +4821,10 @@ async function stageUpdate(kind, customerId, target, payload) {
|
|
|
4931
4821
|
async function stageTarget(kind, customerId, target) {
|
|
4932
4822
|
await stageGoogleOp({ kind, customerId, target });
|
|
4933
4823
|
}
|
|
4934
|
-
async function draftAction(
|
|
4824
|
+
async function draftAction(path14, body) {
|
|
4935
4825
|
try {
|
|
4936
4826
|
const chatId = requireChatId();
|
|
4937
|
-
const response = await apiPost(
|
|
4827
|
+
const response = await apiPost(path14, { chatId, ...body });
|
|
4938
4828
|
writeJsonEnvelope(response);
|
|
4939
4829
|
} catch (err) {
|
|
4940
4830
|
handleGoogleError(err);
|
|
@@ -8689,19 +8579,19 @@ function failWriteValidation2(message) {
|
|
|
8689
8579
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
8690
8580
|
process.exit(1);
|
|
8691
8581
|
}
|
|
8692
|
-
function loadJsonFileArg2(
|
|
8693
|
-
if (typeof
|
|
8582
|
+
function loadJsonFileArg2(path14) {
|
|
8583
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8694
8584
|
return {};
|
|
8695
8585
|
}
|
|
8696
8586
|
try {
|
|
8697
|
-
const parsed = JSON.parse(readFileSync6(
|
|
8587
|
+
const parsed = JSON.parse(readFileSync6(path14, "utf8"));
|
|
8698
8588
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8699
|
-
failWriteValidation2(`${
|
|
8589
|
+
failWriteValidation2(`${path14} must contain a JSON object`);
|
|
8700
8590
|
}
|
|
8701
8591
|
return parsed;
|
|
8702
8592
|
} catch (err) {
|
|
8703
8593
|
if (err instanceof SyntaxError) {
|
|
8704
|
-
failWriteValidation2(`${
|
|
8594
|
+
failWriteValidation2(`${path14} is not valid JSON: ${err.message}`);
|
|
8705
8595
|
}
|
|
8706
8596
|
throw err;
|
|
8707
8597
|
}
|
|
@@ -8786,15 +8676,15 @@ function parseLocaleFlag(value) {
|
|
|
8786
8676
|
}
|
|
8787
8677
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
8788
8678
|
}
|
|
8789
|
-
function loadTargetingFileArg(
|
|
8790
|
-
if (typeof
|
|
8679
|
+
function loadTargetingFileArg(path14) {
|
|
8680
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8791
8681
|
return void 0;
|
|
8792
8682
|
}
|
|
8793
|
-
const parsed = loadJsonFileArg2(
|
|
8683
|
+
const parsed = loadJsonFileArg2(path14);
|
|
8794
8684
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
8795
8685
|
if (!criteria.include) {
|
|
8796
8686
|
failWriteValidation2(
|
|
8797
|
-
`${
|
|
8687
|
+
`${path14} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
8798
8688
|
);
|
|
8799
8689
|
}
|
|
8800
8690
|
return criteria;
|
|
@@ -8829,14 +8719,14 @@ function parseCsvLine(line) {
|
|
|
8829
8719
|
cells.push(current);
|
|
8830
8720
|
return cells.map((cell) => cell.trim());
|
|
8831
8721
|
}
|
|
8832
|
-
function parseListFileArg(
|
|
8833
|
-
if (typeof
|
|
8722
|
+
function parseListFileArg(path14, maxRows) {
|
|
8723
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8834
8724
|
return void 0;
|
|
8835
8725
|
}
|
|
8836
|
-
const raw = readFileSync6(
|
|
8726
|
+
const raw = readFileSync6(path14, "utf8");
|
|
8837
8727
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
8838
8728
|
if (lines.length < 2) {
|
|
8839
|
-
failWriteValidation2(`${
|
|
8729
|
+
failWriteValidation2(`${path14} needs a header row and at least one data row`);
|
|
8840
8730
|
}
|
|
8841
8731
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
8842
8732
|
const rows = [];
|
|
@@ -8855,7 +8745,7 @@ function parseListFileArg(path12, maxRows) {
|
|
|
8855
8745
|
}
|
|
8856
8746
|
}
|
|
8857
8747
|
if (rows.length > maxRows) {
|
|
8858
|
-
failWriteValidation2(`${
|
|
8748
|
+
failWriteValidation2(`${path14} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
8859
8749
|
}
|
|
8860
8750
|
return { columns, rows };
|
|
8861
8751
|
}
|
|
@@ -9500,7 +9390,7 @@ var leadFormsCreateCommand = defineCommand38({
|
|
|
9500
9390
|
Required: name, headline (\u226460), privacyPolicyUrl, questions[] (\u226412; playbook: \u22644 for completion).
|
|
9501
9391
|
Each question is a predefined profile field ({ name, predefinedField: "EMAIL" }) or a custom question ({ name, questionType: "MULTIPLE_CHOICE", options: [...] }; \u22643 custom).
|
|
9502
9392
|
Best-practice fields the preview will nudge for if missing: 1-3 qualifying questions, consents[] (disclosure checkboxes), thankYou.message + thankYou.landingUrl|appointmentUrl.
|
|
9503
|
-
Also supported: locale, formImageId|formImageUrn, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
|
|
9393
|
+
Also supported: locale, formImageId|formImageUrn, privacyPolicyText, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
|
|
9504
9394
|
},
|
|
9505
9395
|
args: {
|
|
9506
9396
|
...accountArgs,
|
|
@@ -10924,72 +10814,72 @@ var NUMERIC_ID_REGEX3 = /^\d+$/;
|
|
|
10924
10814
|
var IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;
|
|
10925
10815
|
|
|
10926
10816
|
// ../api/src/ads-meta/ops.ts
|
|
10927
|
-
import { z as
|
|
10928
|
-
var tempRefSchema3 =
|
|
10929
|
-
var parentRefSchema2 =
|
|
10930
|
-
var moneySchema2 =
|
|
10931
|
-
amount:
|
|
10932
|
-
currencyCode:
|
|
10933
|
-
});
|
|
10934
|
-
var httpsUrlSchema3 =
|
|
10935
|
-
var bakerMediaIdSchema2 =
|
|
10936
|
-
var stageableStatusSchema3 =
|
|
10937
|
-
var updateStatusSchema =
|
|
10817
|
+
import { z as z9 } from "zod";
|
|
10818
|
+
var tempRefSchema3 = z9.string().regex(TEMP_REF_REGEX3, "expected a meta_temp_* reference");
|
|
10819
|
+
var parentRefSchema2 = z9.union([z9.string().regex(NUMERIC_ID_REGEX3, "expected a numeric id"), tempRefSchema3]);
|
|
10820
|
+
var moneySchema2 = z9.object({
|
|
10821
|
+
amount: z9.string().regex(/^\d+(\.\d{1,2})?$/, "expected a decimal amount like 50 or 50.00").refine((val) => Number(val) > 0, "amount must be greater than zero"),
|
|
10822
|
+
currencyCode: z9.string().length(3).optional()
|
|
10823
|
+
});
|
|
10824
|
+
var httpsUrlSchema3 = z9.string().url().refine((u) => u.startsWith("https://"), "destination URLs must be https");
|
|
10825
|
+
var bakerMediaIdSchema2 = z9.string().min(1);
|
|
10826
|
+
var stageableStatusSchema3 = z9.enum(STAGEABLE_CREATE_STATUSES3);
|
|
10827
|
+
var updateStatusSchema = z9.enum(UPDATE_STATUSES);
|
|
10938
10828
|
function currencyMinimums2(currencyCode) {
|
|
10939
10829
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
10940
10830
|
}
|
|
10941
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
10831
|
+
function validateDailyBudgetFloor(money, ctx, path14) {
|
|
10942
10832
|
if (money?.currencyCode) {
|
|
10943
10833
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
10944
10834
|
if (Number(money.amount) < min) {
|
|
10945
|
-
ctx.addIssue({ code: "custom", path:
|
|
10835
|
+
ctx.addIssue({ code: "custom", path: path14, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
10946
10836
|
}
|
|
10947
10837
|
}
|
|
10948
10838
|
}
|
|
10949
|
-
var geoLocationsSchema =
|
|
10950
|
-
countries:
|
|
10951
|
-
regions:
|
|
10952
|
-
cities:
|
|
10953
|
-
zips:
|
|
10954
|
-
location_types:
|
|
10955
|
-
}).catchall(
|
|
10956
|
-
var idNameSchema =
|
|
10957
|
-
var metaTargetingSchema =
|
|
10839
|
+
var geoLocationsSchema = z9.object({
|
|
10840
|
+
countries: z9.array(z9.string().length(2)).optional(),
|
|
10841
|
+
regions: z9.array(z9.object({ key: z9.string() })).optional(),
|
|
10842
|
+
cities: z9.array(z9.object({ key: z9.string(), radius: z9.number().optional(), distance_unit: z9.string().optional() })).optional(),
|
|
10843
|
+
zips: z9.array(z9.object({ key: z9.string() })).optional(),
|
|
10844
|
+
location_types: z9.array(z9.string()).optional()
|
|
10845
|
+
}).catchall(z9.unknown());
|
|
10846
|
+
var idNameSchema = z9.object({ id: z9.string(), name: z9.string().optional() });
|
|
10847
|
+
var metaTargetingSchema = z9.object({
|
|
10958
10848
|
geo_locations: geoLocationsSchema.optional(),
|
|
10959
10849
|
excluded_geo_locations: geoLocationsSchema.optional(),
|
|
10960
|
-
age_min:
|
|
10961
|
-
age_max:
|
|
10962
|
-
genders:
|
|
10963
|
-
locales:
|
|
10964
|
-
interests:
|
|
10965
|
-
behaviors:
|
|
10966
|
-
custom_audiences:
|
|
10967
|
-
excluded_custom_audiences:
|
|
10968
|
-
flexible_spec:
|
|
10969
|
-
exclusions:
|
|
10970
|
-
publisher_platforms:
|
|
10971
|
-
facebook_positions:
|
|
10972
|
-
instagram_positions:
|
|
10973
|
-
audience_network_positions:
|
|
10974
|
-
messenger_positions:
|
|
10975
|
-
device_platforms:
|
|
10976
|
-
targeting_automation:
|
|
10977
|
-
}).catchall(
|
|
10978
|
-
var specialAdCategoriesSchema =
|
|
10979
|
-
var campaignCreateSchema3 =
|
|
10980
|
-
name:
|
|
10981
|
-
objective:
|
|
10850
|
+
age_min: z9.number().int().min(13).max(65).optional(),
|
|
10851
|
+
age_max: z9.number().int().min(13).max(65).optional(),
|
|
10852
|
+
genders: z9.array(z9.union([z9.literal(1), z9.literal(2)])).optional(),
|
|
10853
|
+
locales: z9.array(z9.number().int()).optional(),
|
|
10854
|
+
interests: z9.array(idNameSchema).optional(),
|
|
10855
|
+
behaviors: z9.array(idNameSchema).optional(),
|
|
10856
|
+
custom_audiences: z9.array(z9.object({ id: parentRefSchema2 })).optional(),
|
|
10857
|
+
excluded_custom_audiences: z9.array(z9.object({ id: parentRefSchema2 })).optional(),
|
|
10858
|
+
flexible_spec: z9.array(z9.record(z9.string(), z9.unknown())).optional(),
|
|
10859
|
+
exclusions: z9.record(z9.string(), z9.unknown()).optional(),
|
|
10860
|
+
publisher_platforms: z9.array(z9.string()).optional(),
|
|
10861
|
+
facebook_positions: z9.array(z9.string()).optional(),
|
|
10862
|
+
instagram_positions: z9.array(z9.string()).optional(),
|
|
10863
|
+
audience_network_positions: z9.array(z9.string()).optional(),
|
|
10864
|
+
messenger_positions: z9.array(z9.string()).optional(),
|
|
10865
|
+
device_platforms: z9.array(z9.string()).optional(),
|
|
10866
|
+
targeting_automation: z9.object({ advantage_audience: z9.union([z9.literal(0), z9.literal(1)]) }).partial().optional()
|
|
10867
|
+
}).catchall(z9.unknown());
|
|
10868
|
+
var specialAdCategoriesSchema = z9.array(z9.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
|
|
10869
|
+
var campaignCreateSchema3 = z9.object({
|
|
10870
|
+
name: z9.string().min(1).max(META_LIMITS.campaign.nameMax),
|
|
10871
|
+
objective: z9.enum(OBJECTIVES),
|
|
10982
10872
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
10983
10873
|
special_ad_categories: specialAdCategoriesSchema,
|
|
10984
|
-
special_ad_category_country:
|
|
10985
|
-
buying_type:
|
|
10986
|
-
bid_strategy:
|
|
10874
|
+
special_ad_category_country: z9.array(z9.string().length(2)).optional(),
|
|
10875
|
+
buying_type: z9.enum(BUYING_TYPES).default("AUCTION"),
|
|
10876
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10987
10877
|
/** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */
|
|
10988
10878
|
dailyBudget: moneySchema2.optional(),
|
|
10989
10879
|
lifetimeBudget: moneySchema2.optional(),
|
|
10990
10880
|
spendCap: moneySchema2.optional(),
|
|
10991
|
-
start_time:
|
|
10992
|
-
stop_time:
|
|
10881
|
+
start_time: z9.number().int().positive().optional(),
|
|
10882
|
+
stop_time: z9.number().int().positive().optional()
|
|
10993
10883
|
}).superRefine((p, ctx) => {
|
|
10994
10884
|
if (p.dailyBudget && p.lifetimeBudget) {
|
|
10995
10885
|
ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
|
|
@@ -10999,15 +10889,15 @@ var campaignCreateSchema3 = z10.object({
|
|
|
10999
10889
|
ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
|
|
11000
10890
|
}
|
|
11001
10891
|
});
|
|
11002
|
-
var campaignUpdateSchema3 =
|
|
11003
|
-
name:
|
|
10892
|
+
var campaignUpdateSchema3 = z9.object({
|
|
10893
|
+
name: z9.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
|
|
11004
10894
|
status: updateStatusSchema.optional(),
|
|
11005
|
-
bid_strategy:
|
|
10895
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
11006
10896
|
dailyBudget: moneySchema2.optional(),
|
|
11007
10897
|
lifetimeBudget: moneySchema2.optional(),
|
|
11008
10898
|
spendCap: moneySchema2.optional(),
|
|
11009
|
-
start_time:
|
|
11010
|
-
stop_time:
|
|
10899
|
+
start_time: z9.number().int().positive().optional(),
|
|
10900
|
+
stop_time: z9.number().int().positive().optional()
|
|
11011
10901
|
}).superRefine((p, ctx) => {
|
|
11012
10902
|
if (!Object.values(p).some((val) => val !== void 0)) {
|
|
11013
10903
|
ctx.addIssue({ code: "custom", message: "update needs at least one field" });
|
|
@@ -11017,38 +10907,38 @@ var campaignUpdateSchema3 = z10.object({
|
|
|
11017
10907
|
}
|
|
11018
10908
|
validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
|
|
11019
10909
|
});
|
|
11020
|
-
var promotedObjectSchema =
|
|
10910
|
+
var promotedObjectSchema = z9.object({
|
|
11021
10911
|
page_id: parentRefSchema2.optional(),
|
|
11022
|
-
pixel_id:
|
|
11023
|
-
custom_event_type:
|
|
11024
|
-
application_id:
|
|
11025
|
-
object_store_url:
|
|
11026
|
-
product_catalog_id:
|
|
11027
|
-
product_set_id:
|
|
11028
|
-
whatsapp_phone_number:
|
|
11029
|
-
offline_conversion_data_set_id:
|
|
10912
|
+
pixel_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10913
|
+
custom_event_type: z9.enum(CUSTOM_EVENT_TYPES).optional(),
|
|
10914
|
+
application_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10915
|
+
object_store_url: z9.string().url().optional(),
|
|
10916
|
+
product_catalog_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10917
|
+
product_set_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10918
|
+
whatsapp_phone_number: z9.string().optional(),
|
|
10919
|
+
offline_conversion_data_set_id: z9.string().regex(NUMERIC_ID_REGEX3).optional()
|
|
11030
10920
|
}).partial();
|
|
11031
|
-
var attributionSpecSchema =
|
|
11032
|
-
|
|
11033
|
-
event_type:
|
|
11034
|
-
window_days:
|
|
10921
|
+
var attributionSpecSchema = z9.array(
|
|
10922
|
+
z9.object({
|
|
10923
|
+
event_type: z9.enum(ATTRIBUTION_EVENT_TYPES),
|
|
10924
|
+
window_days: z9.union([z9.literal(1), z9.literal(7), z9.literal(28)])
|
|
11035
10925
|
})
|
|
11036
10926
|
);
|
|
11037
10927
|
var adSetFields = {
|
|
11038
|
-
name:
|
|
10928
|
+
name: z9.string().min(1).max(META_LIMITS.adSet.nameMax),
|
|
11039
10929
|
campaign_id: parentRefSchema2,
|
|
11040
10930
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
11041
10931
|
dailyBudget: moneySchema2.optional(),
|
|
11042
10932
|
lifetimeBudget: moneySchema2.optional(),
|
|
11043
10933
|
bidAmount: moneySchema2.optional(),
|
|
11044
|
-
bid_strategy:
|
|
11045
|
-
billing_event:
|
|
11046
|
-
optimization_goal:
|
|
11047
|
-
destination_type:
|
|
10934
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10935
|
+
billing_event: z9.enum(BILLING_EVENTS),
|
|
10936
|
+
optimization_goal: z9.enum(OPTIMIZATION_GOALS),
|
|
10937
|
+
destination_type: z9.enum(DESTINATION_TYPES).optional(),
|
|
11048
10938
|
promoted_object: promotedObjectSchema.optional(),
|
|
11049
10939
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11050
|
-
start_time:
|
|
11051
|
-
end_time:
|
|
10940
|
+
start_time: z9.number().int().positive().optional(),
|
|
10941
|
+
end_time: z9.number().int().positive().optional(),
|
|
11052
10942
|
targeting: metaTargetingSchema
|
|
11053
10943
|
};
|
|
11054
10944
|
function validateAdSetBudgetAndBid(p, ctx) {
|
|
@@ -11066,22 +10956,22 @@ function validateAdSetBudgetAndBid(p, ctx) {
|
|
|
11066
10956
|
ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
|
|
11067
10957
|
}
|
|
11068
10958
|
}
|
|
11069
|
-
var adSetCreateSchema =
|
|
10959
|
+
var adSetCreateSchema = z9.object(adSetFields).superRefine((p, ctx) => {
|
|
11070
10960
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11071
10961
|
});
|
|
11072
|
-
var adSetUpdateSchema =
|
|
10962
|
+
var adSetUpdateSchema = z9.object({
|
|
11073
10963
|
name: adSetFields.name.optional(),
|
|
11074
10964
|
status: updateStatusSchema.optional(),
|
|
11075
10965
|
dailyBudget: moneySchema2.optional(),
|
|
11076
10966
|
lifetimeBudget: moneySchema2.optional(),
|
|
11077
10967
|
bidAmount: moneySchema2.optional(),
|
|
11078
|
-
bid_strategy:
|
|
11079
|
-
optimization_goal:
|
|
11080
|
-
destination_type:
|
|
10968
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10969
|
+
optimization_goal: z9.enum(OPTIMIZATION_GOALS).optional(),
|
|
10970
|
+
destination_type: z9.enum(DESTINATION_TYPES).optional(),
|
|
11081
10971
|
promoted_object: promotedObjectSchema.optional(),
|
|
11082
10972
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11083
|
-
start_time:
|
|
11084
|
-
end_time:
|
|
10973
|
+
start_time: z9.number().int().positive().optional(),
|
|
10974
|
+
end_time: z9.number().int().positive().optional(),
|
|
11085
10975
|
targeting: metaTargetingSchema.optional()
|
|
11086
10976
|
}).superRefine((p, ctx) => {
|
|
11087
10977
|
if (!Object.values(p).some((val) => val !== void 0)) {
|
|
@@ -11089,38 +10979,38 @@ var adSetUpdateSchema = z10.object({
|
|
|
11089
10979
|
}
|
|
11090
10980
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11091
10981
|
});
|
|
11092
|
-
var messageSchema =
|
|
11093
|
-
var headlineSchema2 =
|
|
11094
|
-
var descriptionSchema =
|
|
11095
|
-
var callToActionSchema =
|
|
11096
|
-
type:
|
|
10982
|
+
var messageSchema = z9.string().min(1).max(META_LIMITS.creative.messageHardMax);
|
|
10983
|
+
var headlineSchema2 = z9.string().min(1).max(META_LIMITS.creative.headlineMax);
|
|
10984
|
+
var descriptionSchema = z9.string().min(1).max(META_LIMITS.creative.descriptionMax);
|
|
10985
|
+
var callToActionSchema = z9.object({
|
|
10986
|
+
type: z9.enum(CTA_TYPES2),
|
|
11097
10987
|
/** Overrides the base link for the CTA button; defaults to the ad's link. */
|
|
11098
10988
|
link: httpsUrlSchema3.optional()
|
|
11099
10989
|
});
|
|
11100
|
-
var creativeEnhancementsSchema =
|
|
11101
|
-
standardEnhancements:
|
|
11102
|
-
features:
|
|
10990
|
+
var creativeEnhancementsSchema = z9.object({
|
|
10991
|
+
standardEnhancements: z9.enum(ENROLL_STATUSES).optional(),
|
|
10992
|
+
features: z9.record(z9.string(), z9.enum(ENROLL_STATUSES)).optional()
|
|
11103
10993
|
});
|
|
11104
10994
|
var creativeSharedFields = {
|
|
11105
|
-
name:
|
|
10995
|
+
name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
|
|
11106
10996
|
/** Facebook Page id backing the ad's identity. */
|
|
11107
10997
|
page_id: parentRefSchema2,
|
|
11108
10998
|
/** Instagram account id for IG placements (aka instagram_actor_id on read). */
|
|
11109
|
-
instagram_user_id:
|
|
10999
|
+
instagram_user_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
11110
11000
|
/** URL tracking parameters appended to the destination, e.g. "utm_source=fb&utm_campaign=x". */
|
|
11111
|
-
url_tags:
|
|
11001
|
+
url_tags: z9.string().max(1e3).optional(),
|
|
11112
11002
|
enhancements: creativeEnhancementsSchema.optional()
|
|
11113
11003
|
};
|
|
11114
11004
|
var imageMediaFields = {
|
|
11115
|
-
imageHash:
|
|
11005
|
+
imageHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
|
|
11116
11006
|
imageRef: tempRefSchema3.optional()
|
|
11117
11007
|
};
|
|
11118
11008
|
var videoMediaFields = {
|
|
11119
|
-
videoId:
|
|
11009
|
+
videoId: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
11120
11010
|
videoRef: tempRefSchema3.optional(),
|
|
11121
11011
|
/** Thumbnail for a video creative — image hash, ref, or public url. */
|
|
11122
|
-
thumbnailHash:
|
|
11123
|
-
imageUrl:
|
|
11012
|
+
thumbnailHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
|
|
11013
|
+
imageUrl: z9.string().url().optional()
|
|
11124
11014
|
};
|
|
11125
11015
|
function countImageRefs(p) {
|
|
11126
11016
|
return [p.imageHash, p.imageRef].filter(Boolean).length;
|
|
@@ -11128,8 +11018,8 @@ function countImageRefs(p) {
|
|
|
11128
11018
|
function countVideoRefs(p) {
|
|
11129
11019
|
return [p.videoId, p.videoRef].filter(Boolean).length;
|
|
11130
11020
|
}
|
|
11131
|
-
var singleCreativeSchema =
|
|
11132
|
-
creativeType:
|
|
11021
|
+
var singleCreativeSchema = z9.object({
|
|
11022
|
+
creativeType: z9.literal("single"),
|
|
11133
11023
|
...creativeSharedFields,
|
|
11134
11024
|
/** Primary text. */
|
|
11135
11025
|
message: messageSchema,
|
|
@@ -11138,7 +11028,7 @@ var singleCreativeSchema = z10.object({
|
|
|
11138
11028
|
headline: headlineSchema2.optional(),
|
|
11139
11029
|
description: descriptionSchema.optional(),
|
|
11140
11030
|
/** Display URL / caption shown under the headline. */
|
|
11141
|
-
caption:
|
|
11031
|
+
caption: z9.string().max(255).optional(),
|
|
11142
11032
|
call_to_action: callToActionSchema.optional(),
|
|
11143
11033
|
...imageMediaFields,
|
|
11144
11034
|
...videoMediaFields
|
|
@@ -11162,10 +11052,10 @@ var singleCreativeSchema = z10.object({
|
|
|
11162
11052
|
});
|
|
11163
11053
|
}
|
|
11164
11054
|
});
|
|
11165
|
-
var carouselCardSchema =
|
|
11055
|
+
var carouselCardSchema = z9.object({
|
|
11166
11056
|
link: httpsUrlSchema3,
|
|
11167
|
-
headline:
|
|
11168
|
-
description:
|
|
11057
|
+
headline: z9.string().max(META_LIMITS.creative.headlineMax).optional(),
|
|
11058
|
+
description: z9.string().max(META_LIMITS.creative.descriptionMax).optional(),
|
|
11169
11059
|
call_to_action: callToActionSchema.optional(),
|
|
11170
11060
|
...imageMediaFields,
|
|
11171
11061
|
...videoMediaFields
|
|
@@ -11185,35 +11075,35 @@ var carouselCardSchema = z10.object({
|
|
|
11185
11075
|
ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
|
|
11186
11076
|
}
|
|
11187
11077
|
});
|
|
11188
|
-
var carouselCreativeSchema2 =
|
|
11189
|
-
creativeType:
|
|
11078
|
+
var carouselCreativeSchema2 = z9.object({
|
|
11079
|
+
creativeType: z9.literal("carousel"),
|
|
11190
11080
|
...creativeSharedFields,
|
|
11191
11081
|
message: messageSchema,
|
|
11192
11082
|
/** Optional "see more" card destination applied when a card has no own link. */
|
|
11193
11083
|
link: httpsUrlSchema3.optional(),
|
|
11194
11084
|
call_to_action: callToActionSchema.optional(),
|
|
11195
|
-
cards:
|
|
11085
|
+
cards: z9.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax)
|
|
11196
11086
|
});
|
|
11197
|
-
var dynamicImageSchema =
|
|
11198
|
-
var dynamicVideoSchema =
|
|
11087
|
+
var dynamicImageSchema = z9.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
|
|
11088
|
+
var dynamicVideoSchema = z9.object({
|
|
11199
11089
|
videoId: videoMediaFields.videoId,
|
|
11200
11090
|
videoRef: videoMediaFields.videoRef,
|
|
11201
11091
|
thumbnailHash: videoMediaFields.thumbnailHash
|
|
11202
11092
|
}).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
|
|
11203
11093
|
var DYN = META_LIMITS.creative;
|
|
11204
|
-
var dynamicCreativeSchema =
|
|
11205
|
-
creativeType:
|
|
11094
|
+
var dynamicCreativeSchema = z9.object({
|
|
11095
|
+
creativeType: z9.literal("dynamic"),
|
|
11206
11096
|
...creativeSharedFields,
|
|
11207
|
-
bodies:
|
|
11208
|
-
titles:
|
|
11209
|
-
descriptions:
|
|
11210
|
-
images:
|
|
11211
|
-
videos:
|
|
11212
|
-
ad_formats:
|
|
11213
|
-
call_to_action_types:
|
|
11214
|
-
link_urls:
|
|
11097
|
+
bodies: z9.array(z9.object({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
|
|
11098
|
+
titles: z9.array(z9.object({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
|
|
11099
|
+
descriptions: z9.array(z9.object({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
|
|
11100
|
+
images: z9.array(dynamicImageSchema).optional(),
|
|
11101
|
+
videos: z9.array(dynamicVideoSchema).optional(),
|
|
11102
|
+
ad_formats: z9.array(z9.enum(AD_FORMATS2)).min(1),
|
|
11103
|
+
call_to_action_types: z9.array(z9.enum(CTA_TYPES2)).optional(),
|
|
11104
|
+
link_urls: z9.array(z9.object({ website_url: httpsUrlSchema3, display_url: z9.string().optional() })).min(1),
|
|
11215
11105
|
/** Multi-language / placement customization — structural passthrough for v1. */
|
|
11216
|
-
asset_customization_rules:
|
|
11106
|
+
asset_customization_rules: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11217
11107
|
}).superRefine((p, ctx) => {
|
|
11218
11108
|
if (!(p.images?.length || p.videos?.length)) {
|
|
11219
11109
|
ctx.addIssue({
|
|
@@ -11223,57 +11113,57 @@ var dynamicCreativeSchema = z10.object({
|
|
|
11223
11113
|
});
|
|
11224
11114
|
}
|
|
11225
11115
|
});
|
|
11226
|
-
var existingPostCreativeSchema =
|
|
11227
|
-
creativeType:
|
|
11116
|
+
var existingPostCreativeSchema = z9.object({
|
|
11117
|
+
creativeType: z9.literal("existing_post"),
|
|
11228
11118
|
name: creativeSharedFields.name,
|
|
11229
11119
|
/** "<page_id>_<post_id>" object story id of the post to promote. */
|
|
11230
|
-
object_story_id:
|
|
11120
|
+
object_story_id: z9.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
|
|
11231
11121
|
instagram_user_id: creativeSharedFields.instagram_user_id,
|
|
11232
11122
|
url_tags: creativeSharedFields.url_tags,
|
|
11233
11123
|
enhancements: creativeSharedFields.enhancements
|
|
11234
11124
|
});
|
|
11235
|
-
var creativeContentSchema2 =
|
|
11125
|
+
var creativeContentSchema2 = z9.discriminatedUnion("creativeType", [
|
|
11236
11126
|
singleCreativeSchema,
|
|
11237
11127
|
carouselCreativeSchema2,
|
|
11238
11128
|
dynamicCreativeSchema,
|
|
11239
11129
|
existingPostCreativeSchema
|
|
11240
11130
|
]);
|
|
11241
11131
|
var adCreativeCreateSchema = creativeContentSchema2;
|
|
11242
|
-
var adCreativeUpdateSchema =
|
|
11243
|
-
name:
|
|
11132
|
+
var adCreativeUpdateSchema = z9.object({
|
|
11133
|
+
name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
|
|
11244
11134
|
status: updateStatusSchema.optional(),
|
|
11245
11135
|
/** Content patch — only honored when the target is a staged meta_temp_* creative. */
|
|
11246
|
-
content:
|
|
11136
|
+
content: z9.record(z9.string(), z9.unknown()).optional()
|
|
11247
11137
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11248
|
-
var adCreateSchema2 =
|
|
11249
|
-
name:
|
|
11138
|
+
var adCreateSchema2 = z9.object({
|
|
11139
|
+
name: z9.string().min(1).max(META_LIMITS.ad.nameMax),
|
|
11250
11140
|
adset_id: parentRefSchema2,
|
|
11251
11141
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
11252
|
-
creative:
|
|
11142
|
+
creative: z9.object({ creative_id: parentRefSchema2 }),
|
|
11253
11143
|
/** Conversion pixel / offline event set / view tags — structural passthrough. */
|
|
11254
|
-
tracking_specs:
|
|
11144
|
+
tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11255
11145
|
});
|
|
11256
|
-
var adUpdateSchema2 =
|
|
11257
|
-
name:
|
|
11146
|
+
var adUpdateSchema2 = z9.object({
|
|
11147
|
+
name: z9.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
|
|
11258
11148
|
status: updateStatusSchema.optional(),
|
|
11259
11149
|
/** Swapping the creative is the Meta way to "edit" an ad's creative. */
|
|
11260
|
-
creative:
|
|
11261
|
-
tracking_specs:
|
|
11150
|
+
creative: z9.object({ creative_id: parentRefSchema2 }).optional(),
|
|
11151
|
+
tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11262
11152
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11263
|
-
var lookalikeSpecSchema =
|
|
11264
|
-
origin:
|
|
11265
|
-
ratio:
|
|
11266
|
-
country:
|
|
11267
|
-
});
|
|
11268
|
-
var customAudienceCreateSchema =
|
|
11269
|
-
name:
|
|
11270
|
-
subtype:
|
|
11271
|
-
description:
|
|
11272
|
-
customer_file_source:
|
|
11273
|
-
retention_days:
|
|
11153
|
+
var lookalikeSpecSchema = z9.object({
|
|
11154
|
+
origin: z9.array(z9.object({ id: parentRefSchema2 })).min(1),
|
|
11155
|
+
ratio: z9.number().min(0.01).max(0.2).optional(),
|
|
11156
|
+
country: z9.string().length(2).optional()
|
|
11157
|
+
});
|
|
11158
|
+
var customAudienceCreateSchema = z9.object({
|
|
11159
|
+
name: z9.string().min(1).max(META_LIMITS.audience.nameMax),
|
|
11160
|
+
subtype: z9.enum(CUSTOM_AUDIENCE_SUBTYPES),
|
|
11161
|
+
description: z9.string().max(500).optional(),
|
|
11162
|
+
customer_file_source: z9.string().optional(),
|
|
11163
|
+
retention_days: z9.number().int().min(1).max(META_LIMITS.audience.retentionDaysMax).optional(),
|
|
11274
11164
|
lookalike_spec: lookalikeSpecSchema.optional(),
|
|
11275
11165
|
/** Website/engagement rule — structural passthrough validated by Meta. */
|
|
11276
|
-
rule:
|
|
11166
|
+
rule: z9.record(z9.string(), z9.unknown()).optional()
|
|
11277
11167
|
}).superRefine((p, ctx) => {
|
|
11278
11168
|
if (p.subtype === "LOOKALIKE" && !p.lookalike_spec) {
|
|
11279
11169
|
ctx.addIssue({ code: "custom", path: ["lookalike_spec"], message: "LOOKALIKE audiences need a lookalike_spec" });
|
|
@@ -11282,16 +11172,16 @@ var customAudienceCreateSchema = z10.object({
|
|
|
11282
11172
|
ctx.addIssue({ code: "custom", path: ["rule"], message: `${p.subtype} audiences need a rule (use --file)` });
|
|
11283
11173
|
}
|
|
11284
11174
|
});
|
|
11285
|
-
var customAudienceUpdateSchema =
|
|
11286
|
-
name:
|
|
11287
|
-
description:
|
|
11175
|
+
var customAudienceUpdateSchema = z9.object({
|
|
11176
|
+
name: z9.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
|
|
11177
|
+
description: z9.string().max(500).optional()
|
|
11288
11178
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11289
|
-
var mediaUploadSchema =
|
|
11290
|
-
kind:
|
|
11179
|
+
var mediaUploadSchema = z9.object({
|
|
11180
|
+
kind: z9.enum(MEDIA_KINDS),
|
|
11291
11181
|
bakerImageId: bakerMediaIdSchema2.optional(),
|
|
11292
11182
|
bakerVideoId: bakerMediaIdSchema2.optional(),
|
|
11293
11183
|
/** Optional display name / filename hint. */
|
|
11294
|
-
name:
|
|
11184
|
+
name: z9.string().max(255).optional()
|
|
11295
11185
|
}).superRefine((p, ctx) => {
|
|
11296
11186
|
if (p.kind === "image" && !p.bakerImageId) {
|
|
11297
11187
|
ctx.addIssue({ code: "custom", path: ["bakerImageId"], message: "image uploads need a bakerImageId" });
|
|
@@ -11313,16 +11203,16 @@ var META_DRAFT_OP_KINDS = [
|
|
|
11313
11203
|
"customAudience.update",
|
|
11314
11204
|
"media.upload"
|
|
11315
11205
|
];
|
|
11316
|
-
var metaDraftOpKindSchema =
|
|
11317
|
-
var accountIdSchema2 =
|
|
11318
|
-
var updateTargetSchema2 =
|
|
11206
|
+
var metaDraftOpKindSchema = z9.enum(META_DRAFT_OP_KINDS);
|
|
11207
|
+
var accountIdSchema2 = z9.string().regex(NUMERIC_ID_REGEX3, "accountId must be the bare numeric ad account id");
|
|
11208
|
+
var updateTargetSchema2 = z9.union([z9.string().regex(NUMERIC_ID_REGEX3), tempRefSchema3]);
|
|
11319
11209
|
function createOp3(kind, payload) {
|
|
11320
|
-
return
|
|
11210
|
+
return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, payload });
|
|
11321
11211
|
}
|
|
11322
11212
|
function updateOp3(kind, payload) {
|
|
11323
|
-
return
|
|
11213
|
+
return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, target: updateTargetSchema2, payload });
|
|
11324
11214
|
}
|
|
11325
|
-
var metaDraftOpInputSchema =
|
|
11215
|
+
var metaDraftOpInputSchema = z9.discriminatedUnion("kind", [
|
|
11326
11216
|
createOp3("campaign.create", campaignCreateSchema3),
|
|
11327
11217
|
updateOp3("campaign.update", campaignUpdateSchema3),
|
|
11328
11218
|
createOp3("adSet.create", adSetCreateSchema),
|
|
@@ -11337,89 +11227,89 @@ var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
|
|
|
11337
11227
|
]);
|
|
11338
11228
|
|
|
11339
11229
|
// ../api/src/ads-meta/wire.ts
|
|
11340
|
-
import { z as
|
|
11341
|
-
var metaWriteModeSchema =
|
|
11342
|
-
var metaDraftOpResultSchema =
|
|
11343
|
-
status:
|
|
11230
|
+
import { z as z10 } from "zod";
|
|
11231
|
+
var metaWriteModeSchema = z10.enum(["live", "simulated"]);
|
|
11232
|
+
var metaDraftOpResultSchema = z10.object({
|
|
11233
|
+
status: z10.enum(["applied", "simulated", "failed", "skipped"]),
|
|
11344
11234
|
/** The resulting Meta node id (campaign/adset/creative/ad/audience) or simulated id. */
|
|
11345
|
-
id:
|
|
11235
|
+
id: z10.string().optional(),
|
|
11346
11236
|
/** For media.upload ops: the resulting image hash. */
|
|
11347
|
-
hash:
|
|
11348
|
-
error:
|
|
11349
|
-
skippedBecause:
|
|
11350
|
-
executedAt:
|
|
11237
|
+
hash: z10.string().optional(),
|
|
11238
|
+
error: z10.string().optional(),
|
|
11239
|
+
skippedBecause: z10.string().optional(),
|
|
11240
|
+
executedAt: z10.number().optional()
|
|
11351
11241
|
});
|
|
11352
|
-
var metaDraftStageRequestSchema =
|
|
11353
|
-
chatId:
|
|
11242
|
+
var metaDraftStageRequestSchema = z10.object({
|
|
11243
|
+
chatId: z10.string(),
|
|
11354
11244
|
op: metaDraftOpInputSchema
|
|
11355
11245
|
});
|
|
11356
|
-
var metaDraftStageResponseSchema =
|
|
11357
|
-
staged:
|
|
11358
|
-
ref:
|
|
11246
|
+
var metaDraftStageResponseSchema = z10.object({
|
|
11247
|
+
staged: z10.literal(true),
|
|
11248
|
+
ref: z10.string(),
|
|
11359
11249
|
kind: metaDraftOpKindSchema,
|
|
11360
11250
|
mode: metaWriteModeSchema,
|
|
11361
|
-
dependsOn:
|
|
11362
|
-
summary:
|
|
11363
|
-
warnings:
|
|
11251
|
+
dependsOn: z10.array(z10.string()),
|
|
11252
|
+
summary: z10.string(),
|
|
11253
|
+
warnings: z10.array(z10.string()),
|
|
11364
11254
|
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
11365
|
-
amended:
|
|
11366
|
-
});
|
|
11367
|
-
var metaDraftDuplicateRequestSchema =
|
|
11368
|
-
chatId:
|
|
11369
|
-
accountId:
|
|
11370
|
-
entity:
|
|
11371
|
-
sourceId:
|
|
11372
|
-
overrides:
|
|
11255
|
+
amended: z10.boolean().optional()
|
|
11256
|
+
});
|
|
11257
|
+
var metaDraftDuplicateRequestSchema = z10.object({
|
|
11258
|
+
chatId: z10.string(),
|
|
11259
|
+
accountId: z10.string(),
|
|
11260
|
+
entity: z10.enum(["campaign", "adSet", "ad"]),
|
|
11261
|
+
sourceId: z10.string(),
|
|
11262
|
+
overrides: z10.record(z10.string(), z10.unknown()).optional(),
|
|
11373
11263
|
/** Pause the original after the copy publishes. */
|
|
11374
|
-
replace:
|
|
11264
|
+
replace: z10.boolean().optional()
|
|
11375
11265
|
});
|
|
11376
|
-
var metaDraftOpViewSchema =
|
|
11377
|
-
ref:
|
|
11266
|
+
var metaDraftOpViewSchema = z10.object({
|
|
11267
|
+
ref: z10.string(),
|
|
11378
11268
|
kind: metaDraftOpKindSchema,
|
|
11379
|
-
accountId:
|
|
11380
|
-
target:
|
|
11381
|
-
dependsOn:
|
|
11382
|
-
summary:
|
|
11383
|
-
stagedAt:
|
|
11269
|
+
accountId: z10.string(),
|
|
11270
|
+
target: z10.string().optional(),
|
|
11271
|
+
dependsOn: z10.array(z10.string()),
|
|
11272
|
+
summary: z10.string(),
|
|
11273
|
+
stagedAt: z10.number(),
|
|
11384
11274
|
result: metaDraftOpResultSchema.optional()
|
|
11385
11275
|
});
|
|
11386
|
-
var metaDraftListRequestSchema =
|
|
11387
|
-
chatId:
|
|
11276
|
+
var metaDraftListRequestSchema = z10.object({
|
|
11277
|
+
chatId: z10.string()
|
|
11388
11278
|
});
|
|
11389
|
-
var metaDraftAdvisorySchema =
|
|
11390
|
-
ref:
|
|
11391
|
-
message:
|
|
11279
|
+
var metaDraftAdvisorySchema = z10.object({
|
|
11280
|
+
ref: z10.string(),
|
|
11281
|
+
message: z10.string()
|
|
11392
11282
|
});
|
|
11393
|
-
var metaDraftListResponseSchema =
|
|
11394
|
-
status:
|
|
11283
|
+
var metaDraftListResponseSchema = z10.object({
|
|
11284
|
+
status: z10.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
11395
11285
|
mode: metaWriteModeSchema,
|
|
11396
|
-
count:
|
|
11397
|
-
ops:
|
|
11286
|
+
count: z10.number(),
|
|
11287
|
+
ops: z10.array(metaDraftOpViewSchema),
|
|
11398
11288
|
/** Non-blocking cross-op quality advisories — "good campaign, not just valid". */
|
|
11399
|
-
advisories:
|
|
11289
|
+
advisories: z10.array(metaDraftAdvisorySchema)
|
|
11400
11290
|
});
|
|
11401
|
-
var metaDraftRemoveRequestSchema =
|
|
11402
|
-
chatId:
|
|
11403
|
-
ref:
|
|
11291
|
+
var metaDraftRemoveRequestSchema = z10.object({
|
|
11292
|
+
chatId: z10.string(),
|
|
11293
|
+
ref: z10.string()
|
|
11404
11294
|
});
|
|
11405
|
-
var metaDraftRemoveResponseSchema =
|
|
11295
|
+
var metaDraftRemoveResponseSchema = z10.object({
|
|
11406
11296
|
/** The requested ref plus any dependents removed by cascade. */
|
|
11407
|
-
removed:
|
|
11297
|
+
removed: z10.array(z10.string())
|
|
11408
11298
|
});
|
|
11409
|
-
var metaDraftClearRequestSchema =
|
|
11410
|
-
chatId:
|
|
11299
|
+
var metaDraftClearRequestSchema = z10.object({
|
|
11300
|
+
chatId: z10.string()
|
|
11411
11301
|
});
|
|
11412
|
-
var metaDraftClearResponseSchema =
|
|
11413
|
-
cleared:
|
|
11302
|
+
var metaDraftClearResponseSchema = z10.object({
|
|
11303
|
+
cleared: z10.number()
|
|
11414
11304
|
});
|
|
11415
|
-
var metaFieldErrorSchema =
|
|
11416
|
-
path:
|
|
11417
|
-
message:
|
|
11305
|
+
var metaFieldErrorSchema = z10.object({
|
|
11306
|
+
path: z10.string(),
|
|
11307
|
+
message: z10.string()
|
|
11418
11308
|
});
|
|
11419
|
-
var metaDraftErrorResponseSchema =
|
|
11420
|
-
code:
|
|
11421
|
-
error:
|
|
11422
|
-
fields:
|
|
11309
|
+
var metaDraftErrorResponseSchema = z10.object({
|
|
11310
|
+
code: z10.string(),
|
|
11311
|
+
error: z10.string(),
|
|
11312
|
+
fields: z10.array(metaFieldErrorSchema).optional()
|
|
11423
11313
|
});
|
|
11424
11314
|
|
|
11425
11315
|
// src/commands/ads/meta/write-shared.ts
|
|
@@ -11430,19 +11320,19 @@ function failWriteValidation3(message) {
|
|
|
11430
11320
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
11431
11321
|
process.exit(1);
|
|
11432
11322
|
}
|
|
11433
|
-
function loadJsonFileArg3(
|
|
11434
|
-
if (typeof
|
|
11323
|
+
function loadJsonFileArg3(path14) {
|
|
11324
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
11435
11325
|
return {};
|
|
11436
11326
|
}
|
|
11437
11327
|
try {
|
|
11438
|
-
const parsed = JSON.parse(readFileSync8(
|
|
11328
|
+
const parsed = JSON.parse(readFileSync8(path14, "utf8"));
|
|
11439
11329
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11440
|
-
failWriteValidation3(`${
|
|
11330
|
+
failWriteValidation3(`${path14} must contain a JSON object`);
|
|
11441
11331
|
}
|
|
11442
11332
|
return parsed;
|
|
11443
11333
|
} catch (err) {
|
|
11444
11334
|
if (err instanceof SyntaxError) {
|
|
11445
|
-
failWriteValidation3(`${
|
|
11335
|
+
failWriteValidation3(`${path14} is not valid JSON: ${err.message}`);
|
|
11446
11336
|
}
|
|
11447
11337
|
throw err;
|
|
11448
11338
|
}
|
|
@@ -14505,7 +14395,7 @@ async function probeDuration(filePath) {
|
|
|
14505
14395
|
|
|
14506
14396
|
// src/commands/canvas/run.ts
|
|
14507
14397
|
import { readFile as readFile2 } from "fs/promises";
|
|
14508
|
-
import
|
|
14398
|
+
import path5 from "path";
|
|
14509
14399
|
import { defineCommand as defineCommand88 } from "citty";
|
|
14510
14400
|
|
|
14511
14401
|
// src/commands/canvas/placeholders.ts
|
|
@@ -14549,9 +14439,265 @@ function isResolvableRelative(value) {
|
|
|
14549
14439
|
return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
|
|
14550
14440
|
}
|
|
14551
14441
|
|
|
14442
|
+
// src/commands/canvas/run-record.ts
|
|
14443
|
+
import path3 from "path";
|
|
14444
|
+
var MAX_RUN_NODES = 200;
|
|
14445
|
+
var MAX_OUTPUTS_PER_NODE = 10;
|
|
14446
|
+
var MAX_FINAL_OUTPUTS = 10;
|
|
14447
|
+
var MAX_PARAMS_PREVIEW_LENGTH = 4e3;
|
|
14448
|
+
function paramsPreviewFromParams(params) {
|
|
14449
|
+
if (params === void 0 || params === null) return void 0;
|
|
14450
|
+
const text = humanParamText(params, "prompt") ?? humanParamText(params, "source") ?? compactJson(params);
|
|
14451
|
+
if (!text) return void 0;
|
|
14452
|
+
return text.length > MAX_PARAMS_PREVIEW_LENGTH ? `${text.slice(0, MAX_PARAMS_PREVIEW_LENGTH - 1)}\u2026` : text;
|
|
14453
|
+
}
|
|
14454
|
+
function humanParamText(params, key) {
|
|
14455
|
+
const value = params[key];
|
|
14456
|
+
if (typeof value !== "string") return void 0;
|
|
14457
|
+
const trimmed = value.trim();
|
|
14458
|
+
return trimmed && !trimmed.startsWith("$ref:") ? trimmed : void 0;
|
|
14459
|
+
}
|
|
14460
|
+
function compactJson(params) {
|
|
14461
|
+
try {
|
|
14462
|
+
const json = JSON.stringify(params);
|
|
14463
|
+
return json && json !== "{}" ? json : void 0;
|
|
14464
|
+
} catch {
|
|
14465
|
+
return void 0;
|
|
14466
|
+
}
|
|
14467
|
+
}
|
|
14468
|
+
var MAX_CREATIVE_SLUG_LENGTH = 100;
|
|
14469
|
+
function creativeSlugFromCanvasPath(filePath) {
|
|
14470
|
+
const normalized = filePath.split(path3.sep).join("/");
|
|
14471
|
+
const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
|
|
14472
|
+
const slug = match?.[1] ?? null;
|
|
14473
|
+
return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
|
|
14474
|
+
}
|
|
14475
|
+
var OUTPUT_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
|
|
14476
|
+
function toRecordOutput(slot, value) {
|
|
14477
|
+
const refs = collectAssetRefLikes(value);
|
|
14478
|
+
const ref = refs.length === 1 ? refs[0] : null;
|
|
14479
|
+
if (!ref || !isPersistedAssetRef(ref)) return null;
|
|
14480
|
+
const kind = typeof ref.kind === "string" && OUTPUT_KINDS.has(ref.kind) ? ref.kind : null;
|
|
14481
|
+
if (!kind) return null;
|
|
14482
|
+
return {
|
|
14483
|
+
slot,
|
|
14484
|
+
kind,
|
|
14485
|
+
sha256: ref.sha256,
|
|
14486
|
+
url: ref.url,
|
|
14487
|
+
mime: ref.mime,
|
|
14488
|
+
width: typeof ref.width === "number" ? ref.width : void 0,
|
|
14489
|
+
height: typeof ref.height === "number" ? ref.height : void 0,
|
|
14490
|
+
durationMs: typeof ref.duration_ms === "number" ? ref.duration_ms : void 0
|
|
14491
|
+
};
|
|
14492
|
+
}
|
|
14493
|
+
function nodeOutputsToRecord(nodeOutputs) {
|
|
14494
|
+
const out = [];
|
|
14495
|
+
for (const [slot, value] of Object.entries(nodeOutputs)) {
|
|
14496
|
+
if (Array.isArray(value)) {
|
|
14497
|
+
value.forEach((item, i) => {
|
|
14498
|
+
const rec = toRecordOutput(`${slot}#${i}`, item);
|
|
14499
|
+
if (rec) out.push(rec);
|
|
14500
|
+
});
|
|
14501
|
+
} else {
|
|
14502
|
+
const rec = toRecordOutput(slot, value);
|
|
14503
|
+
if (rec) out.push(rec);
|
|
14504
|
+
}
|
|
14505
|
+
}
|
|
14506
|
+
return out.slice(0, MAX_OUTPUTS_PER_NODE);
|
|
14507
|
+
}
|
|
14508
|
+
function finalOutputsToRecord(output) {
|
|
14509
|
+
if (Array.isArray(output)) {
|
|
14510
|
+
return output.map((item, i) => toRecordOutput(`final#${i}`, item)).filter((rec2) => rec2 !== null).slice(0, MAX_FINAL_OUTPUTS);
|
|
14511
|
+
}
|
|
14512
|
+
const rec = toRecordOutput("final", output);
|
|
14513
|
+
return rec ? [rec] : [];
|
|
14514
|
+
}
|
|
14515
|
+
function buildRunRecord(result, meta, plan) {
|
|
14516
|
+
const nodes = result.node_runs.slice(0, MAX_RUN_NODES).map((run) => {
|
|
14517
|
+
const planned = plan?.get(run.node_id);
|
|
14518
|
+
return {
|
|
14519
|
+
nodeId: run.node_id,
|
|
14520
|
+
nodeType: run.node_type,
|
|
14521
|
+
cached: run.cached,
|
|
14522
|
+
credits: run.credits,
|
|
14523
|
+
durationMs: run.duration_ms,
|
|
14524
|
+
outputs: nodeOutputsToRecord(result.outputs_by_node[run.node_id] ?? {}),
|
|
14525
|
+
deps: planned?.deps,
|
|
14526
|
+
status: plan ? "completed" : void 0,
|
|
14527
|
+
paramsPreview: planned?.paramsPreview
|
|
14528
|
+
};
|
|
14529
|
+
});
|
|
14530
|
+
const finalOutputs = finalOutputsToRecord(result.output);
|
|
14531
|
+
return {
|
|
14532
|
+
runId: result.run_id,
|
|
14533
|
+
creativeSlug: meta.creativeSlug,
|
|
14534
|
+
canvasPath: meta.canvasPath,
|
|
14535
|
+
canvasSha: meta.canvasSha,
|
|
14536
|
+
chatId: meta.chatId,
|
|
14537
|
+
status: "completed",
|
|
14538
|
+
stats: {
|
|
14539
|
+
totalNodes: result.stats.total_nodes,
|
|
14540
|
+
cachedNodes: result.stats.cached_nodes,
|
|
14541
|
+
totalCredits: result.stats.total_credits,
|
|
14542
|
+
durationMs: result.stats.duration_ms
|
|
14543
|
+
},
|
|
14544
|
+
nodes,
|
|
14545
|
+
finalOutputs: finalOutputs.length > 0 ? finalOutputs : void 0
|
|
14546
|
+
};
|
|
14547
|
+
}
|
|
14548
|
+
function buildFailedRunRecord(runId, errorMessage, meta) {
|
|
14549
|
+
return {
|
|
14550
|
+
runId,
|
|
14551
|
+
creativeSlug: meta.creativeSlug,
|
|
14552
|
+
canvasPath: meta.canvasPath,
|
|
14553
|
+
canvasSha: meta.canvasSha,
|
|
14554
|
+
chatId: meta.chatId,
|
|
14555
|
+
status: "failed",
|
|
14556
|
+
errorMessage: errorMessage.slice(0, 2e3),
|
|
14557
|
+
stats: { totalNodes: 0, cachedNodes: 0, totalCredits: 0, durationMs: 0 },
|
|
14558
|
+
nodes: []
|
|
14559
|
+
};
|
|
14560
|
+
}
|
|
14561
|
+
|
|
14562
|
+
// src/commands/canvas/run-progress.ts
|
|
14563
|
+
var RunProgressTracker = class {
|
|
14564
|
+
runId;
|
|
14565
|
+
meta;
|
|
14566
|
+
startedAt;
|
|
14567
|
+
nodes = /* @__PURE__ */ new Map();
|
|
14568
|
+
planned = false;
|
|
14569
|
+
constructor(runId, meta) {
|
|
14570
|
+
this.runId = runId;
|
|
14571
|
+
this.meta = meta;
|
|
14572
|
+
this.startedAt = Date.now();
|
|
14573
|
+
}
|
|
14574
|
+
apply(event) {
|
|
14575
|
+
if (event.kind === "plan") {
|
|
14576
|
+
for (const node of event.nodes) {
|
|
14577
|
+
this.nodes.set(node.node_id, {
|
|
14578
|
+
nodeId: node.node_id,
|
|
14579
|
+
nodeType: node.node_type,
|
|
14580
|
+
cached: false,
|
|
14581
|
+
credits: 0,
|
|
14582
|
+
durationMs: 0,
|
|
14583
|
+
outputs: [],
|
|
14584
|
+
deps: node.deps,
|
|
14585
|
+
status: "pending",
|
|
14586
|
+
paramsPreview: paramsPreviewFromParams(node.params)
|
|
14587
|
+
});
|
|
14588
|
+
}
|
|
14589
|
+
this.planned = true;
|
|
14590
|
+
return;
|
|
14591
|
+
}
|
|
14592
|
+
if (event.kind === "node_start") {
|
|
14593
|
+
this.patchNode(event.node_id, { status: "running" });
|
|
14594
|
+
return;
|
|
14595
|
+
}
|
|
14596
|
+
if (event.kind === "node_settled") {
|
|
14597
|
+
this.patchNode(event.run.node_id, {
|
|
14598
|
+
status: "completed",
|
|
14599
|
+
cached: event.run.cached,
|
|
14600
|
+
credits: event.run.credits,
|
|
14601
|
+
durationMs: event.run.duration_ms,
|
|
14602
|
+
outputs: nodeOutputsToRecord(event.outputs)
|
|
14603
|
+
});
|
|
14604
|
+
return;
|
|
14605
|
+
}
|
|
14606
|
+
this.patchNode(event.node_id, { status: "failed" });
|
|
14607
|
+
}
|
|
14608
|
+
/** True once the plan event landed — before that there is nothing worth posting. */
|
|
14609
|
+
hasPlan() {
|
|
14610
|
+
return this.planned;
|
|
14611
|
+
}
|
|
14612
|
+
/** Plan facts (deps + params preview) for stamping the terminal record's nodes. */
|
|
14613
|
+
planInfo() {
|
|
14614
|
+
const info = /* @__PURE__ */ new Map();
|
|
14615
|
+
for (const node of this.nodes.values()) {
|
|
14616
|
+
info.set(node.nodeId, { deps: node.deps ?? [], paramsPreview: node.paramsPreview });
|
|
14617
|
+
}
|
|
14618
|
+
return info;
|
|
14619
|
+
}
|
|
14620
|
+
/** The current in-flight state as a postable full record. */
|
|
14621
|
+
snapshot() {
|
|
14622
|
+
const nodes = [...this.nodes.values()];
|
|
14623
|
+
return {
|
|
14624
|
+
runId: this.runId,
|
|
14625
|
+
...this.meta,
|
|
14626
|
+
status: "running",
|
|
14627
|
+
stats: {
|
|
14628
|
+
totalNodes: nodes.length,
|
|
14629
|
+
cachedNodes: nodes.filter((n) => n.cached).length,
|
|
14630
|
+
totalCredits: nodes.reduce((sum, n) => sum + n.credits, 0),
|
|
14631
|
+
durationMs: Date.now() - this.startedAt
|
|
14632
|
+
},
|
|
14633
|
+
nodes
|
|
14634
|
+
};
|
|
14635
|
+
}
|
|
14636
|
+
/**
|
|
14637
|
+
* Terminal record for a failed run, preserving what each node got to —
|
|
14638
|
+
* completed nodes keep their outputs so the graph shows exactly where the
|
|
14639
|
+
* run died instead of an empty husk.
|
|
14640
|
+
*/
|
|
14641
|
+
failedSnapshot(errorMessage) {
|
|
14642
|
+
const snapshot = this.snapshot();
|
|
14643
|
+
return {
|
|
14644
|
+
...snapshot,
|
|
14645
|
+
status: "failed",
|
|
14646
|
+
errorMessage: errorMessage.slice(0, 2e3),
|
|
14647
|
+
stats: { ...snapshot.stats, durationMs: Date.now() - this.startedAt }
|
|
14648
|
+
};
|
|
14649
|
+
}
|
|
14650
|
+
patchNode(nodeId, patch) {
|
|
14651
|
+
const existing = this.nodes.get(nodeId);
|
|
14652
|
+
if (!existing) return;
|
|
14653
|
+
this.nodes.set(nodeId, { ...existing, ...patch, status: patch.status ?? existing.status });
|
|
14654
|
+
}
|
|
14655
|
+
};
|
|
14656
|
+
var RunRecordPoster = class {
|
|
14657
|
+
post;
|
|
14658
|
+
latest = null;
|
|
14659
|
+
inflight = null;
|
|
14660
|
+
warned = false;
|
|
14661
|
+
constructor(post) {
|
|
14662
|
+
this.post = post;
|
|
14663
|
+
}
|
|
14664
|
+
/** Queue a progress snapshot; returns immediately. */
|
|
14665
|
+
enqueue(payload) {
|
|
14666
|
+
this.latest = payload;
|
|
14667
|
+
if (!this.inflight) this.inflight = this.pump();
|
|
14668
|
+
}
|
|
14669
|
+
/**
|
|
14670
|
+
* Post the terminal record (awaited, errors surfaced to the caller). Any
|
|
14671
|
+
* queued progress snapshot is superseded — the terminal record is the full
|
|
14672
|
+
* state — but an in-flight POST is awaited first so it can't land after.
|
|
14673
|
+
*/
|
|
14674
|
+
async flush(terminal) {
|
|
14675
|
+
this.latest = null;
|
|
14676
|
+
if (this.inflight) await this.inflight;
|
|
14677
|
+
await this.post(terminal);
|
|
14678
|
+
}
|
|
14679
|
+
async pump() {
|
|
14680
|
+
while (this.latest) {
|
|
14681
|
+
const payload = this.latest;
|
|
14682
|
+
this.latest = null;
|
|
14683
|
+
try {
|
|
14684
|
+
await this.post(payload);
|
|
14685
|
+
} catch (e) {
|
|
14686
|
+
if (!this.warned) {
|
|
14687
|
+
this.warned = true;
|
|
14688
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14689
|
+
process.stderr.write(`[warn] live run progress not streaming (${msg})
|
|
14690
|
+
`);
|
|
14691
|
+
}
|
|
14692
|
+
}
|
|
14693
|
+
}
|
|
14694
|
+
this.inflight = null;
|
|
14695
|
+
}
|
|
14696
|
+
};
|
|
14697
|
+
|
|
14552
14698
|
// src/commands/canvas/run-retention.ts
|
|
14553
14699
|
import { rm } from "fs/promises";
|
|
14554
|
-
import
|
|
14700
|
+
import path4 from "path";
|
|
14555
14701
|
function runDirsToPrune(entries, keep, currentRunId) {
|
|
14556
14702
|
const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
|
|
14557
14703
|
if (keep <= 0) return runs;
|
|
@@ -14568,7 +14714,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
|
14568
14714
|
const toPrune = runDirsToPrune(entries, keep, currentRunId);
|
|
14569
14715
|
if (toPrune.length === 0) return;
|
|
14570
14716
|
for (const dir of toPrune) {
|
|
14571
|
-
await rm(
|
|
14717
|
+
await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
|
|
14572
14718
|
(e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
|
|
14573
14719
|
);
|
|
14574
14720
|
}
|
|
@@ -14595,10 +14741,22 @@ var runCommand = defineCommand88({
|
|
|
14595
14741
|
"keep-runs": {
|
|
14596
14742
|
type: "string",
|
|
14597
14743
|
description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
|
|
14744
|
+
},
|
|
14745
|
+
"remote-cache": {
|
|
14746
|
+
type: "string",
|
|
14747
|
+
description: "on | off \u2014 company-scoped remote cache + durable asset persistence (default on; env BAKER_CANVAS_REMOTE_CACHE)"
|
|
14748
|
+
},
|
|
14749
|
+
// citty consumes any `--no-<flag>` as a negation of `<flag>`, so the
|
|
14750
|
+
// opt-out spelling `--no-record` requires the flag to be named `record`
|
|
14751
|
+
// (a literal "no-record" arg would never receive a value).
|
|
14752
|
+
record: {
|
|
14753
|
+
type: "boolean",
|
|
14754
|
+
default: true,
|
|
14755
|
+
description: "Post the durable run-history record to Baker (disable with --no-record)"
|
|
14598
14756
|
}
|
|
14599
14757
|
},
|
|
14600
14758
|
async run({ args }) {
|
|
14601
|
-
const filePath =
|
|
14759
|
+
const filePath = path5.resolve(String(args.file));
|
|
14602
14760
|
const raw = await readFile2(filePath, "utf8");
|
|
14603
14761
|
let parsed;
|
|
14604
14762
|
try {
|
|
@@ -14609,7 +14767,7 @@ var runCommand = defineCommand88({
|
|
|
14609
14767
|
`);
|
|
14610
14768
|
process.exit(2);
|
|
14611
14769
|
}
|
|
14612
|
-
parsed = resolveRelativeCanvasPaths(parsed,
|
|
14770
|
+
parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
|
|
14613
14771
|
const pending = unsuppliedPlaceholderAssets(parsed);
|
|
14614
14772
|
if (pending.length > 0) {
|
|
14615
14773
|
process.stderr.write(
|
|
@@ -14629,26 +14787,43 @@ var runCommand = defineCommand88({
|
|
|
14629
14787
|
);
|
|
14630
14788
|
process.exit(2);
|
|
14631
14789
|
}
|
|
14790
|
+
const remoteCache = args["remote-cache"] !== void 0 ? String(args["remote-cache"]) !== "off" : void 0;
|
|
14632
14791
|
const engine = createEngineFromEnv({
|
|
14633
14792
|
cacheDir: args["cache-dir"] ? String(args["cache-dir"]) : void 0,
|
|
14634
14793
|
outputsDir: args["outputs-dir"] ? String(args["outputs-dir"]) : void 0,
|
|
14635
14794
|
log: (line) => process.stdout.write(`${line}
|
|
14636
|
-
`)
|
|
14795
|
+
`),
|
|
14796
|
+
remoteCache
|
|
14637
14797
|
});
|
|
14798
|
+
const runId = args["run-id"] ? String(args["run-id"]) : `r_${ulid()}`;
|
|
14799
|
+
const recordMeta = {
|
|
14800
|
+
creativeSlug: creativeSlugFromCanvasPath(filePath) ?? void 0,
|
|
14801
|
+
canvasPath: path5.relative(process.cwd(), filePath) || void 0,
|
|
14802
|
+
canvasSha: sha256Hex(Buffer.from(raw)),
|
|
14803
|
+
chatId: getEnv().BAKER_CHAT_ID || void 0
|
|
14804
|
+
};
|
|
14805
|
+
const record = args.record === false ? null : buildRecorder();
|
|
14806
|
+
const progress = record ? new RunProgressTracker(runId, recordMeta) : null;
|
|
14807
|
+
const poster = record ? new RunRecordPoster(record) : null;
|
|
14638
14808
|
try {
|
|
14639
14809
|
const policy = args["cache-policy"] ?? "read_write";
|
|
14640
14810
|
const result = await engine.run(parsed, {
|
|
14641
|
-
run_id:
|
|
14811
|
+
run_id: runId,
|
|
14642
14812
|
cache_policy: policy,
|
|
14643
14813
|
concurrency: resolveConcurrency(
|
|
14644
14814
|
// --concurrency wins; --parallel is the discoverable alias for the same bound.
|
|
14645
14815
|
(args.concurrency ?? args.parallel) !== void 0 ? String(args.concurrency ?? args.parallel) : void 0,
|
|
14646
14816
|
process.env.BAKER_CANVAS_CONCURRENCY
|
|
14647
|
-
)
|
|
14817
|
+
),
|
|
14818
|
+
onProgress: progress && poster ? (event) => {
|
|
14819
|
+
progress.apply(event);
|
|
14820
|
+
if (progress.hasPlan()) poster.enqueue(progress.snapshot());
|
|
14821
|
+
} : void 0
|
|
14648
14822
|
});
|
|
14823
|
+
if (poster) await poster.flush(buildRunRecord(result, recordMeta, progress?.planInfo()));
|
|
14649
14824
|
const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
|
|
14650
14825
|
if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
|
|
14651
|
-
const outputsDir = args["outputs-dir"] ?
|
|
14826
|
+
const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
|
|
14652
14827
|
await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
|
|
14653
14828
|
`));
|
|
14654
14829
|
}
|
|
@@ -14674,8 +14849,10 @@ var runCommand = defineCommand88({
|
|
|
14674
14849
|
);
|
|
14675
14850
|
process.exit(2);
|
|
14676
14851
|
}
|
|
14852
|
+
const failedPayload = (message) => progress?.hasPlan() ? progress.failedSnapshot(message) : buildFailedRunRecord(runId, message, recordMeta);
|
|
14677
14853
|
if (e instanceof LayerExecutionError) {
|
|
14678
14854
|
const failures = e.failures.map((f) => ({ node_id: f.nodeId, message: describeFailureReason(f.reason) }));
|
|
14855
|
+
if (poster) await poster.flush(failedPayload(e.message));
|
|
14679
14856
|
process.stderr.write(
|
|
14680
14857
|
`${JSON.stringify({ ok: false, error: { code: "runtime", message: e.message, failures } }, null, 2)}
|
|
14681
14858
|
`
|
|
@@ -14683,40 +14860,54 @@ var runCommand = defineCommand88({
|
|
|
14683
14860
|
process.exit(1);
|
|
14684
14861
|
}
|
|
14685
14862
|
const msg = e instanceof Error ? e.message : String(e);
|
|
14863
|
+
if (poster) await poster.flush(failedPayload(msg));
|
|
14686
14864
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "runtime", message: msg } }, null, 2)}
|
|
14687
14865
|
`);
|
|
14688
14866
|
process.exit(1);
|
|
14689
14867
|
}
|
|
14690
14868
|
}
|
|
14691
14869
|
});
|
|
14870
|
+
function buildRecorder() {
|
|
14871
|
+
return async (payload) => {
|
|
14872
|
+
try {
|
|
14873
|
+
const creds = requireCredentialsFromEnv();
|
|
14874
|
+
const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
|
|
14875
|
+
await client.recordRun(payload);
|
|
14876
|
+
} catch (e) {
|
|
14877
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14878
|
+
process.stderr.write(`[warn] run record not persisted (${msg})
|
|
14879
|
+
`);
|
|
14880
|
+
}
|
|
14881
|
+
};
|
|
14882
|
+
}
|
|
14692
14883
|
|
|
14693
14884
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
14694
|
-
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
14695
|
-
import
|
|
14885
|
+
import { access, mkdir, readFile as readFile3, writeFile } from "fs/promises";
|
|
14886
|
+
import path8 from "path";
|
|
14696
14887
|
import { defineCommand as defineCommand89 } from "citty";
|
|
14697
14888
|
|
|
14698
14889
|
// src/engine/scaffold/staticAd.ts
|
|
14699
|
-
import { z as
|
|
14890
|
+
import { z as z11 } from "zod";
|
|
14700
14891
|
var GEN_ASPECT_RATIOS = /* @__PURE__ */ new Set(["1:1", "4:5", "9:16", "16:9", "4:3", "3:4", "2:3", "3:2", "21:9"]);
|
|
14701
14892
|
var DEFAULT_ASPECT_RATIO = "9:16";
|
|
14702
|
-
var Blueprint =
|
|
14703
|
-
meta:
|
|
14704
|
-
text_content:
|
|
14893
|
+
var Blueprint = z11.object({
|
|
14894
|
+
meta: z11.object({ estimated_aspect_ratio: z11.string().optional() }).loose().optional(),
|
|
14895
|
+
text_content: z11.array(z11.object({ text: z11.string().optional() }).loose()).optional()
|
|
14705
14896
|
}).loose();
|
|
14706
|
-
var ElementLocator =
|
|
14707
|
-
collection:
|
|
14708
|
-
index:
|
|
14897
|
+
var ElementLocator = z11.object({
|
|
14898
|
+
collection: z11.enum(["subjects", "people", "brands_logos"]),
|
|
14899
|
+
index: z11.number().int().nonnegative()
|
|
14709
14900
|
}).loose();
|
|
14710
|
-
var MainElement =
|
|
14901
|
+
var MainElement = z11.object({
|
|
14711
14902
|
// logo | product | person | animal | badge | other
|
|
14712
|
-
type:
|
|
14713
|
-
label:
|
|
14714
|
-
description:
|
|
14715
|
-
expression:
|
|
14716
|
-
reason:
|
|
14903
|
+
type: z11.string(),
|
|
14904
|
+
label: z11.string().optional(),
|
|
14905
|
+
description: z11.string().optional(),
|
|
14906
|
+
expression: z11.string().nullable().optional(),
|
|
14907
|
+
reason: z11.string().optional(),
|
|
14717
14908
|
locator: ElementLocator.optional()
|
|
14718
14909
|
}).loose();
|
|
14719
|
-
var MainElements =
|
|
14910
|
+
var MainElements = z11.array(MainElement);
|
|
14720
14911
|
function sanitizeId(raw, fallback) {
|
|
14721
14912
|
const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
14722
14913
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
@@ -14878,18 +15069,102 @@ function staticAdReport(input, elementsInput, opts) {
|
|
|
14878
15069
|
};
|
|
14879
15070
|
}
|
|
14880
15071
|
|
|
15072
|
+
// src/commands/canvas/creative-definition.ts
|
|
15073
|
+
import path6 from "path";
|
|
15074
|
+
var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
|
|
15075
|
+
var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
|
|
15076
|
+
function titleFromSlug(slug) {
|
|
15077
|
+
const title = slug.split("-").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
15078
|
+
return title || slug;
|
|
15079
|
+
}
|
|
15080
|
+
function resolvePlatform(platform) {
|
|
15081
|
+
const value = platform?.trim();
|
|
15082
|
+
return value && PLATFORM_VALUES.includes(value) ? value : "meta";
|
|
15083
|
+
}
|
|
15084
|
+
function resolveFormats(aspect) {
|
|
15085
|
+
const value = aspect?.trim();
|
|
15086
|
+
return value && FORMAT_VALUES.includes(value) ? [value] : ["4:5"];
|
|
15087
|
+
}
|
|
15088
|
+
function referenceRelativePath(kind, ext) {
|
|
15089
|
+
const name = kind === "video" ? "source" : "original";
|
|
15090
|
+
return `references/${name}${ext}`;
|
|
15091
|
+
}
|
|
15092
|
+
function describeBlueprintIntent(blueprint) {
|
|
15093
|
+
const intent = blueprint?.ad_intent;
|
|
15094
|
+
if (typeof intent === "string" && intent.trim()) return intent.trim();
|
|
15095
|
+
if (intent && typeof intent === "object") {
|
|
15096
|
+
const summary = intent.summary ?? intent.feeling;
|
|
15097
|
+
if (typeof summary === "string" && summary.trim()) return summary.trim();
|
|
15098
|
+
}
|
|
15099
|
+
return void 0;
|
|
15100
|
+
}
|
|
15101
|
+
function yamlScalar(value) {
|
|
15102
|
+
return JSON.stringify(value);
|
|
15103
|
+
}
|
|
15104
|
+
function buildCreativeDefinition(input) {
|
|
15105
|
+
const lines = ["---", `title: ${yamlScalar(input.title)}`, `kind: ${input.kind}`, `platform: ${input.platform}`];
|
|
15106
|
+
lines.push(`formats: [${input.formats.map(yamlScalar).join(", ")}]`);
|
|
15107
|
+
lines.push(`status: ${input.status ?? "draft"}`);
|
|
15108
|
+
if (input.sourceReferenceUrl) lines.push(`sourceReferenceUrl: ${yamlScalar(input.sourceReferenceUrl)}`);
|
|
15109
|
+
if (input.sourceAdvertiser) lines.push(`sourceAdvertiser: ${yamlScalar(input.sourceAdvertiser)}`);
|
|
15110
|
+
if (input.sourceKind) lines.push(`sourceKind: ${input.sourceKind}`);
|
|
15111
|
+
if (input.sourcePath) lines.push(`sourcePath: ${yamlScalar(input.sourcePath)}`);
|
|
15112
|
+
lines.push("---", "");
|
|
15113
|
+
lines.push(input.description?.trim() || `${input.title} \u2014 canvas-built ${input.kind} ad for ${input.platform}.`);
|
|
15114
|
+
lines.push("");
|
|
15115
|
+
return lines.join("\n");
|
|
15116
|
+
}
|
|
15117
|
+
|
|
14881
15118
|
// src/commands/canvas/scaffold-static-ad-paths.ts
|
|
14882
|
-
import
|
|
14883
|
-
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd()) {
|
|
15119
|
+
import path7 from "path";
|
|
15120
|
+
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
|
|
14884
15121
|
const file = rawFile.trim();
|
|
14885
15122
|
const imageIsUrl = /^https?:\/\//i.test(file);
|
|
14886
|
-
const imageSource = imageIsUrl ? file :
|
|
14887
|
-
const outPath = out ?
|
|
14888
|
-
const blueprintPath =
|
|
14889
|
-
|
|
15123
|
+
const imageSource = imageIsUrl ? file : path7.resolve(cwd, file);
|
|
15124
|
+
const outPath = out ? path7.resolve(cwd, out) : slug ? path7.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path7.join(cwd, "static-ad.canvas.json") : path7.join(path7.dirname(imageSource), "static-ad.canvas.json");
|
|
15125
|
+
const blueprintPath = path7.join(path7.dirname(outPath), "prompt.json");
|
|
15126
|
+
const creativeDir = slug ? path7.dirname(outPath) : null;
|
|
15127
|
+
const definitionPath = creativeDir ? path7.join(creativeDir, "_definition.md") : null;
|
|
15128
|
+
const referencesDir = creativeDir ? path7.join(creativeDir, "references") : null;
|
|
15129
|
+
return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
|
|
15130
|
+
}
|
|
15131
|
+
var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
15132
|
+
var SCAFFOLD_SLUG_MAX_LENGTH = 100;
|
|
15133
|
+
function isValidScaffoldSlug(slug) {
|
|
15134
|
+
return slug.length <= SCAFFOLD_SLUG_MAX_LENGTH && SCAFFOLD_SLUG_PATTERN.test(slug);
|
|
14890
15135
|
}
|
|
14891
15136
|
|
|
14892
15137
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
15138
|
+
async function fileExists(target) {
|
|
15139
|
+
try {
|
|
15140
|
+
await access(target);
|
|
15141
|
+
return true;
|
|
15142
|
+
} catch {
|
|
15143
|
+
return false;
|
|
15144
|
+
}
|
|
15145
|
+
}
|
|
15146
|
+
var MODEL_SAFE_EXT_BY_MIME = {
|
|
15147
|
+
"image/png": ".png",
|
|
15148
|
+
"image/jpeg": ".jpg",
|
|
15149
|
+
"image/gif": ".gif",
|
|
15150
|
+
"image/webp": ".webp"
|
|
15151
|
+
};
|
|
15152
|
+
async function copySourceIntoReferences(source, isUrl, referencesDir) {
|
|
15153
|
+
await mkdir(referencesDir, { recursive: true });
|
|
15154
|
+
let bytes;
|
|
15155
|
+
if (isUrl) {
|
|
15156
|
+
const res = await fetch(source);
|
|
15157
|
+
if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
|
|
15158
|
+
bytes = Buffer.from(await res.arrayBuffer());
|
|
15159
|
+
} else {
|
|
15160
|
+
bytes = await readFile3(source);
|
|
15161
|
+
}
|
|
15162
|
+
const safe = await toModelSafeImage(bytes);
|
|
15163
|
+
const relPath = referenceRelativePath("image", MODEL_SAFE_EXT_BY_MIME[safe.mime] ?? ".png");
|
|
15164
|
+
const dest = path8.join(referencesDir, path8.basename(relPath));
|
|
15165
|
+
await writeFile(dest, safe.bytes);
|
|
15166
|
+
return relPath;
|
|
15167
|
+
}
|
|
14893
15168
|
function resolveModel(kind, preferred) {
|
|
14894
15169
|
const ids = Object.keys(MODEL_REGISTRY[kind]);
|
|
14895
15170
|
return ids.includes(preferred) ? preferred : ids[0] ?? preferred;
|
|
@@ -15049,6 +15324,16 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15049
15324
|
file: { type: "positional", required: true, description: "Path or http(s) URL to the source/inspiration image" },
|
|
15050
15325
|
context: { type: "string", description: "Known provenance (advertiser, category, market) to ground the describe" },
|
|
15051
15326
|
out: { type: "string", description: "Output canvas path (default <image-dir>/static-ad.canvas.json)" },
|
|
15327
|
+
slug: {
|
|
15328
|
+
type: "string",
|
|
15329
|
+
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
15330
|
+
},
|
|
15331
|
+
title: { type: "string", description: "Creative title for _definition.md (default: title-cased slug)" },
|
|
15332
|
+
platform: {
|
|
15333
|
+
type: "string",
|
|
15334
|
+
description: "Ad platform for _definition.md (meta|google|linkedin|tiktok|youtube|x|other; default meta)"
|
|
15335
|
+
},
|
|
15336
|
+
advertiser: { type: "string", description: "Source advertiser recorded in _definition.md" },
|
|
15052
15337
|
"describe-model": { type: "string", description: "Override the image_describe model id" },
|
|
15053
15338
|
"select-model": { type: "string", description: "Override the text_generate model id for element selection" },
|
|
15054
15339
|
"layout-model": { type: "string", description: "Override the text_generate model id for the layout pass" },
|
|
@@ -15057,10 +15342,21 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15057
15342
|
"skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
|
|
15058
15343
|
},
|
|
15059
15344
|
async run({ args }) {
|
|
15060
|
-
const
|
|
15345
|
+
const slug = args.slug ? String(args.slug) : void 0;
|
|
15346
|
+
if (slug && !isValidScaffoldSlug(slug)) {
|
|
15347
|
+
process.stderr.write(
|
|
15348
|
+
`${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
|
|
15349
|
+
`
|
|
15350
|
+
);
|
|
15351
|
+
process.exit(2);
|
|
15352
|
+
}
|
|
15353
|
+
const { imageIsUrl, imageSource, outPath, blueprintPath, definitionPath, referencesDir } = resolveScaffoldStaticAdPaths(
|
|
15061
15354
|
String(args.file),
|
|
15062
|
-
args.out ? String(args.out) : void 0
|
|
15355
|
+
args.out ? String(args.out) : void 0,
|
|
15356
|
+
process.cwd(),
|
|
15357
|
+
slug
|
|
15063
15358
|
);
|
|
15359
|
+
await mkdir(path8.dirname(outPath), { recursive: true });
|
|
15064
15360
|
const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
|
|
15065
15361
|
const describeCanvas = buildDescribeCanvas(
|
|
15066
15362
|
imageSource,
|
|
@@ -15077,11 +15373,21 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15077
15373
|
}
|
|
15078
15374
|
await writeFile(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
15079
15375
|
`, "utf8");
|
|
15376
|
+
let canvasImagePath = imageSource;
|
|
15377
|
+
let canvasImageIsUrl = imageIsUrl;
|
|
15378
|
+
let canvasBlueprintPath = blueprintPath;
|
|
15379
|
+
let sourceRelPath;
|
|
15380
|
+
if (referencesDir) {
|
|
15381
|
+
sourceRelPath = await copySourceIntoReferences(imageSource, imageIsUrl, referencesDir);
|
|
15382
|
+
canvasImagePath = sourceRelPath;
|
|
15383
|
+
canvasImageIsUrl = false;
|
|
15384
|
+
canvasBlueprintPath = "./prompt.json";
|
|
15385
|
+
}
|
|
15080
15386
|
const opts = {
|
|
15081
15387
|
genModel,
|
|
15082
|
-
imagePath:
|
|
15083
|
-
imageIsUrl,
|
|
15084
|
-
blueprintPath,
|
|
15388
|
+
imagePath: canvasImagePath,
|
|
15389
|
+
imageIsUrl: canvasImageIsUrl,
|
|
15390
|
+
blueprintPath: canvasBlueprintPath,
|
|
15085
15391
|
aspectRatio: args.aspect ? String(args.aspect) : void 0,
|
|
15086
15392
|
includeFont: !args["skip-font"]
|
|
15087
15393
|
};
|
|
@@ -15103,12 +15409,31 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15103
15409
|
}
|
|
15104
15410
|
await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
15105
15411
|
`, "utf8");
|
|
15412
|
+
if (definitionPath && !await fileExists(definitionPath)) {
|
|
15413
|
+
await writeFile(
|
|
15414
|
+
definitionPath,
|
|
15415
|
+
buildCreativeDefinition({
|
|
15416
|
+
title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
|
|
15417
|
+
kind: "static",
|
|
15418
|
+
platform: resolvePlatform(args.platform ? String(args.platform) : void 0),
|
|
15419
|
+
formats: resolveFormats(args.aspect ? String(args.aspect) : report.aspect_ratio),
|
|
15420
|
+
sourceReferenceUrl: imageIsUrl ? imageSource : void 0,
|
|
15421
|
+
sourceAdvertiser: args.advertiser ? String(args.advertiser) : args.context ? String(args.context) : void 0,
|
|
15422
|
+
sourceKind: "image",
|
|
15423
|
+
sourcePath: sourceRelPath,
|
|
15424
|
+
description: describeBlueprintIntent(blueprint)
|
|
15425
|
+
}),
|
|
15426
|
+
"utf8"
|
|
15427
|
+
);
|
|
15428
|
+
}
|
|
15106
15429
|
process.stdout.write(
|
|
15107
15430
|
`${JSON.stringify(
|
|
15108
15431
|
{
|
|
15109
15432
|
ok: true,
|
|
15110
15433
|
canvas_path: outPath,
|
|
15111
15434
|
prompt_path: blueprintPath,
|
|
15435
|
+
definition_path: definitionPath ?? void 0,
|
|
15436
|
+
source_reference: sourceRelPath ?? void 0,
|
|
15112
15437
|
output: canvas.output,
|
|
15113
15438
|
models: { describe: describeModel, select: selectModel, layout: layoutModel, gen: opts.genModel },
|
|
15114
15439
|
aspect_ratio: report.aspect_ratio,
|
|
@@ -15119,7 +15444,7 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15119
15444
|
run_estimated_credits: validation.estimatedCredits
|
|
15120
15445
|
},
|
|
15121
15446
|
checklist: {
|
|
15122
|
-
edit_prompt: `Edit ${
|
|
15447
|
+
edit_prompt: `Edit ${path8.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
|
|
15123
15448
|
assets_to_supply: report.elements,
|
|
15124
15449
|
font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path, or delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
|
|
15125
15450
|
note: "Replace every [TODO] ingest path with a real file, then `baker canvas validate` and `baker canvas run`. Running generates a billed image \u2014 it is not free."
|
|
@@ -15134,8 +15459,8 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15134
15459
|
});
|
|
15135
15460
|
|
|
15136
15461
|
// src/commands/canvas/scaffold-video.ts
|
|
15137
|
-
import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
15138
|
-
import
|
|
15462
|
+
import { cp, mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
15463
|
+
import path11 from "path";
|
|
15139
15464
|
import { defineCommand as defineCommand90 } from "citty";
|
|
15140
15465
|
|
|
15141
15466
|
// src/engine/nodes/local/lib/sceneDetect.ts
|
|
@@ -15252,7 +15577,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
|
|
|
15252
15577
|
import { toCardinal as nwNl } from "n2words/nl-NL";
|
|
15253
15578
|
import { toCardinal as nwPl } from "n2words/pl-PL";
|
|
15254
15579
|
import { toCardinal as nwPt } from "n2words/pt-PT";
|
|
15255
|
-
import { z as
|
|
15580
|
+
import { z as z12 } from "zod";
|
|
15256
15581
|
|
|
15257
15582
|
// src/engine/scaffold/lib/shoot-modes.ts
|
|
15258
15583
|
var SHOOT_MODES = [
|
|
@@ -15565,71 +15890,71 @@ function trimArgs(durationS, offsetS = 0, dims) {
|
|
|
15565
15890
|
"{{out.video}}"
|
|
15566
15891
|
];
|
|
15567
15892
|
}
|
|
15568
|
-
var FrameAsset =
|
|
15569
|
-
var DialogueLine =
|
|
15570
|
-
speaker:
|
|
15571
|
-
line:
|
|
15893
|
+
var FrameAsset = z12.object({ url: z12.string().optional() }).loose().optional();
|
|
15894
|
+
var DialogueLine = z12.object({
|
|
15895
|
+
speaker: z12.string().optional(),
|
|
15896
|
+
line: z12.string().optional(),
|
|
15572
15897
|
// Absolute seconds on the source timeline (the deconstruct emits both).
|
|
15573
|
-
start_s:
|
|
15574
|
-
end_s:
|
|
15575
|
-
delivery:
|
|
15576
|
-
voice_description:
|
|
15898
|
+
start_s: z12.number().optional(),
|
|
15899
|
+
end_s: z12.number().optional(),
|
|
15900
|
+
delivery: z12.string().optional(),
|
|
15901
|
+
voice_description: z12.string().optional(),
|
|
15577
15902
|
// DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element
|
|
15578
15903
|
// presence alone can't answer that — a founder pictured in a polaroid close-up is
|
|
15579
15904
|
// "present" yet the line is voiceover, and treating it as on-camera produced a
|
|
15580
15905
|
// native Seedance lip-sync clip of a still photograph. `false` pins the line to
|
|
15581
15906
|
// the VO path; absent keeps the presence-based decision (old blueprints).
|
|
15582
|
-
on_camera:
|
|
15907
|
+
on_camera: z12.boolean().optional()
|
|
15583
15908
|
}).loose();
|
|
15584
|
-
var Sfx =
|
|
15585
|
-
at_s:
|
|
15586
|
-
duration_s:
|
|
15587
|
-
sound_effect_prompt:
|
|
15588
|
-
description:
|
|
15909
|
+
var Sfx = z12.object({
|
|
15910
|
+
at_s: z12.number().optional(),
|
|
15911
|
+
duration_s: z12.number().optional(),
|
|
15912
|
+
sound_effect_prompt: z12.string().optional(),
|
|
15913
|
+
description: z12.string().optional()
|
|
15589
15914
|
}).loose();
|
|
15590
|
-
var CompositionRegion =
|
|
15915
|
+
var CompositionRegion = z12.object({
|
|
15591
15916
|
// full | top | bottom | left | right | inset
|
|
15592
|
-
panel:
|
|
15917
|
+
panel: z12.string().optional(),
|
|
15593
15918
|
// 9-grid anchor for an `inset` presenter box.
|
|
15594
|
-
position:
|
|
15595
|
-
is_presenter:
|
|
15919
|
+
position: z12.string().optional(),
|
|
15920
|
+
is_presenter: z12.boolean().optional(),
|
|
15596
15921
|
// The cast id shown/speaking in this region (routes lip-sync + element refs).
|
|
15597
|
-
cast_ref:
|
|
15922
|
+
cast_ref: z12.string().optional(),
|
|
15598
15923
|
// What the region's content IS: camera | screen_capture | static_graphic |
|
|
15599
15924
|
// generated. Authoritative for routing when present (regex-over-prose fallback
|
|
15600
15925
|
// otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the
|
|
15601
15926
|
// overlay layer, never AI-generated.
|
|
15602
|
-
kind:
|
|
15927
|
+
kind: z12.string().optional(),
|
|
15603
15928
|
// Opaque id naming the SPECIFIC on-screen document/note/app-state this
|
|
15604
15929
|
// screen_capture region shows. Two scenes share it only when they show the SAME
|
|
15605
15930
|
// recording continuing (scrolling/typing/waiting within it) — a genuinely
|
|
15606
15931
|
// DIFFERENT document/note/recording (a source video splicing two screen captures)
|
|
15607
15932
|
// gets a different id. Breaks a persistent-layout run into separate surface stubs
|
|
15608
15933
|
// instead of asking the operator for one screenshot that can't cover both.
|
|
15609
|
-
surface_id:
|
|
15934
|
+
surface_id: z12.string().optional(),
|
|
15610
15935
|
// Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style
|
|
15611
15936
|
// presenter bubble inside a screen recording) — video-in-video the reproduction
|
|
15612
15937
|
// must re-composite, not paint into the surface.
|
|
15613
|
-
nested:
|
|
15614
|
-
summary:
|
|
15615
|
-
frame_prompt:
|
|
15616
|
-
motion_prompt:
|
|
15938
|
+
nested: z12.array(z12.object({}).loose()).optional(),
|
|
15939
|
+
summary: z12.string().optional(),
|
|
15940
|
+
frame_prompt: z12.string().optional(),
|
|
15941
|
+
motion_prompt: z12.string().optional()
|
|
15617
15942
|
}).loose();
|
|
15618
|
-
var SceneComposition =
|
|
15943
|
+
var SceneComposition = z12.object({
|
|
15619
15944
|
// full_frame (default) | split_screen | pip | keyed_overlay
|
|
15620
|
-
layout:
|
|
15945
|
+
layout: z12.string().optional(),
|
|
15621
15946
|
// split_screen only: vertical (top/bottom) | horizontal (left/right).
|
|
15622
|
-
split_axis:
|
|
15623
|
-
regions:
|
|
15947
|
+
split_axis: z12.string().optional(),
|
|
15948
|
+
regions: z12.array(CompositionRegion).optional()
|
|
15624
15949
|
}).loose();
|
|
15625
|
-
var CameraMotion =
|
|
15626
|
-
var TranscriptWord =
|
|
15627
|
-
var Scene =
|
|
15628
|
-
start_s:
|
|
15629
|
-
end_s:
|
|
15630
|
-
duration_s:
|
|
15631
|
-
summary:
|
|
15632
|
-
action_detail:
|
|
15950
|
+
var CameraMotion = z12.object({ movement: z12.string().optional(), detail: z12.string().optional() }).loose();
|
|
15951
|
+
var TranscriptWord = z12.object({ text: z12.string().optional() }).loose();
|
|
15952
|
+
var Scene = z12.object({
|
|
15953
|
+
start_s: z12.number().optional(),
|
|
15954
|
+
end_s: z12.number().optional(),
|
|
15955
|
+
duration_s: z12.number().optional(),
|
|
15956
|
+
summary: z12.string().optional(),
|
|
15957
|
+
action_detail: z12.string().optional(),
|
|
15633
15958
|
// The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
|
|
15634
15959
|
// A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
|
|
15635
15960
|
// builds one clip per region and stacks/overlays them into the scene picture.
|
|
@@ -15637,82 +15962,82 @@ var Scene = z13.object({
|
|
|
15637
15962
|
// The capture "look" for this scene — selected from the ad-native shoot-mode
|
|
15638
15963
|
// grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
|
|
15639
15964
|
// UGC/product mode; a human can override per scene by setting this.
|
|
15640
|
-
shoot_mode:
|
|
15965
|
+
shoot_mode: z12.string().optional(),
|
|
15641
15966
|
// Diegetic ambient the clip's native audio should carry (no music). When
|
|
15642
15967
|
// absent the scene falls back to its shoot mode's default ambience.
|
|
15643
|
-
ambient:
|
|
15968
|
+
ambient: z12.string().optional(),
|
|
15644
15969
|
camera_motion: CameraMotion.optional(),
|
|
15645
|
-
start_frame_prompt:
|
|
15646
|
-
end_frame_prompt:
|
|
15647
|
-
motion_prompt:
|
|
15970
|
+
start_frame_prompt: z12.string().optional(),
|
|
15971
|
+
end_frame_prompt: z12.string().optional(),
|
|
15972
|
+
motion_prompt: z12.string().optional(),
|
|
15648
15973
|
// The scene's role in the ad's persuasion arc (DECON-supplied); drives the
|
|
15649
15974
|
// script re-craft checklist. Inferred from position when absent.
|
|
15650
|
-
narrative_role:
|
|
15975
|
+
narrative_role: z12.string().optional(),
|
|
15651
15976
|
// DECON-supplied on the HOOK scene: the engineered physical/emotional state that
|
|
15652
15977
|
// makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
|
|
15653
15978
|
// into the hook's start-frame description so the generator renders that state,
|
|
15654
15979
|
// not a calm influencer (CCA-11).
|
|
15655
|
-
hook_mechanic:
|
|
15980
|
+
hook_mechanic: z12.object({ mechanic: z12.string().optional(), why_it_stops_scroll: z12.string().optional() }).loose().optional(),
|
|
15656
15981
|
// DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
|
|
15657
|
-
scene_setting:
|
|
15982
|
+
scene_setting: z12.string().optional(),
|
|
15658
15983
|
// How this scene cuts to the next (DECON-supplied). A recognized non-cut type
|
|
15659
15984
|
// (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
|
|
15660
15985
|
// boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
|
|
15661
15986
|
// ignored (nothing follows it).
|
|
15662
|
-
transition_out:
|
|
15663
|
-
dialogue:
|
|
15664
|
-
sfx:
|
|
15665
|
-
overlays:
|
|
15666
|
-
floating_elements:
|
|
15987
|
+
transition_out: z12.object({ type: z12.string().optional(), description: z12.string().optional() }).loose().optional(),
|
|
15988
|
+
dialogue: z12.array(DialogueLine).optional(),
|
|
15989
|
+
sfx: z12.array(Sfx).optional(),
|
|
15990
|
+
overlays: z12.array(z12.unknown()).optional(),
|
|
15991
|
+
floating_elements: z12.array(z12.unknown()).optional(),
|
|
15667
15992
|
// DECON-supplied: how much the picture itself moves within the shot. Gates the
|
|
15668
15993
|
// flash-hold optimization — a sub-2s b-roll flash with REAL subject motion
|
|
15669
15994
|
// (pouring, spreading, hands working) must stay a real clip; freezing it turns
|
|
15670
15995
|
// a montage into a slideshow. Absent (old blueprints) keeps the cheap still.
|
|
15671
|
-
motion_level:
|
|
15672
|
-
transcript_slice:
|
|
15996
|
+
motion_level: z12.enum(["static", "subtle", "dynamic"]).optional(),
|
|
15997
|
+
transcript_slice: z12.array(TranscriptWord).optional(),
|
|
15673
15998
|
start_frame_asset: FrameAsset,
|
|
15674
15999
|
end_frame_asset: FrameAsset,
|
|
15675
16000
|
// DECON-supplied: true when this scene is a length-split CONTINUATION of the
|
|
15676
16001
|
// previous one (the SAME physical shot, broken up only because it exceeded the
|
|
15677
16002
|
// clip ceiling). The scaffold then shares the splice keyframe — this scene's
|
|
15678
16003
|
// start frame IS the previous scene's end frame — so the join is seamless.
|
|
15679
|
-
continues_previous:
|
|
16004
|
+
continues_previous: z12.boolean().optional()
|
|
15680
16005
|
}).loose();
|
|
15681
|
-
var VideoBlueprint =
|
|
15682
|
-
source:
|
|
15683
|
-
global:
|
|
15684
|
-
music:
|
|
15685
|
-
present:
|
|
15686
|
-
music_prompt:
|
|
16006
|
+
var VideoBlueprint = z12.object({
|
|
16007
|
+
source: z12.object({ aspect_ratio: z12.string().optional(), duration_s: z12.number().optional() }).loose().optional(),
|
|
16008
|
+
global: z12.object({
|
|
16009
|
+
music: z12.object({
|
|
16010
|
+
present: z12.boolean().optional(),
|
|
16011
|
+
music_prompt: z12.string().optional(),
|
|
15687
16012
|
// Absolute second the music enters in the reference (the bed often
|
|
15688
16013
|
// kicks in mid-ad, after the hook). We start the regenerated track here
|
|
15689
16014
|
// instead of at 0 so the timing matches.
|
|
15690
|
-
starts_at_s:
|
|
16015
|
+
starts_at_s: z12.number().optional(),
|
|
15691
16016
|
// Populated by the deconstruct when AudD (Shazam-style) recognizes the
|
|
15692
16017
|
// reference track. We never reuse it — only style the regenerated bed.
|
|
15693
|
-
identified_track:
|
|
16018
|
+
identified_track: z12.object({ title: z12.string().optional(), artist: z12.string().optional() }).loose().nullish()
|
|
15694
16019
|
}).loose().optional(),
|
|
15695
|
-
cast:
|
|
15696
|
-
|
|
15697
|
-
id:
|
|
15698
|
-
description:
|
|
16020
|
+
cast: z12.array(
|
|
16021
|
+
z12.object({
|
|
16022
|
+
id: z12.string().optional(),
|
|
16023
|
+
description: z12.string().optional(),
|
|
15699
16024
|
// The deconstruct's note on the target-market localization (e.g. "native
|
|
15700
16025
|
// French speaker") — read to derive the spoken-track language code.
|
|
15701
|
-
market_localization_note:
|
|
16026
|
+
market_localization_note: z12.string().optional()
|
|
15702
16027
|
}).loose()
|
|
15703
16028
|
).optional(),
|
|
15704
|
-
voiceover:
|
|
16029
|
+
voiceover: z12.object({
|
|
15705
16030
|
// on_camera | mixed → mouths are on screen (lip-sync candidates);
|
|
15706
16031
|
// voiceover | none → narration over the picture (no lip-sync).
|
|
15707
|
-
mode:
|
|
15708
|
-
voice_description:
|
|
15709
|
-
persona:
|
|
16032
|
+
mode: z12.string().optional(),
|
|
16033
|
+
voice_description: z12.string().optional(),
|
|
16034
|
+
persona: z12.string().optional()
|
|
15710
16035
|
}).loose().optional(),
|
|
15711
16036
|
// Visual palette — read only to colour a clean brand-card/CTA plate (the
|
|
15712
16037
|
// first hex is the dominant brand colour); never to drive frame generation.
|
|
15713
|
-
style:
|
|
16038
|
+
style: z12.object({ palette: z12.array(z12.object({ hex: z12.string().optional() }).loose()).optional() }).loose().optional()
|
|
15714
16039
|
}).loose().optional(),
|
|
15715
|
-
scenes:
|
|
16040
|
+
scenes: z12.array(Scene).min(1)
|
|
15716
16041
|
}).loose();
|
|
15717
16042
|
function injectHookPhysicality(blueprint) {
|
|
15718
16043
|
for (const scene of blueprint.scenes) {
|
|
@@ -15722,26 +16047,26 @@ function injectHookPhysicality(blueprint) {
|
|
|
15722
16047
|
scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
|
|
15723
16048
|
}
|
|
15724
16049
|
}
|
|
15725
|
-
var AppearsItem =
|
|
15726
|
-
var RecurringElement =
|
|
16050
|
+
var AppearsItem = z12.union([z12.number(), z12.object({ scene: z12.number(), edge: z12.string().optional() }).loose()]);
|
|
16051
|
+
var RecurringElement = z12.object({
|
|
15727
16052
|
// person | animal | product | logo | badge | other
|
|
15728
|
-
type:
|
|
15729
|
-
label:
|
|
15730
|
-
description:
|
|
15731
|
-
expression:
|
|
16053
|
+
type: z12.string(),
|
|
16054
|
+
label: z12.string().optional(),
|
|
16055
|
+
description: z12.string().optional(),
|
|
16056
|
+
expression: z12.string().nullable().optional(),
|
|
15732
16057
|
// When the element maps to a global cast entry, its stable id (for annotation).
|
|
15733
|
-
cast_id:
|
|
16058
|
+
cast_id: z12.string().nullable().optional(),
|
|
15734
16059
|
// The label of another element that is the SAME individual as this one, shown
|
|
15735
16060
|
// in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
|
|
15736
16061
|
// pink shirt and believer in a white shirt). Each look gets its own reference
|
|
15737
16062
|
// slot, but the face/identity must stay identical across them.
|
|
15738
|
-
same_as:
|
|
16063
|
+
same_as: z12.string().nullable().optional(),
|
|
15739
16064
|
// Scenes the element appears in. Either a bare list of scene indices (both
|
|
15740
16065
|
// edges) or per-{scene,edge} entries. Both forms are accepted and merged.
|
|
15741
|
-
scenes:
|
|
15742
|
-
appears_in:
|
|
16066
|
+
scenes: z12.array(z12.number()).optional(),
|
|
16067
|
+
appears_in: z12.array(AppearsItem).optional()
|
|
15743
16068
|
}).loose();
|
|
15744
|
-
var RecurringElements =
|
|
16069
|
+
var RecurringElements = z12.array(RecurringElement);
|
|
15745
16070
|
function sanitizeId2(raw, fallback) {
|
|
15746
16071
|
const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
15747
16072
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
@@ -16159,7 +16484,7 @@ function scrubFloatSentences(text, floatDescs) {
|
|
|
16159
16484
|
return kept;
|
|
16160
16485
|
}
|
|
16161
16486
|
function sceneFloatDescs(scene) {
|
|
16162
|
-
const floats =
|
|
16487
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
16163
16488
|
if (!floats.success) return [];
|
|
16164
16489
|
return floats.data.map((f) => f.description?.trim() ?? "").filter(Boolean);
|
|
16165
16490
|
}
|
|
@@ -17499,25 +17824,25 @@ function buildSfxMusic(blueprint, nodes) {
|
|
|
17499
17824
|
}
|
|
17500
17825
|
return tracks;
|
|
17501
17826
|
}
|
|
17502
|
-
var OverlayStyle =
|
|
17503
|
-
var Overlay =
|
|
17504
|
-
text:
|
|
17505
|
-
appears_at_s:
|
|
17506
|
-
duration_s:
|
|
17507
|
-
position:
|
|
17508
|
-
role:
|
|
17509
|
-
animation:
|
|
17510
|
-
animation_detail:
|
|
17827
|
+
var OverlayStyle = z12.object({ color_hex: z12.string().optional(), background: z12.string().optional(), size: z12.string().optional() }).loose();
|
|
17828
|
+
var Overlay = z12.object({
|
|
17829
|
+
text: z12.string().optional(),
|
|
17830
|
+
appears_at_s: z12.number().optional(),
|
|
17831
|
+
duration_s: z12.number().optional(),
|
|
17832
|
+
position: z12.string().optional(),
|
|
17833
|
+
role: z12.string().optional(),
|
|
17834
|
+
animation: z12.string().optional(),
|
|
17835
|
+
animation_detail: z12.string().optional(),
|
|
17511
17836
|
style: OverlayStyle.optional()
|
|
17512
17837
|
}).loose();
|
|
17513
|
-
var FloatingElement =
|
|
17514
|
-
kind:
|
|
17515
|
-
description:
|
|
17516
|
-
brand_name:
|
|
17517
|
-
what_it_represents:
|
|
17518
|
-
appears_at_s:
|
|
17519
|
-
duration_s:
|
|
17520
|
-
position:
|
|
17838
|
+
var FloatingElement = z12.object({
|
|
17839
|
+
kind: z12.string().optional(),
|
|
17840
|
+
description: z12.string().optional(),
|
|
17841
|
+
brand_name: z12.string().nullish(),
|
|
17842
|
+
what_it_represents: z12.string().optional(),
|
|
17843
|
+
appears_at_s: z12.number().optional(),
|
|
17844
|
+
duration_s: z12.number().optional(),
|
|
17845
|
+
position: z12.string().optional()
|
|
17521
17846
|
}).loose();
|
|
17522
17847
|
function escapeHtml(s) {
|
|
17523
17848
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -17549,7 +17874,7 @@ function positionClass(position) {
|
|
|
17549
17874
|
function collectCaptions(blueprint) {
|
|
17550
17875
|
return blueprint.scenes.flatMap((scene) => {
|
|
17551
17876
|
const sceneStart = scene.start_s ?? 0;
|
|
17552
|
-
const overlays =
|
|
17877
|
+
const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
|
|
17553
17878
|
return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
|
|
17554
17879
|
const at = ov.appears_at_s ?? sceneStart;
|
|
17555
17880
|
return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
|
|
@@ -17629,7 +17954,7 @@ function collectFloatWindows(blueprint, uiRouted) {
|
|
|
17629
17954
|
const windows = /* @__PURE__ */ new Map();
|
|
17630
17955
|
blueprint.scenes.forEach((scene, i) => {
|
|
17631
17956
|
const sceneStart = scene.start_s ?? 0;
|
|
17632
|
-
const floats =
|
|
17957
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
17633
17958
|
if (!floats.success) return;
|
|
17634
17959
|
for (const fe of floats.data) {
|
|
17635
17960
|
const at = fe.appears_at_s ?? sceneStart;
|
|
@@ -18015,8 +18340,8 @@ function buildMotionBoard(blueprint) {
|
|
|
18015
18340
|
const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
|
|
18016
18341
|
cursor = end_s;
|
|
18017
18342
|
const spoken = sceneSpokenText(scene);
|
|
18018
|
-
const overlays =
|
|
18019
|
-
const floats =
|
|
18343
|
+
const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
|
|
18344
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
18020
18345
|
const graphics = [
|
|
18021
18346
|
...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
|
|
18022
18347
|
kind: "text",
|
|
@@ -18243,23 +18568,23 @@ function videoReport(input, elementsInput) {
|
|
|
18243
18568
|
|
|
18244
18569
|
// src/commands/canvas/composition-path.ts
|
|
18245
18570
|
import { existsSync as existsSync3 } from "fs";
|
|
18246
|
-
import
|
|
18571
|
+
import path9 from "path";
|
|
18247
18572
|
function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
|
|
18248
|
-
const rel =
|
|
18573
|
+
const rel = path9.join("canvas", name);
|
|
18249
18574
|
let dir = startDir;
|
|
18250
18575
|
for (let i = 0; i < maxDepth; i++) {
|
|
18251
|
-
const candidate =
|
|
18252
|
-
if (exists(
|
|
18253
|
-
const parent =
|
|
18576
|
+
const candidate = path9.join(dir, rel);
|
|
18577
|
+
if (exists(path9.join(candidate, "meta.json"))) return candidate;
|
|
18578
|
+
const parent = path9.dirname(dir);
|
|
18254
18579
|
if (parent === dir) break;
|
|
18255
18580
|
dir = parent;
|
|
18256
18581
|
}
|
|
18257
|
-
return
|
|
18582
|
+
return path9.resolve(startDir, "../../../", rel);
|
|
18258
18583
|
}
|
|
18259
18584
|
|
|
18260
18585
|
// src/commands/canvas/gitignore.ts
|
|
18261
18586
|
import { appendFile, readFile as readFile5 } from "fs/promises";
|
|
18262
|
-
import
|
|
18587
|
+
import path10 from "path";
|
|
18263
18588
|
function missingGitignoreEntries(existing, entries) {
|
|
18264
18589
|
const present = new Set(
|
|
18265
18590
|
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
@@ -18267,7 +18592,7 @@ function missingGitignoreEntries(existing, entries) {
|
|
|
18267
18592
|
return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
|
|
18268
18593
|
}
|
|
18269
18594
|
async function ensureGitignore(dir, entries) {
|
|
18270
|
-
const file =
|
|
18595
|
+
const file = path10.join(dir, ".gitignore");
|
|
18271
18596
|
let existing;
|
|
18272
18597
|
try {
|
|
18273
18598
|
existing = await readFile5(file, "utf8");
|
|
@@ -18328,7 +18653,7 @@ async function loadTranscriptBestEffort(ref) {
|
|
|
18328
18653
|
async function stageCaptions(outDir, transcript) {
|
|
18329
18654
|
const text = transcript?.trim();
|
|
18330
18655
|
if (!text || text === "[]") return {};
|
|
18331
|
-
const compositionPath =
|
|
18656
|
+
const compositionPath = path11.join(outDir, "tiktok-captions-composition");
|
|
18332
18657
|
await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
18333
18658
|
return { compositionPath };
|
|
18334
18659
|
}
|
|
@@ -18346,10 +18671,10 @@ function patchCompositionHtml(html, dims) {
|
|
|
18346
18671
|
return html.replace(/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+(")/i, `$1${dims.w}$2${dims.h}$3`).replace(/(width:\s*)\d+(px;\s*height:\s*)\d+(px;)/i, `$1${dims.w}$2${dims.h}$3`).replace(/(data-width=")\d+(")/i, `$1${dims.w}$2`).replace(/(data-height=")\d+(")/i, `$1${dims.h}$2`);
|
|
18347
18672
|
}
|
|
18348
18673
|
async function stampCompositionDims(compositionDir, dims) {
|
|
18349
|
-
const metaPath =
|
|
18674
|
+
const metaPath = path11.join(compositionDir, "meta.json");
|
|
18350
18675
|
const rawMeta = await readFile6(metaPath, "utf8");
|
|
18351
18676
|
await writeFile2(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
|
|
18352
|
-
const htmlPath =
|
|
18677
|
+
const htmlPath = path11.join(compositionDir, "index.html");
|
|
18353
18678
|
const rawHtml = await readFile6(htmlPath, "utf8");
|
|
18354
18679
|
await writeFile2(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
|
|
18355
18680
|
}
|
|
@@ -18489,6 +18814,10 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18489
18814
|
args: {
|
|
18490
18815
|
file: { type: "positional", required: true, description: "Path to the reference video" },
|
|
18491
18816
|
out: { type: "string", description: "Output canvas path (default <video-dir>/<name>.video.canvas.json)" },
|
|
18817
|
+
slug: {
|
|
18818
|
+
type: "string",
|
|
18819
|
+
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
18820
|
+
},
|
|
18492
18821
|
frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
|
|
18493
18822
|
ambient: {
|
|
18494
18823
|
type: "boolean",
|
|
@@ -18515,11 +18844,19 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18515
18844
|
}
|
|
18516
18845
|
},
|
|
18517
18846
|
async run({ args }) {
|
|
18518
|
-
const videoPath =
|
|
18519
|
-
const base =
|
|
18520
|
-
const
|
|
18521
|
-
|
|
18522
|
-
|
|
18847
|
+
const videoPath = path11.resolve(String(args.file));
|
|
18848
|
+
const base = path11.basename(videoPath, path11.extname(videoPath));
|
|
18849
|
+
const slug = args.slug ? String(args.slug) : void 0;
|
|
18850
|
+
if (slug && !isValidScaffoldSlug(slug)) {
|
|
18851
|
+
process.stderr.write(
|
|
18852
|
+
`${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
|
|
18853
|
+
`
|
|
18854
|
+
);
|
|
18855
|
+
process.exit(2);
|
|
18856
|
+
}
|
|
18857
|
+
const outPath = args.out ? path11.resolve(String(args.out)) : slug ? path11.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path11.join(path11.dirname(videoPath), `${base}.video.canvas.json`);
|
|
18858
|
+
const outDir = path11.dirname(outPath);
|
|
18859
|
+
const blueprintPath = path11.join(outDir, "prompt.json");
|
|
18523
18860
|
const frames = args.frames === "reuse" ? "reuse" : "generate";
|
|
18524
18861
|
const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
|
|
18525
18862
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -18538,7 +18875,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18538
18875
|
shotCuts
|
|
18539
18876
|
});
|
|
18540
18877
|
const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
|
|
18541
|
-
await
|
|
18878
|
+
await mkdir2(outDir, { recursive: true });
|
|
18542
18879
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
18543
18880
|
await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
18544
18881
|
`, "utf8");
|
|
@@ -18559,10 +18896,10 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18559
18896
|
`
|
|
18560
18897
|
);
|
|
18561
18898
|
}
|
|
18562
|
-
const compositionDest =
|
|
18899
|
+
const compositionDest = path11.join(outDir, "video-overlay-composition");
|
|
18563
18900
|
await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
18564
18901
|
await stampCompositionDims(compositionDest, outDims);
|
|
18565
|
-
const indexPath =
|
|
18902
|
+
const indexPath = path11.join(compositionDest, "index.html");
|
|
18566
18903
|
const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
|
|
18567
18904
|
const indexHtml = await readFile6(indexPath, "utf8");
|
|
18568
18905
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
@@ -18578,9 +18915,9 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18578
18915
|
const opts = {
|
|
18579
18916
|
imageModel,
|
|
18580
18917
|
videoModel,
|
|
18581
|
-
overlayCompositionPath:
|
|
18582
|
-
captionsCompositionPath: captions.compositionPath ?
|
|
18583
|
-
blueprintPath:
|
|
18918
|
+
overlayCompositionPath: path11.relative(outDir, compositionDest),
|
|
18919
|
+
captionsCompositionPath: captions.compositionPath ? path11.relative(outDir, captions.compositionPath) : void 0,
|
|
18920
|
+
blueprintPath: path11.relative(outDir, blueprintPath),
|
|
18584
18921
|
frames,
|
|
18585
18922
|
ambient: Boolean(args.ambient),
|
|
18586
18923
|
...args.aspect ? { aspect: String(args.aspect) } : {},
|
|
@@ -18638,7 +18975,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18638
18975
|
run_estimated_credits: validation.estimatedCredits
|
|
18639
18976
|
},
|
|
18640
18977
|
checklist: {
|
|
18641
|
-
edit_prompt: `Edit ${
|
|
18978
|
+
edit_prompt: `Edit ${path11.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Every scene frame reads it via target_blueprint.`,
|
|
18642
18979
|
recurring_elements_to_supply: report.elements,
|
|
18643
18980
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
18644
18981
|
scene: d.scene,
|
|
@@ -18665,7 +19002,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18665
19002
|
|
|
18666
19003
|
// src/commands/canvas/set-prompt.ts
|
|
18667
19004
|
import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
|
|
18668
|
-
import
|
|
19005
|
+
import path12 from "path";
|
|
18669
19006
|
import { defineCommand as defineCommand91 } from "citty";
|
|
18670
19007
|
function setNodePrompt(canvas, nodeId, text) {
|
|
18671
19008
|
const nodes = canvas?.nodes;
|
|
@@ -18693,7 +19030,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18693
19030
|
"text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
|
|
18694
19031
|
},
|
|
18695
19032
|
async run({ args }) {
|
|
18696
|
-
const filePath =
|
|
19033
|
+
const filePath = path12.resolve(String(args.file));
|
|
18697
19034
|
let canvas;
|
|
18698
19035
|
try {
|
|
18699
19036
|
canvas = JSON.parse(await readFile7(filePath, "utf8"));
|
|
@@ -18703,7 +19040,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18703
19040
|
process.exit(2);
|
|
18704
19041
|
}
|
|
18705
19042
|
let text;
|
|
18706
|
-
if (args["text-file"]) text = await readFile7(
|
|
19043
|
+
if (args["text-file"]) text = await readFile7(path12.resolve(String(args["text-file"])), "utf8");
|
|
18707
19044
|
else if (args.text !== void 0) text = String(args.text);
|
|
18708
19045
|
else {
|
|
18709
19046
|
process.stderr.write(
|
|
@@ -18724,7 +19061,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18724
19061
|
process.exit(2);
|
|
18725
19062
|
return;
|
|
18726
19063
|
}
|
|
18727
|
-
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated,
|
|
19064
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path12.dirname(filePath)), defaultRegistry());
|
|
18728
19065
|
if (!validation.ok) {
|
|
18729
19066
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
18730
19067
|
`);
|
|
@@ -18740,7 +19077,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18740
19077
|
|
|
18741
19078
|
// src/commands/canvas/validate.ts
|
|
18742
19079
|
import { readFile as readFile8 } from "fs/promises";
|
|
18743
|
-
import
|
|
19080
|
+
import path13 from "path";
|
|
18744
19081
|
import { defineCommand as defineCommand92 } from "citty";
|
|
18745
19082
|
var validateCommand = defineCommand92({
|
|
18746
19083
|
meta: {
|
|
@@ -18749,7 +19086,7 @@ var validateCommand = defineCommand92({
|
|
|
18749
19086
|
},
|
|
18750
19087
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
18751
19088
|
async run({ args }) {
|
|
18752
|
-
const filePath =
|
|
19089
|
+
const filePath = path13.resolve(String(args.file));
|
|
18753
19090
|
const raw = await readFile8(filePath, "utf8");
|
|
18754
19091
|
let parsed;
|
|
18755
19092
|
try {
|
|
@@ -18760,7 +19097,7 @@ var validateCommand = defineCommand92({
|
|
|
18760
19097
|
`);
|
|
18761
19098
|
process.exit(2);
|
|
18762
19099
|
}
|
|
18763
|
-
parsed = resolveRelativeCanvasPaths(parsed,
|
|
19100
|
+
parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
|
|
18764
19101
|
const result = await validateCanvasDeep(parsed, defaultRegistry());
|
|
18765
19102
|
if (!result.ok) {
|
|
18766
19103
|
process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
|
|
@@ -18897,6 +19234,16 @@ registerSchema({
|
|
|
18897
19234
|
type: "string",
|
|
18898
19235
|
description: "Optional URL of the original reference ad",
|
|
18899
19236
|
required: false
|
|
19237
|
+
},
|
|
19238
|
+
slug: {
|
|
19239
|
+
type: "string",
|
|
19240
|
+
description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
|
|
19241
|
+
required: false
|
|
19242
|
+
},
|
|
19243
|
+
runId: {
|
|
19244
|
+
type: "string",
|
|
19245
|
+
description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
|
|
19246
|
+
required: false
|
|
18900
19247
|
}
|
|
18901
19248
|
}
|
|
18902
19249
|
});
|
|
@@ -18906,6 +19253,13 @@ function detectCreativeContentType(filePath) {
|
|
|
18906
19253
|
unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
|
|
18907
19254
|
});
|
|
18908
19255
|
}
|
|
19256
|
+
function chatIdFromEnv() {
|
|
19257
|
+
try {
|
|
19258
|
+
return getEnv().BAKER_CHAT_ID || void 0;
|
|
19259
|
+
} catch {
|
|
19260
|
+
return void 0;
|
|
19261
|
+
}
|
|
19262
|
+
}
|
|
18909
19263
|
function parseOptionalUrl(value) {
|
|
18910
19264
|
if (value === void 0 || value.trim() === "") {
|
|
18911
19265
|
return void 0;
|
|
@@ -18936,7 +19290,11 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
|
|
|
18936
19290
|
return publishImageAsCreative(deps, {
|
|
18937
19291
|
imageId: upload.imageId,
|
|
18938
19292
|
title,
|
|
18939
|
-
sourceReferenceUrl
|
|
19293
|
+
sourceReferenceUrl,
|
|
19294
|
+
slug: args.slug,
|
|
19295
|
+
runId: args.runId,
|
|
19296
|
+
// Attribute the publish to the driving chat (injected by the bridge).
|
|
19297
|
+
chatId: chatIdFromEnv()
|
|
18940
19298
|
});
|
|
18941
19299
|
}
|
|
18942
19300
|
var publishCommand = defineCommand94({
|
|
@@ -18952,6 +19310,16 @@ var publishCommand = defineCommand94({
|
|
|
18952
19310
|
type: "string",
|
|
18953
19311
|
description: "Optional URL of the original reference ad",
|
|
18954
19312
|
required: false
|
|
19313
|
+
},
|
|
19314
|
+
slug: {
|
|
19315
|
+
type: "string",
|
|
19316
|
+
description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
|
|
19317
|
+
required: false
|
|
19318
|
+
},
|
|
19319
|
+
runId: {
|
|
19320
|
+
type: "string",
|
|
19321
|
+
description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
|
|
19322
|
+
required: false
|
|
18955
19323
|
}
|
|
18956
19324
|
},
|
|
18957
19325
|
run: async ({ args }) => {
|
|
@@ -18970,7 +19338,9 @@ var publishCommand = defineCommand94({
|
|
|
18970
19338
|
file,
|
|
18971
19339
|
title,
|
|
18972
19340
|
context: args.context,
|
|
18973
|
-
sourceReferenceUrl: args.sourceReferenceUrl
|
|
19341
|
+
sourceReferenceUrl: args.sourceReferenceUrl,
|
|
19342
|
+
slug: args.slug,
|
|
19343
|
+
runId: args.runId
|
|
18974
19344
|
});
|
|
18975
19345
|
writeJson({ ok: true, data });
|
|
18976
19346
|
} catch (err) {
|
|
@@ -19868,9 +20238,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
19868
20238
|
}
|
|
19869
20239
|
return readFile10(pathOrUrl);
|
|
19870
20240
|
}
|
|
19871
|
-
async function isDirectory(
|
|
20241
|
+
async function isDirectory(path14) {
|
|
19872
20242
|
try {
|
|
19873
|
-
const s = await stat2(
|
|
20243
|
+
const s = await stat2(path14);
|
|
19874
20244
|
return s.isDirectory();
|
|
19875
20245
|
} catch {
|
|
19876
20246
|
return false;
|
|
@@ -23932,130 +24302,11 @@ var schemaCommand = defineCommand147({
|
|
|
23932
24302
|
}
|
|
23933
24303
|
});
|
|
23934
24304
|
|
|
23935
|
-
// src/commands/tags/index.ts
|
|
23936
|
-
import { defineCommand as defineCommand148 } from "citty";
|
|
23937
|
-
|
|
23938
|
-
// src/commands/tags/shared.ts
|
|
23939
|
-
function failApi3(err) {
|
|
23940
|
-
if (err instanceof ApiError) {
|
|
23941
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
23942
|
-
process.exit(1);
|
|
23943
|
-
}
|
|
23944
|
-
if (err instanceof Error) {
|
|
23945
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: err.message } });
|
|
23946
|
-
process.exit(1);
|
|
23947
|
-
}
|
|
23948
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
23949
|
-
process.exit(1);
|
|
23950
|
-
}
|
|
23951
|
-
function renderConfigValue(value) {
|
|
23952
|
-
return value.includes("\n") ? value.replace(/\n/g, "\n ") : value;
|
|
23953
|
-
}
|
|
23954
|
-
function renderEffectiveEntry(entry) {
|
|
23955
|
-
const parts = [entry.ref, entry.type];
|
|
23956
|
-
if (entry.identifier !== void 0) {
|
|
23957
|
-
parts.push(entry.identifier);
|
|
23958
|
-
}
|
|
23959
|
-
if (entry.staged !== void 0) {
|
|
23960
|
-
parts.push(`[staged: ${entry.staged}]`);
|
|
23961
|
-
}
|
|
23962
|
-
const secretBits = [
|
|
23963
|
-
...entry.secretsSet.map((field) => `${field} \u2713 set`),
|
|
23964
|
-
...entry.secretsPending.map((field) => `${field} \u23F3 pending`)
|
|
23965
|
-
];
|
|
23966
|
-
if (secretBits.length > 0) {
|
|
23967
|
-
parts.push(`[secrets: ${secretBits.join(", ")}]`);
|
|
23968
|
-
}
|
|
23969
|
-
const header = parts.join(" ");
|
|
23970
|
-
const identifyingField = TAG_IDENTIFYING_FIELD[entry.type];
|
|
23971
|
-
const configLines = Object.entries(entry.config).filter(([key]) => key !== identifyingField).map(([key, value]) => ` ${key}: ${renderConfigValue(value)}`);
|
|
23972
|
-
return configLines.length > 0 ? `${header}
|
|
23973
|
-
${configLines.join("\n")}` : header;
|
|
23974
|
-
}
|
|
23975
|
-
|
|
23976
|
-
// src/commands/tags/index.ts
|
|
23977
|
-
registerSchema({
|
|
23978
|
-
command: "tags.list",
|
|
23979
|
-
description: "Effective marketing tags for this chat: production tags overlaid with the changes staged in this chat. Prints each tag's readable config in full (secrets are never included) \u2014 e.g. the Clarity projectId, GA4 measurementId, or the entire custom `code` snippet \u2014 so reuse a stored value to pre-fill a follow-up change instead of asking the user for something we already have. The printed refs (tag ids or tag_temp_*) are exactly what flow side-effect tagIds should reference. Read-only \u2014 every tag change (create, edit, delete) goes through the request_tag_input approval tool.",
|
|
23980
|
-
args: {
|
|
23981
|
-
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
|
|
23982
|
-
}
|
|
23983
|
-
});
|
|
23984
|
-
async function listTags(json) {
|
|
23985
|
-
try {
|
|
23986
|
-
const chatId = requireChatId();
|
|
23987
|
-
const response = await apiPost("/api/tags/list", { chatId });
|
|
23988
|
-
if (json) {
|
|
23989
|
-
writeJson({ ok: true, data: response });
|
|
23990
|
-
return;
|
|
23991
|
-
}
|
|
23992
|
-
if (response.tags.length === 0) {
|
|
23993
|
-
process.stdout.write("No tags configured. Propose one with the request_tag_input tool (baker_ui).\n");
|
|
23994
|
-
return;
|
|
23995
|
-
}
|
|
23996
|
-
process.stdout.write(`${response.tags.map(renderEffectiveEntry).join("\n")}
|
|
23997
|
-
`);
|
|
23998
|
-
} catch (err) {
|
|
23999
|
-
failApi3(err);
|
|
24000
|
-
}
|
|
24001
|
-
}
|
|
24002
|
-
var listCommand7 = defineCommand148({
|
|
24003
|
-
meta: {
|
|
24004
|
-
name: "list",
|
|
24005
|
-
description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
|
|
24006
|
-
},
|
|
24007
|
-
args: { json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" } },
|
|
24008
|
-
run: async ({ args }) => {
|
|
24009
|
-
await listTags(args.json === true);
|
|
24010
|
-
}
|
|
24011
|
-
});
|
|
24012
|
-
async function listDraft3() {
|
|
24013
|
-
try {
|
|
24014
|
-
const chatId = requireChatId();
|
|
24015
|
-
const response = await apiPost("/api/tags/draft", { chatId });
|
|
24016
|
-
writeJson({ ok: true, data: response });
|
|
24017
|
-
} catch (err) {
|
|
24018
|
-
failApi3(err);
|
|
24019
|
-
}
|
|
24020
|
-
}
|
|
24021
|
-
var draftCommand3 = defineCommand148({
|
|
24022
|
-
meta: {
|
|
24023
|
-
name: "draft",
|
|
24024
|
-
description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create)."
|
|
24025
|
-
},
|
|
24026
|
-
run: async () => {
|
|
24027
|
-
await listDraft3();
|
|
24028
|
-
}
|
|
24029
|
-
});
|
|
24030
|
-
var tagsCommand3 = defineCommand148({
|
|
24031
|
-
meta: {
|
|
24032
|
-
name: "tags",
|
|
24033
|
-
description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
|
|
24034
|
-
|
|
24035
|
-
This command is READ-ONLY. Every tag change \u2014 create, edit, or delete \u2014 goes through the request_tag_input tool (baker_ui MCP server): propose one or more changes (each becomes a tab in one approval form), pre-fill the non-secret fields you know, and the user reviews, fills secrets, and approves or skips each. Secret values (accessToken, apiSecret, authorizationToken, apiKey, conversionToken, OAuth connections) never pass through the CLI or the chat.
|
|
24036
|
-
|
|
24037
|
-
Refs: \`baker tags list\` prints each tag's ref \u2014 a real tag id, or tag_temp_* for creates staged in this chat. Use these refs as flow side-effect tagIds; they keep resolving after publish.
|
|
24038
|
-
|
|
24039
|
-
\`baker tags list\` prints each tag's readable config in full (secrets excluded) \u2014 the Clarity projectId, GA4 measurementId, the whole custom \`code\` snippet, etc. Reuse a stored value to pre-fill a follow-up change instead of asking the user for something already installed.
|
|
24040
|
-
|
|
24041
|
-
Examples:
|
|
24042
|
-
baker tags list # production + staged, full readable config + secret status
|
|
24043
|
-
baker tags draft # review the staged changes awaiting publish`
|
|
24044
|
-
},
|
|
24045
|
-
subCommands: {
|
|
24046
|
-
list: listCommand7,
|
|
24047
|
-
draft: draftCommand3
|
|
24048
|
-
},
|
|
24049
|
-
run: async () => {
|
|
24050
|
-
await listTags(false);
|
|
24051
|
-
}
|
|
24052
|
-
});
|
|
24053
|
-
|
|
24054
24305
|
// src/commands/testimonials/index.ts
|
|
24055
|
-
import { defineCommand as
|
|
24306
|
+
import { defineCommand as defineCommand151 } from "citty";
|
|
24056
24307
|
|
|
24057
24308
|
// src/commands/testimonials/get.ts
|
|
24058
|
-
import { defineCommand as
|
|
24309
|
+
import { defineCommand as defineCommand148 } from "citty";
|
|
24059
24310
|
registerSchema({
|
|
24060
24311
|
command: "testimonials.get",
|
|
24061
24312
|
description: "Get a single testimonial by ID",
|
|
@@ -24063,7 +24314,7 @@ registerSchema({
|
|
|
24063
24314
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
24064
24315
|
}
|
|
24065
24316
|
});
|
|
24066
|
-
var getCommand4 =
|
|
24317
|
+
var getCommand4 = defineCommand148({
|
|
24067
24318
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
24068
24319
|
args: {
|
|
24069
24320
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -24100,7 +24351,7 @@ var getCommand4 = defineCommand149({
|
|
|
24100
24351
|
});
|
|
24101
24352
|
|
|
24102
24353
|
// src/commands/testimonials/list.ts
|
|
24103
|
-
import { defineCommand as
|
|
24354
|
+
import { defineCommand as defineCommand149 } from "citty";
|
|
24104
24355
|
registerSchema({
|
|
24105
24356
|
command: "testimonials.list",
|
|
24106
24357
|
description: "List testimonials with optional filters.",
|
|
@@ -24130,7 +24381,7 @@ registerSchema({
|
|
|
24130
24381
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
24131
24382
|
}
|
|
24132
24383
|
});
|
|
24133
|
-
var
|
|
24384
|
+
var listCommand7 = defineCommand149({
|
|
24134
24385
|
meta: {
|
|
24135
24386
|
name: "list",
|
|
24136
24387
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -24179,7 +24430,7 @@ var listCommand8 = defineCommand150({
|
|
|
24179
24430
|
});
|
|
24180
24431
|
|
|
24181
24432
|
// src/commands/testimonials/search.ts
|
|
24182
|
-
import { defineCommand as
|
|
24433
|
+
import { defineCommand as defineCommand150 } from "citty";
|
|
24183
24434
|
registerSchema({
|
|
24184
24435
|
command: "testimonials.search",
|
|
24185
24436
|
description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
|
|
@@ -24210,7 +24461,7 @@ registerSchema({
|
|
|
24210
24461
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
24211
24462
|
}
|
|
24212
24463
|
});
|
|
24213
|
-
var searchCommand2 =
|
|
24464
|
+
var searchCommand2 = defineCommand150({
|
|
24214
24465
|
meta: {
|
|
24215
24466
|
name: "search",
|
|
24216
24467
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -24281,10 +24532,10 @@ var searchCommand2 = defineCommand151({
|
|
|
24281
24532
|
});
|
|
24282
24533
|
|
|
24283
24534
|
// src/commands/testimonials/tags.ts
|
|
24284
|
-
var
|
|
24535
|
+
var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
24285
24536
|
|
|
24286
24537
|
// src/commands/testimonials/index.ts
|
|
24287
|
-
var testimonialsCommand =
|
|
24538
|
+
var testimonialsCommand = defineCommand151({
|
|
24288
24539
|
meta: {
|
|
24289
24540
|
name: "testimonials",
|
|
24290
24541
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -24299,16 +24550,16 @@ Examples:
|
|
|
24299
24550
|
subCommands: {
|
|
24300
24551
|
get: getCommand4,
|
|
24301
24552
|
search: searchCommand2,
|
|
24302
|
-
list:
|
|
24303
|
-
tags:
|
|
24553
|
+
list: listCommand7,
|
|
24554
|
+
tags: tagsCommand3
|
|
24304
24555
|
}
|
|
24305
24556
|
});
|
|
24306
24557
|
|
|
24307
24558
|
// src/commands/videos/index.ts
|
|
24308
|
-
import { defineCommand as
|
|
24559
|
+
import { defineCommand as defineCommand156 } from "citty";
|
|
24309
24560
|
|
|
24310
24561
|
// src/commands/videos/delete.ts
|
|
24311
|
-
import { defineCommand as
|
|
24562
|
+
import { defineCommand as defineCommand152 } from "citty";
|
|
24312
24563
|
registerSchema({
|
|
24313
24564
|
command: "videos.delete",
|
|
24314
24565
|
description: "Delete a video by ID",
|
|
@@ -24322,7 +24573,7 @@ registerSchema({
|
|
|
24322
24573
|
}
|
|
24323
24574
|
}
|
|
24324
24575
|
});
|
|
24325
|
-
var deleteCommand3 =
|
|
24576
|
+
var deleteCommand3 = defineCommand152({
|
|
24326
24577
|
meta: {
|
|
24327
24578
|
name: "delete",
|
|
24328
24579
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -24363,7 +24614,7 @@ var deleteCommand3 = defineCommand153({
|
|
|
24363
24614
|
});
|
|
24364
24615
|
|
|
24365
24616
|
// src/commands/videos/get.ts
|
|
24366
|
-
import { defineCommand as
|
|
24617
|
+
import { defineCommand as defineCommand153 } from "citty";
|
|
24367
24618
|
registerSchema({
|
|
24368
24619
|
command: "videos.get",
|
|
24369
24620
|
description: "Get a single video by ID",
|
|
@@ -24371,7 +24622,7 @@ registerSchema({
|
|
|
24371
24622
|
id: { type: "string", description: "Video ID", required: true }
|
|
24372
24623
|
}
|
|
24373
24624
|
});
|
|
24374
|
-
var getCommand5 =
|
|
24625
|
+
var getCommand5 = defineCommand153({
|
|
24375
24626
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
24376
24627
|
args: {
|
|
24377
24628
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -24408,7 +24659,7 @@ var getCommand5 = defineCommand154({
|
|
|
24408
24659
|
});
|
|
24409
24660
|
|
|
24410
24661
|
// src/commands/videos/search.ts
|
|
24411
|
-
import { defineCommand as
|
|
24662
|
+
import { defineCommand as defineCommand154 } from "citty";
|
|
24412
24663
|
registerSchema({
|
|
24413
24664
|
command: "videos.search",
|
|
24414
24665
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -24418,7 +24669,7 @@ registerSchema({
|
|
|
24418
24669
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
24419
24670
|
}
|
|
24420
24671
|
});
|
|
24421
|
-
var searchCommand3 =
|
|
24672
|
+
var searchCommand3 = defineCommand154({
|
|
24422
24673
|
meta: {
|
|
24423
24674
|
name: "search",
|
|
24424
24675
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -24465,12 +24716,12 @@ var searchCommand3 = defineCommand155({
|
|
|
24465
24716
|
});
|
|
24466
24717
|
|
|
24467
24718
|
// src/commands/videos/tags.ts
|
|
24468
|
-
var
|
|
24719
|
+
var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
24469
24720
|
|
|
24470
24721
|
// src/commands/videos/upload.ts
|
|
24471
24722
|
import { readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
24472
24723
|
import { extname as extname3 } from "path";
|
|
24473
|
-
import { defineCommand as
|
|
24724
|
+
import { defineCommand as defineCommand155 } from "citty";
|
|
24474
24725
|
var MIME_MAP = {
|
|
24475
24726
|
".mp4": "video/mp4",
|
|
24476
24727
|
".mov": "video/quicktime",
|
|
@@ -24504,7 +24755,7 @@ function detectContentType(filePath) {
|
|
|
24504
24755
|
}
|
|
24505
24756
|
return mime;
|
|
24506
24757
|
}
|
|
24507
|
-
var uploadCommand2 =
|
|
24758
|
+
var uploadCommand2 = defineCommand155({
|
|
24508
24759
|
meta: {
|
|
24509
24760
|
name: "upload",
|
|
24510
24761
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -24558,7 +24809,7 @@ var uploadCommand2 = defineCommand156({
|
|
|
24558
24809
|
});
|
|
24559
24810
|
|
|
24560
24811
|
// src/commands/videos/index.ts
|
|
24561
|
-
var videosCommand =
|
|
24812
|
+
var videosCommand = defineCommand156({
|
|
24562
24813
|
meta: {
|
|
24563
24814
|
name: "videos",
|
|
24564
24815
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -24576,15 +24827,15 @@ Examples:
|
|
|
24576
24827
|
search: searchCommand3,
|
|
24577
24828
|
upload: uploadCommand2,
|
|
24578
24829
|
delete: deleteCommand3,
|
|
24579
|
-
tags:
|
|
24830
|
+
tags: tagsCommand4
|
|
24580
24831
|
}
|
|
24581
24832
|
});
|
|
24582
24833
|
|
|
24583
24834
|
// src/commands/winning-ads/index.ts
|
|
24584
|
-
import { defineCommand as
|
|
24835
|
+
import { defineCommand as defineCommand159 } from "citty";
|
|
24585
24836
|
|
|
24586
24837
|
// src/commands/winning-ads/advertisers.ts
|
|
24587
|
-
import { defineCommand as
|
|
24838
|
+
import { defineCommand as defineCommand157 } from "citty";
|
|
24588
24839
|
registerSchema({
|
|
24589
24840
|
command: "winning-ads.advertisers",
|
|
24590
24841
|
description: "Resolve a brand name to advertiser_id(s) in the ad-dna corpus \u2014 to find your OWN advertiser (to --exclude-advertiser) or a competitor (to --advertiser-id).",
|
|
@@ -24597,7 +24848,7 @@ registerSchema({
|
|
|
24597
24848
|
function identity(record) {
|
|
24598
24849
|
return record;
|
|
24599
24850
|
}
|
|
24600
|
-
var advertisersCommand2 =
|
|
24851
|
+
var advertisersCommand2 = defineCommand157({
|
|
24601
24852
|
meta: {
|
|
24602
24853
|
name: "advertisers",
|
|
24603
24854
|
description: 'Resolve a brand name to advertiser_id(s). Use it to find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id. Example: baker winning-ads advertisers "Deel" --output md'
|
|
@@ -24648,7 +24899,7 @@ var advertisersCommand2 = defineCommand158({
|
|
|
24648
24899
|
});
|
|
24649
24900
|
|
|
24650
24901
|
// src/commands/winning-ads/search.ts
|
|
24651
|
-
import { defineCommand as
|
|
24902
|
+
import { defineCommand as defineCommand158 } from "citty";
|
|
24652
24903
|
registerSchema({
|
|
24653
24904
|
command: "winning-ads.search",
|
|
24654
24905
|
description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
|
|
@@ -24756,7 +25007,7 @@ function buildSearchBody(args) {
|
|
|
24756
25007
|
}
|
|
24757
25008
|
return body;
|
|
24758
25009
|
}
|
|
24759
|
-
var searchCommand4 =
|
|
25010
|
+
var searchCommand4 = defineCommand158({
|
|
24760
25011
|
meta: {
|
|
24761
25012
|
name: "search",
|
|
24762
25013
|
description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
|
|
@@ -24868,7 +25119,7 @@ var searchCommand4 = defineCommand159({
|
|
|
24868
25119
|
});
|
|
24869
25120
|
|
|
24870
25121
|
// src/commands/winning-ads/index.ts
|
|
24871
|
-
var winningAdsCommand =
|
|
25122
|
+
var winningAdsCommand = defineCommand159({
|
|
24872
25123
|
meta: {
|
|
24873
25124
|
name: "winning-ads",
|
|
24874
25125
|
description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
|
|
@@ -24908,11 +25159,11 @@ function getCliVersion() {
|
|
|
24908
25159
|
}
|
|
24909
25160
|
|
|
24910
25161
|
// src/cli.ts
|
|
24911
|
-
var main =
|
|
25162
|
+
var main = defineCommand160({
|
|
24912
25163
|
meta: {
|
|
24913
25164
|
name: "baker",
|
|
24914
25165
|
version: getCliVersion(),
|
|
24915
|
-
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions,
|
|
25166
|
+
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, and ad platform data in Baker.
|
|
24916
25167
|
|
|
24917
25168
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
24918
25169
|
Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
|
|
@@ -24932,7 +25183,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
24932
25183
|
videos: videosCommand,
|
|
24933
25184
|
testimonials: testimonialsCommand,
|
|
24934
25185
|
canvas: canvasCommand,
|
|
24935
|
-
tags: tagsCommand3,
|
|
24936
25186
|
"winning-ads": winningAdsCommand,
|
|
24937
25187
|
mcp: mcpCommand,
|
|
24938
25188
|
schema: schemaCommand
|